First Agent
Run one agent end-to-end and inspect the final result.
Prerequisites
Section titled “Prerequisites”[dependencies]awaken = { git = "https://github.com/AwakenWorks/awaken" }tokio = { version = "1", features = ["full"] }async-trait = "0.1"serde_json = "1"Set one model provider key before running:
# OpenAI-compatible models (for gpt-4o-mini)export OPENAI_API_KEY=<your-key>
# Or DeepSeek modelsexport DEEPSEEK_API_KEY=<your-key>1. Create src/main.rs
Section titled “1. Create src/main.rs”use std::sync::Arc;use serde_json::{json, Value};use async_trait::async_trait;use awaken::contract::tool::{Tool, ToolDescriptor, ToolResult, ToolOutput, ToolError, ToolCallContext};use awaken::contract::message::Message;use awaken::engine::GenaiExecutor;use awaken::registry_spec::AgentSpec;use awaken::registry_spec::ModelSpec;use awaken::{AgentRuntimeBuilder, RunActivation};
struct EchoTool;
#[async_trait]impl Tool for EchoTool { fn descriptor(&self) -> ToolDescriptor { ToolDescriptor::new("echo", "Echo", "Echo input back to the caller") .with_parameters(json!({ "type": "object", "properties": { "text": { "type": "string" } }, "required": ["text"] })) }
async fn execute( &self, args: Value, _ctx: &ToolCallContext, ) -> Result<ToolOutput, ToolError> { let text = args["text"].as_str().unwrap_or_default(); Ok(ToolResult::success("echo", json!({ "echoed": text })).into()) }}
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let agent_spec = AgentSpec::new("assistant") .with_model_id("gpt-4o-mini") .with_system_prompt("You are a helpful assistant. Use the echo tool when asked.") .with_max_rounds(5);
let runtime = AgentRuntimeBuilder::new() .with_agent_spec(agent_spec) .with_tool("echo", Arc::new(EchoTool)) .with_provider("openai", Arc::new(GenaiExecutor::new())) .with_model(ModelSpec::new("gpt-4o-mini", "openai", "gpt-4o-mini")) .build()?;
let request = RunActivation::new( "thread-1", vec![Message::user("Say hello using the echo tool")], ) .with_agent_id("assistant");
// This tutorial only needs the final result. Use run(..., sink) when // streaming events to SSE, WebSocket, protocol adapters, or tests. let result = runtime.run_to_completion(request).await?; println!("response: {}", result.response); println!("termination: {:?}", result.termination);
Ok(())}2. Run
Section titled “2. Run”cargo run3. Verify
Section titled “3. Verify”Expected output includes:
response: ...termination: NaturalEnd
What You Created
Section titled “What You Created”This example creates an in-process AgentRuntime and runs one request immediately.
The core object is:
let runtime = AgentRuntimeBuilder::new() .with_agent_spec(agent_spec) .with_tool("echo", Arc::new(EchoTool)) .with_provider("openai", Arc::new(GenaiExecutor::new())) .with_model(ModelSpec::new("gpt-4o-mini", "openai", "gpt-4o-mini")) .build()?;After that, the normal entry point is:
let result = runtime.run_to_completion(request).await?;Common usage patterns:
- one-shot CLI program: construct
RunActivation, callruntime.run_to_completion(...), print the result - application service: use
runtime.run(...)with anEventSinkwhen callers need streaming events - HTTP server: store
Arc<AgentRuntime>in app state and expose protocol routes
Alternative: load the agent from config
Section titled “Alternative: load the agent from config”The example above bakes system_prompt, model_id, and max_rounds into Rust. That’s the simplest path for a one-shot CLI. For any longer-running agent — anywhere you want to tune the prompt without recompiling — move the spec into config.
Keep EchoTool and the provider in code, drop with_agent_spec:
let runtime = AgentRuntimeBuilder::new() .with_tool("echo", Arc::new(EchoTool)) .with_provider("openai", Arc::new(GenaiExecutor::new())) .with_model(ModelSpec::new("gpt-4o-mini", "openai", "gpt-4o-mini")) .build()?; // agent "assistant" will be resolved from the config snapshotThen expose HTTP/SSE and PUT the agent spec once:
curl -sS -X PUT http://localhost:3000/v1/config/agents/assistant \ -H 'content-type: application/json' \ -d '{ "id": "assistant", "model_id": "gpt-4o-mini", "system_prompt": "You are a helpful assistant. Use the echo tool when asked.", "max_rounds": 5 }'To tweak the prompt later, just PUT the same id with a new system_prompt. The next POST /v1/runs reads the new snapshot — no rebuild, no restart. See Hot-Tune Prompts for the full loop.
Which Doc To Read Next
Section titled “Which Doc To Read Next”Use the next page based on what you want:
- add typed state and stateful tools: First Tool
- learn how events map to the agent loop: Events
- expose the agent over HTTP: Expose HTTP SSE
Common Errors
Section titled “Common Errors”- Model/provider mismatch:
gpt-4o-minirequires a compatible OpenAI-style provider setup. - Missing key: set
OPENAI_API_KEYorDEEPSEEK_API_KEYbeforecargo run. - Tool not selected: ensure the prompt explicitly asks to use
echo. - Early termination: check that
with_max_roundsis high enough for the model to complete.