Agents API¶
agents ¶
BaseAgent ¶
BaseAgent(
agent_name: str,
system_prompt: str,
output_type: type[OutputT],
*,
model: Model | str,
api_key: str | None = None,
retries: int = 3,
tools: list[Tool] | None = None,
toolsets: list[Any] | None = None,
truncated_history: int = 100,
history_processors: list | None = None,
result_budget: int | None = 20000,
context_manager: ContextManager | None = None,
model_settings: ModelSettings | None = None,
reasoning: ReasoningEffort | None = None,
confidence_protocol: Any = None,
)
Abstract base class for orqest agents.
Generic over StateT (input state, a Pydantic model) and OutputT (output, a Pydantic model). Subclasses must implement _run_implementation().
The model parameter is required so that each agent explicitly declares its provider — two agents in the same process can use different models without conflict.
Initialize the agent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_name
|
str
|
Name for logging and identification. |
required |
system_prompt
|
str
|
System prompt guiding agent behavior. |
required |
output_type
|
type[OutputT]
|
Pydantic model class for structured output. |
required |
model
|
Model | str
|
A pydantic-ai Model instance, or a 'provider:model_id' string. |
required |
api_key
|
str | None
|
Required when model is a string; passed to the provider. |
None
|
retries
|
int
|
Retry attempts for failed LLM calls. |
3
|
tools
|
list[Tool] | None
|
Individual Tool instances to register. |
None
|
toolsets
|
list[Any] | None
|
Toolset objects providing collections of tools. |
None
|
truncated_history
|
int
|
Max recent messages kept by the default history processor. |
100
|
history_processors
|
list | None
|
Custom processors; defaults to keep_recent_messages. |
None
|
result_budget
|
int | None
|
Max chars for tool result content before truncation. None disables budgeting. Default 20,000. |
20000
|
context_manager
|
ContextManager | None
|
Optional ContextManager for token-aware compaction. When present, its compact method is prepended as the first history processor. |
None
|
model_settings
|
ModelSettings | None
|
Optional pydantic-ai |
None
|
reasoning
|
ReasoningEffort | None
|
Optional provider-agnostic reasoning/thinking effort —
one of |
None
|
confidence_protocol
|
Any
|
Optional agent-level default
|
None
|
Source code in orqest/agents/base_agent.py
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | |
confidence_protocol
property
¶
The agent-level default ConfidenceProtocol, or None.
Set via the constructor's confidence_protocol keyword; used by
:meth:run_enriched and consulted by callers (e.g.
:class:~orqest.orchestration.loop.RefinementLoop) that need the
agent to be confidence-aware.
add_tool ¶
Add a :class:pydantic_ai.Tool at runtime; invalidate the cache.
Appends tool to self.tools and resets the cached internal
pydantic_ai.Agent so the next call to :attr:agent rebuilds
with the new tool list.
Idempotent for tools sharing a name: an existing entry is
replaced (last write wins). Useful when an LLM-spawned tool needs
to update its implementation.
In-flight runs do NOT see the new tool — the rebuild happens
on the next :attr:agent access; any Agent.run() call already
in flight uses the tool list it captured at start time.
Source code in orqest/agents/base_agent.py
call_model
async
¶
Run the pydantic-ai agent with conversation history from state.
Passes state.message_history into Agent.run() and stores the updated history back on state after the run. This is the recommended way to call the LLM from _run_implementation() when you want multi-turn conversation support.
For stateless one-shot calls, use self.agent.run() directly instead.
Source code in orqest/agents/base_agent.py
call_model_stream
async
¶
Stream the pydantic-ai agent with conversation history from state.
Async context manager that wraps Agent.run_stream(). Yields a StreamedRunResult for full control over the stream. Updates state.message_history after the context exits (once the stream is consumed).
This is the low-level streaming primitive — stream_text() and stream_output() are built on top of it.
Source code in orqest/agents/base_agent.py
stream_output
async
¶
stream_output(
prompt: Prompt,
state: StateT,
*,
debounce_by: float | None = None,
) -> AsyncIterator[OutputT]
Stream partial structured output from the LLM.
Async generator yielding partial OutputT Pydantic model instances as the model produces them. Each yield is the latest validated partial of the structured output.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
Prompt
|
The user prompt to send. |
required |
state
|
StateT
|
Conversation state — history is read and updated. |
required |
debounce_by
|
float | None
|
Optional minimum interval (seconds) between yields. |
None
|
Source code in orqest/agents/base_agent.py
stream_events
async
¶
Stream all agent events including model responses and tool calls.
Async generator yielding AgentStreamEvent instances as the agent runs. This includes model response tokens (PartStartEvent, PartDeltaEvent, PartEndEvent, FinalResultEvent) and tool execution events (FunctionToolCallEvent, FunctionToolResultEvent).
Uses Agent.iter() under the hood for full node-by-node control, making tool calls visible during streaming.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt
|
Prompt
|
The user prompt to send. |
required |
state
|
StateT
|
Conversation state — history is read and updated. |
required |
Source code in orqest/agents/base_agent.py
run
async
¶
run_enriched
async
¶
Execute the agent and pair its output with self-assessment.
Returns :class:~orqest.metacognition.EnrichedOutput[OutputT].
Best-effort: a protocol that fails surfaces confidence=None
and a protocol_error in the metadata; the underlying output
is always returned. Exceptions raised by _run_implementation
propagate, exactly like :meth:run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
StateT
|
The agent's state, same as |
required |
confidence_protocol
|
Any
|
Per-call override of the agent-level
default (set via constructor). When neither is provided,
returns |
None
|
**kwargs
|
Any
|
Forwarded to |
{}
|
Source code in orqest/agents/base_agent.py
CompoundTool ¶
CompoundTool(
agent: BaseAgent,
executor: Callable[[OutputT, StateT], Awaitable[Any]],
*,
state_updater: Callable[[StateT, Any], StateT]
| None = None,
hooks: HookRunner | None = None,
name: str | None = None,
)
Combines an agent call with a tool execution and state update.
Pattern: agent produces structured output, executor runs a tool/action
using that output, state is updated with the result. Hooks fire
before/after the execution step and can influence flow via
:class:HookDecision.
Initialize the compound tool.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
BaseAgent
|
The agent that produces structured output. |
required |
executor
|
Callable[[OutputT, StateT], Awaitable[Any]]
|
Async callable that acts on (agent_output, state). |
required |
state_updater
|
Callable[[StateT, Any], StateT] | None
|
Optional callable to update state with the result. |
None
|
hooks
|
HookRunner | None
|
HookRunner for before/after/error callbacks. |
None
|
name
|
str | None
|
Tool name for hook dispatch. Defaults to agent.agent_name. |
None
|
Source code in orqest/agents/compound_tool.py
run
async
¶
Execute the compound tool: agent, decide, execute, update state.
prompt is injected into state as a user message before the
agent runs (when state supports add_message), so the wrapped
agent receives it through the same channel as as_tool /
AgentStep rather than being silently dropped.
Returns (agent_output, execution_result). Honors
:class:Skip (returns stub_result in place of executor),
:class:Redirect (mutates args/name; bounded one re-execution
on after_tool redirect), and :class:Abort (raises
:class:HookAbortError to the caller).
Source code in orqest/agents/compound_tool.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
ContextManager ¶
ContextManager(
token_budget: int = 128000,
reserve: int = 20000,
summarize_threshold: float = 0.6,
truncate_threshold: float = 0.85,
min_recent_turns: int = 5,
min_recent_tokens: int = 10000,
*,
salience_fn: Callable[[Any], float] | None = None,
)
Progressive context compaction based on token budget.
Three layers of compaction, activated by token usage thresholds: 1. Tool result snipping (handled by budget_tool_results, separate processor) 2. Turn summarization — at summarize_threshold, compress old tool-call turns 3. Emergency truncation — at truncate_threshold, aggressive message dropping
Source code in orqest/agents/context_manager.py
compact ¶
Apply progressive compaction based on token usage.
Returns a new list — never mutates the input. Whatever path runs,
the result is post-processed by :func:_repair_orphan_tool_returns
so a ToolReturnPart never appears without its matching
ToolCallPart earlier in the same window. The Responses API
rejects such orphan returns with
"No tool call found for function call output with call_id ..."
(observed 2026-05-16 mid-Koopman-run), and chat/completions
rejects them with "messages with role 'tool' must be a response
to a preceding message with 'tool_calls'".
Source code in orqest/agents/context_manager.py
BaseSessionState ¶
GlobalState extended with session tracking and native serialization.
Subclass for domain-specific state. model_dump() and
model_validate() handle message_history correctly thanks to the
:data:SerializableMessageHistory annotation.
serialize ¶
Return a JSON-safe dict representation of this state.
Thin wrapper over model_dump(mode="json"); kept for callers
that prefer method-style access.
deserialize
classmethod
¶
Reconstruct a state from a serialized dict.
Thin wrapper over model_validate; corrupt message_history
is handled inside the :data:SerializableMessageHistory validator.
Source code in orqest/agents/session_state.py
GlobalState ¶
budget_tool_results ¶
budget_tool_results(
messages: list[ModelMessage],
*,
max_result_chars: int = 20000,
preview_chars: int = 2000,
) -> list[ModelMessage]
Truncate oversized ToolReturnPart content in message history.
Walks all messages, finds ToolReturnPart instances with content exceeding max_result_chars, and replaces with a preview prefix plus truncation notice. Returns a new list — never mutates input.
Source code in orqest/agents/base_agent.py
keep_recent_messages ¶
keep_recent_messages(
messages: list[ModelMessage], *, max_messages: int = 100
) -> list[ModelMessage]
Truncate message history while preserving the first message and turn integrity.
Returns a new list — never mutates the input.
The first message is always preserved because it typically contains the initial user prompt that establishes context. When truncation would split a request/response pair (tool call followed by tool return), the preceding response is included to maintain a valid message sequence.
Source code in orqest/agents/base_agent.py
run_with_retry
async
¶
run_with_retry(
operation: Callable[[str], Awaitable[str]],
*,
tool_name: str,
args: dict[str, Any],
state: Any,
hooks: HookRunner,
note: str,
max_attempts: int = 2,
enrich_note: Callable[[str, str], str] | None = None,
is_retryable: Callable[[Exception], bool] | None = None,
) -> str
Run a compound tool operation with retry, enrichment, and hook dispatch.
Fires hooks.run_before once at the start and hooks.run_after once
with the final result — whether success or exhausted failure. The caller
does not need to fire hooks itself.
Honors :class:HookDecision directives:
- :class:Skip from before_tool → short-circuit; return
stub_result (JSON-serialised if non-string).
- :class:Redirect(new_args=...) from before_tool → if
new_args["note"] is set, override the note for this run.
- :class:Abort → :class:HookAbortError propagates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation
|
Callable[[str], Awaitable[str]]
|
Async callable that takes a (possibly enriched) note and returns a serialized result string. Raises on failure. |
required |
tool_name
|
str
|
Name passed to hooks.run_before / run_after for dispatch. |
required |
args
|
dict[str, Any]
|
Arguments dict passed to hooks for observability. |
required |
state
|
Any
|
Opaque state object passed to hooks (e.g. SessionState). |
required |
hooks
|
HookRunner
|
HookRunner that dispatches lifecycle events. |
required |
note
|
str
|
Original note/prompt passed to operation on the first attempt. |
required |
max_attempts
|
int
|
Total number of attempts including the first. |
2
|
enrich_note
|
Callable[[str, str], str] | None
|
|
None
|
is_retryable
|
Callable[[Exception], bool] | None
|
|
None
|
Returns:
| Type | Description |
|---|---|
str
|
The operation's successful result string on any attempt, or a |
str
|
JSON-serialized failure payload ( |
str
|
attempts are exhausted or a non-retryable error occurs. |
Source code in orqest/agents/retry.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
as_tool ¶
Wrap a BaseAgent as a pydantic-ai Tool.
The orchestrating agent's LLM sees a tool with a single query parameter.
When invoked, a fresh GlobalState is created, the query is added as a user
message, and the wrapped agent runs statelessly. The output is returned as
a JSON string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
BaseAgent
|
The BaseAgent instance to wrap. |
required |
name
|
str | None
|
Tool name visible to the LLM. Defaults to agent.agent_name. |
None
|
description
|
str
|
Tool description visible to the LLM. Should clearly explain what the agent does and when to use it. |
required |