Agent class abstracts what an agent does into a small set of behaviors, each suited to a different goal:
Reply
reply and reply_stream drive the same reasoning-acting loop over the same inputs; they differ only in how results are delivered. The inputs parameter accepts:
Basic Reply
One call in, one finalMsg out: the simplest way to run the agent, suited for automation where intermediate events don’t matter.
reply consumes all events internally and returns the final Msg when the agent finishes. If the reply pauses for outside interaction, it returns a waiting notice whose finished_reason is None, meaning the reply is not finished yet.
Msg carries the reply’s full outcome. The fields worth checking after each call:
See Message & Event for the complete
Msg structure and content block types.
Streaming Reply
The agent emits text deltas, tool call progress, and lifecycle events in real time, which is the basis for interactive UIs.reply_stream yields AgentEvent objects as they are produced:
yield_final_msg=True to additionally yield the final Msg as the last item of the stream. This is useful when you need the assembled reply message (e.g. its structured_output attribute) besides the events:
Structured Output
A reply can be required to produce fields conforming to a JSON schema, which is typical for generating reports or emitting control fields that drive a workflow. Pass a Pydantic model class viastructured_schema. The agent equips a builtin GenerateStructuredOutput tool whose input schema is your schema: it reasons and calls other tools freely first, then submits the result through this tool. Validation errors are fed back to the model for retry, and the validated result lands on the final message’s structured_output attribute as a plain dict (the message text is only a placeholder).
structured_schema again; the reply continues with the schema it was parked with.
- Validation adapts to how the reply runs. In process, the class itself validates the output: defaults (including
default_factory) are filled, extra fields are dropped, and custom validators are executed. After reloading a serialized state, only the JSON schema remains: schema-declared defaults are filled, extra fields are kept, and custom validators are skipped. - On reaching
max_iterswithout output, the agent forces theGenerateStructuredOutputcall withinstructured_output_grace_itersextra iterations (default 5). If it still fails, the reply ends withfinished_reason=EXCEED_MAX_ITERSandstructured_outputisNone; check forNonebefore use.
Message Observation
Messages can be injected into the agent’s context without triggering a reply. This is useful in multi-agent setups where one agent needs to see another’s output.Context Compression
Long conversations are kept within the model’s context window by summarizing older messages, triggered automatically or on demand. The agent compresses its context when the token count exceedscontext_config.trigger_ratio × model.context_length, and offloads the summarized messages to disk if an offloader is configured.
compress_context takes two optional arguments: a context_config that overrides the default thresholds for this call, and an instructions HintBlock that is injected into the compression context to guide the summarization (for example, what must be preserved):
tool_result_limit tokens are truncated automatically; with an offloader, the truncated portion is offloaded and the agent receives a path reference it can read on demand. See Context for the full compression pipeline and offloading.
If the system prompt alone exceeds the compression threshold,
compress_context raises a RuntimeError. Keep system prompts concise or increase the model’s context length.State Persistence
The complete agent state serializes to JSON, so a reply can pause in one process and resume in another. This is the basis for multi-session services.AgentState holds everything needed to resume exactly where the agent left off: conversation context, compression summary, permission rules, tool state, and the current reply position. RedisStorage is the built-in storage backend, organising state under a (user_id, agent_id, session_id) key hierarchy:
update_session_state raises KeyError if the session does not exist yet. Use upsert_session to create the session record on the first turn, then switch to update_session_state for subsequent turns.