> ## Documentation Index
> Fetch the complete documentation index at: https://phaseo.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Build with the Rust Agent SDK

> Create a synchronous Rust agent that calls a local tool through Phaseo Gateway.

Use this guide to build a small tool-using agent and inspect its completed run.

## Define a tool

```rust theme={null}
use phaseo_agent::{define_tool, Tool};
use serde_json::json;

let lookup = define_tool(Tool::new(
    "lookup_docs",
    "Look up a Phaseo documentation topic",
    json!({
        "type": "object",
        "properties": {
            "topic": { "type": "string" }
        },
        "required": ["topic"]
    }),
    |input, context| {
        Ok(json!({
            "topic": input["topic"],
            "run_id": context.run_id,
            "found": true
        }))
    },
));
```

The closure runs locally. Its `RuntimeContext` includes the run ID, agent ID, step index, application context, and original tool call.

## Create the agent

```rust theme={null}
use phaseo_agent::{create_agent, AgentDefinition};

let agent = create_agent(
    AgentDefinition::new("docs-agent", "openai/gpt-5.6-sol")
        .instructions("Use lookup_docs when it helps. Finish with a concise answer.")
        .max_steps(6)
        .tool(lookup),
);
```

## Run through Phaseo Gateway

```rust theme={null}
use phaseo_agent::{create_gateway_agent_client, RunOptions};

let mut client = create_gateway_agent_client("openai/gpt-5.6-sol")?;
let mut options = RunOptions::new("Explain when to use routing presets.");
options.context = serde_json::json!({
    "workspace": "docs"
});

let result = agent.run(&mut client, options)?;
println!("{}", result.output);
```

## Complete example

```rust theme={null}
use phaseo_agent::{
    create_agent, create_gateway_agent_client, define_tool, AgentDefinition,
    RunOptions, Tool,
};
use serde_json::json;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let lookup = define_tool(Tool::new(
        "lookup_docs",
        "Look up a Phaseo documentation topic",
        json!({
            "type": "object",
            "properties": {
                "topic": { "type": "string" }
            },
            "required": ["topic"]
        }),
        |input, context| {
            Ok(json!({
                "topic": input["topic"],
                "run_id": context.run_id,
                "found": true
            }))
        },
    ));

    let agent = create_agent(
        AgentDefinition::new("docs-agent", "openai/gpt-5.6-sol")
            .instructions("Use lookup_docs when helpful. Answer concisely.")
            .max_steps(6)
            .tool(lookup),
    );

    let mut client = create_gateway_agent_client("openai/gpt-5.6-sol")?;
    let result = agent.run(
        &mut client,
        RunOptions::new("Explain when to use routing presets."),
    )?;

    println!("{}", result.output);
    println!("steps: {}", result.run.step_count);
    println!("tokens: {}", result.usage.total_tokens);
    Ok(())
}
```

## Run state

`RunResult` contains:

* `run`: status, IDs, effective model, step limit, context, and pause state
* `steps`: each model turn, request ID, provider, model, finish reason, tool calls, and usage
* `messages`: the complete model and tool message history
* `output`: the final output value
* `usage`: aggregate token values and any cost supplied by the model client

## Current execution model

Rust Agent SDK runs are synchronous. Local tools execute one at a time. Use an application worker thread or task boundary when a run should not block a request handler.

## Next

* [Tools and approvals](./agent-sdk-tools)
* [Persist and resume runs](./agent-sdk-state-and-approval)
* [Events, retries, and errors](./agent-sdk-events-and-errors)
