Agent ABC — and the manifest
loads it the same way it loads a tool module.
The Agent contract
The whole agent shape is owned once by the contract: theAgent ABC with its
default stream and drain behaviour, the neutral spec descriptors, and a typed
event vocabulary. The skeleton adds no agent implementation of its own — it
surfaces the contract in its own namespace and registers agents against the app.
You register an agent with a decorator that also names it. The skeleton
synthesizes the agent’s JSON run tool from its declared input model, so an agent
is callable exactly like any other tool:
meta={"tai42/pauses": True} on the decorator, like any
tool that can pause. A tool an agent calls
that parks without that declaration fails the agent’s run with UndeclaredPauseError
naming the tool; the model is never handed a tool error to retry around, so the tool’s
body runs once.
An ask inside an agent’s run returns {answer, reply_to, params}, as it does anywhere
(see Block or park). A parked
agent run resumes through the agents’ continuation tool (agent_resume), which is run
with {interaction_id, ask_result} and hands the waiting ask the ask_result object
unchanged.
Streaming events
An agent run streams a typed sequence ofStreamEvents rather than returning a
single blob. The vocabulary covers message deltas and finals, reasoning steps,
tool-call and tool-result steps, structured finals, interrupt finals, and run
usage. The event producers — the projection over the agent runtime’s updates and
messages — live in the agents runtime; a client renders the frames as they arrive.
When a run carries a response_format, the structured result reaches a
user-visible stream only as the terminal structured final — the stream carries
no synthetic structured-output tool-call/result frame for the internal call that
produced it.
A structured-output run that never conforms, or one that exhausts its graph step
limit, ends with a typed non-fatal terminal — structured_output_unresolved_final
(the schema, the attempts, the last validation error) or recursion_limit_final
(the limit) — that a calling run or route branches on by type rather than receiving a
generic failure. The re-prompt bound is the server-wide
TAI_AGENTS_STRUCTURED_OUTPUT_REPROMPT_CAP (default 3).
Run an agent and watch its stream from the CLI:
Context management
Before each model call an agent trims its conversation history to fit a token budget — the default context-management strategy, configurable viaCONTEXT_OVERFLOW_METHODS — keeping the most recent turns and dropping older
ones; a trim that drops history logs a warning. The newest human message is never discarded: when the
budget cannot hold the system prompt plus the current message, the run raises a
typed TrimmingBudgetTooSmallError naming the budget rather than answering from
the system prompt alone, so an overflow surfaces loudly instead of returning a
silently wrong reply. Raise the budget with TRIMMING_MIDDLEWARE_MAX_TOKENS.
The system prompt is per-run configuration, supplied fresh at each model call
(create_agent(system_prompt=...)) — it is never stored in thread or checkpoint
state. Any system message found in replayed thread history is stripped before the
model sees it, so the prompt comes only from the run’s own configuration; it counts
against the trimming budget above.
System-prompt caching
Every agent turn re-sends its whole system prompt. On a provider that takes a system-prompt cache breakpoint, marking that stable prefix lets the provider cache it and read it back on later turns instead of re-billing it. This marking is on by default (TAI_AGENTS_SYSTEM_PROMPT_CACHE_DEFAULT=true), server-wide; a provider
that caches without a mark, or supports none, is left unmarked.
A tools_agent node overrides the default with system_content_kwargs: leave it
unset to take the default, pass {} to opt the node out (no mark), or pass an
explicit mark of your own. Most agent faces carry the default; the retrieval agent
and the Claude Code agent are excluded — see the agents
plugin for the per-face detail.
Authored agents
Beyond code-defined agents, you can author an agent as a saved spec that rides the versioning spine — a preset that bakes the agent’s preset-bakeable fields. Authored agents version and roll back exactly like presets, so an agent’s configuration evolves without breaking its callers.Composition
An agent can drive other agents as sub-agents and chain multi-step work. That compositional side — sub-agents and the ready-made set — is its own pillar: deep agents. The platform ships ready-made deep agents that run that durable, code-executing work over the sandbox — the execution surface an agent reaches for a persistent workspace and code — see the agents plugin and the guide. See the author-an-agent guide for the full authoring path and the Python SDK reference for theAgent
ABC and the StreamEvent types.
