Build an Agent
Use this when you need a production integration path with tool registry, persistence, and protocol endpoints.
Prerequisites
- One model provider key is configured (for example
OPENAI_API_KEYforgpt-4o-mini). - You have at least one tool implementation.
- You know whether the deployment needs persistent storage.
Steps
- Define tool set.
.with_tools(tool_map([SearchTool, SummarizeTool]))
- Define agent behavior.
.with_agent_spec(AgentDefinitionSpec::local_with_id(
"assistant",
AgentDefinition::new("gpt-4o-mini")
.with_system_prompt("You are a helpful assistant.")
.with_max_rounds(10)
.with_allowed_tools(vec!["search".to_string(), "summarize".to_string()]),
))
- Wire persistence.
.with_agent_state_store(store.clone())
- Execute via
run_stream.
let run = os.run_stream(RunRequest {
agent_id: "assistant".to_string(),
thread_id: Some("thread-1".to_string()),
run_id: None,
parent_run_id: None,
parent_thread_id: None,
resource_id: None,
origin: RunOrigin::default(),
state: None,
messages: vec![Message::user("hello")],
initial_decisions: vec![],
source_mailbox_entry_id: None,
}).await?;
- Consume stream and inspect terminal state.
let mut events = run.events;
while let Some(event) = events.next().await {
if let AgentEvent::RunFinish { termination, .. } = event {
println!("termination = {:?}", termination);
}
}
Verify
- You receive at least one
RunStartand oneRunFinishevent. RunFinish.terminationmatches your expectation (NaturalEnd,Stopped,Error, etc.).- If persistence is enabled, thread can be reloaded from store after run.
After The Agent Is Built
Once you have:
let os = AgentOsBuilder::new()
.with_tools(...)
.with_agent_spec(...)
.build()?;
you normally choose one of these runtime modes:
- In-process execution: call
os.run_stream(RunRequest { ... }).await? - Long-lived backend service: put
Arc<AgentOs>into server state and expose HTTP protocol routes - Example/starter backend: reuse the same builder pattern in a dedicated binary and let frontend clients connect over AI SDK or AG-UI
The important point is that AgentDefinition creation alone does not “start” anything. The run starts only when:
- your code calls
run_stream(...), or - an HTTP route receives a request and delegates to
AgentOs
Common Errors
- Model/provider mismatch: Use a model id compatible with the provider key you exported.
- Tool unavailable:
Ensure tool id is registered and included in
allowed_toolsif whitelist is enabled. - Empty runs with no meaningful output:
Confirm user message is appended in
RunRequest.messages.
Related Example
examples/ai-sdk-starter/README.mdis the fastest browser-facing backend integrationexamples/copilotkit-starter/README.mdshows the same runtime exposed through AG-UI with richer UI state
Key Files
examples/src/starter_backend/mod.rscrates/tirea-agentos/src/composition/agent_definition.rscrates/tirea-agentos/src/composition/builder.rscrates/tirea-agentos-server/src/main.rs