Concepts · agent
Agent State
Runtime state observability: history via Messages, everything else via the run stream
- Reading agent state during or after a run
- Understanding state concurrency model
This page gives you the agent state model for history, streams, concurrency, and mid-run observation.
The agent freezes configuration at construction. It exposes conversation history through Messages(). A run’s progress, result, and error live on the Stream returned by Run.
Design: state lives on the run, not the agent
Each call to Run returns its own stream. Stream.Wait() returns that run’s messages and error. Stream.Events() exposes that run’s progress. State from one run cannot be mistaken for another run’s result.
Messages
Messages() returns a defensive copy of the full conversation history. Callers cannot corrupt internal state. WithHistory(msgs...) also copies its input slice.
Concurrency
- Reads —
Messages()acquires a mutex, copies, and returns. Any goroutine can call it, including mid-run. - Writes — only the run’s producer goroutine appends to history, also under the mutex.
- Guard —
Runreads arunningflag under the lock. A concurrentRunreturns an “already running” stream error.
Mid-run observability
For real-time updates during a run, consume the run’s stream:
- Streaming content —
message_updateevents carry partial assistant messages as they stream. - Tool progress —
tool_execution_start/update/endevents track tool calls. - Completion —
agent_endcarries all new messages and accumulated usage. An error ends the stream without this event.