Skip to content

Support modules

Session state

A serializable snapshot of an agent's conversation and audit trail.

Configuration (provider, tools, hooks) is code and is NOT part of the state — rebuild it with Agent.from_state(state, provider, tools=...). If the tool set changed between save and resume, the mismatch with the system prompt already stored in messages is your responsibility.

Hooks and control

Bases: StrEnum

Who is allowed to run tool calls.

  • APPROVE: default-deny. Every tool call must be explicitly allowed by an on_tool_call hook (human-in-the-loop).
  • BYPASS: default-allow. Fully autonomous; hooks can still deny or modify calls.

Verdict of an on_tool_call hook.

Context passed to on_step after each provider call is processed.

Context passed to on_tool_call before execution.

Context passed to on_tool_result after execution (or denial).

Resilience

Wrap a provider with a concurrency cap and/or a minimum interval between calls.

Share one wrapped provider across agents for a process-wide limit. Falls back gracefully: no options means plain pass-through. stream and last_usage are forwarded when the inner provider has them.

Subagents

Wrap agent as a tool.

The sub-agent runs with its own isolated context: heavy exploration it performs never pollutes the caller's conversation — only its final answer comes back as the observation.

Sync facade

Run an agent from sync code (spawns its own event loop).

Cannot be used from inside a running event loop — await agent.run(...) directly there.

Console approver

Build an on_tool_call hook that asks a human about dangerous tools.

Safe tools are allowed silently; tools marked dangerous=True get a terminal prompt. Pass your own (sync) prompt callable in tests to avoid touching input().

Context management

Keeps the conversation within max_tokens using a heuristic estimate.

Two stages, cheapest first: truncate the oldest tool observations to a short preview, then compact by asking the provider itself to summarize the middle of the conversation (the system prompt and the most recent messages are always preserved).

Rough token estimate (~4 chars per token, plus per-message overhead).

Testing helpers

Provider with pre-written responses; records every call it receives.

Responses are consumed in order, one per complete() call. Running out of script raises AssertionError — a failing-by-default signal that your scenario expectations drifted from the agent's actual behavior.

Envelope string requesting a single tool call.

tool is positional on purpose: the keyword arguments are the tool's own arguments (which may legitimately be called name).

Envelope string delivering a final answer.

Developer logging

Point the toolloop logger at stderr (default) or a file.

Replaces any handlers it previously installed, so calling it twice is safe. For anything fancier, configure the "toolloop" logger with the standard :mod:logging machinery — it composes with any handlers you already use.