# Agents

> An agent packages a graph as a reusable, named pattern.

An agent packages a graph as a reusable pattern. You implement the `Agent` trait to define a named behavior that can be registered with the sessions layer, persisted, and shared across your application.

```rust
use polaris_ai::agent::Agent;
use polaris_ai::graph::Graph;
use polaris_ai::system::system;


#[system]
async fn summarize() -> String {
    "A short summary".into()
}


#[system]
async fn evaluate(summary: polaris_ai::system::param::Out<String>) -> usize {
    summary.len()
}


struct SummarizeAgent;


impl Agent for SummarizeAgent {
    fn build(&self, graph: &mut Graph) {
        graph
            .add_system(summarize)
            .add_system(evaluate);
    }


    fn name(&self) -> &'static str {
        "SummarizeAgent"
    }
}
```

Implement `build` and `name`; override `setup` when you need session initialization. `to_graph` is provided for you.

## `build`

`build(&self, graph: &mut Graph)` constructs the graph that defines the agent’s behavior. This is called once when the agent is registered with the server. Everything you have seen on the [Graphs](/docs/polaris/core-concepts/graphs.md) page applies here: you add systems, branches, loops, and parallel sections to the `graph` argument.

Because `build` receives `&self`, you can store configuration on the agent struct and use it to vary the graph structure at registration time.

## `name`

`name()` returns a stable `&'static str` identifier for the agent type. The sessions layer uses this name to associate sessions with the correct agent, so it must not change between releases if you are persisting sessions.

## `setup`

`setup(&self, ctx: &mut SystemContext)` runs before the first turn of a session. You can read configuration from the context, resolve an LLM handle, or insert session-scoped resources that your systems will need. The default implementation is a no-op, so you only override it when your agent needs initialization beyond what plugins provide.

```rust
impl Agent for ReActAgent {
    fn setup(&self, ctx: &mut SystemContext<'static>) -> Result<(), SetupError> {
        let config = ctx.get_resource::<AgentConfig>().map_err(SetupError::new)?;
        let llm = ctx
            .get_resource::<ModelRegistry>()
            .map_err(SetupError::new)?
            .llm(&config.model_id)
            .map_err(SetupError::new)?;
        ctx.insert(AgentLlm(llm));
        Ok(())
    }


    // ...
}
```

## `to_graph`

`to_graph(&self) -> Graph` is a convenience method that creates a new `Graph`, calls `build`, and returns it. You do not need to implement this yourself. It is useful in tests or when you need the graph as a standalone value.

```rust
let agent = SummarizeAgent;
let graph = agent.to_graph();
assert_eq!(graph.node_count(), 2);
```

## The ReAct skeleton

A more realistic agent uses the graph primitives together. Here is the ReAct pattern: loop through LLM calls, branch on whether the model wants to use tools, and exit when it produces a final response.

```rust
impl Agent for ReActAgent {
    fn build(&self, graph: &mut Graph) {
        graph.add_system(receive_user_input);
        graph.add_system(init_loop);


        graph.add_loop::<ReactState, _, _>(
            "react_loop",
            |state| state.is_complete,
            |g| {
                g.add_system(act);
                g.add_conditional_branch::<LlmResponse, _, _, _>(
                    "has_tool_calls",
                    |response| response.has_tool_calls(),
                    |tool_branch| {
                        tool_branch.add_system(execute_tools);
                    },
                    |done_branch| {
                        done_branch.add_system(finalize);
                    },
                );
                g.add_error_handler(|h| {
                    h.add_system(recover);
                });
            },
        );
    }


    fn name(&self) -> &'static str {
        "ReActAgent"
    }
}
```

Each system here is a regular async function annotated with `#[system]`. The agent does not execute anything itself. It builds a graph, and the `GraphExecutor` runs it. [Plugins](/docs/polaris/core-concepts/plugins.md) provide the resources those systems need: the `ModelRegistry` for LLM access, the `ToolRegistry` for tool execution, and so on.

That is the full picture. An agent builds a [graph](/docs/polaris/core-concepts/graphs.md). The graph contains [systems](/docs/polaris/core-concepts/systems.md). Systems use [resources](/docs/polaris/core-concepts/resources.md). [Plugins](/docs/polaris/core-concepts/plugins.md) provide those resources. The `Agent` trait ties these layers into a single, named, registerable unit.
