API Reference

Top-Level Functions

agent_loop()

#![allow(unused)]
fn main() {
pub async fn agent_loop(
    prompts: Vec<AgentMessage>,
    context: &mut AgentContext,
    config: &AgentLoopConfig,
    tx: mpsc::UnboundedSender<AgentEvent>,
    cancel: CancellationToken,
) -> Vec<AgentMessage>
}

Start an agent loop with new prompt messages. Returns all messages generated during the run.

agent_loop_continue()

#![allow(unused)]
fn main() {
pub async fn agent_loop_continue(
    context: &mut AgentContext,
    config: &AgentLoopConfig,
    tx: mpsc::UnboundedSender<AgentEvent>,
    cancel: CancellationToken,
) -> Vec<AgentMessage>
}

Resume from existing context. The last message must not be an assistant message.

default_tools()

(feature native, on by default)

#![allow(unused)]
fn main() {
pub fn default_tools() -> Vec<Box<dyn AgentTool>>
}

Returns: BashTool, ReadFileTool, WriteFileTool, EditFileTool, ListFilesTool, SearchTool.

Agent Struct

High-level stateful wrapper around the agent loop.

Construction

#![allow(unused)]
fn main() {
let agent = Agent::from_config(ModelConfig::anthropic("claude-sonnet-5", "Claude Sonnet 5"));
}
SignatureDescription
Agent::from_config(config: ModelConfig) -> SelfBuild from a ModelConfig — auto-selects the built-in provider for the config's protocol and resolves the API key from the provider's conventional env var (primary constructor)
Agent::from_provider(provider: impl StreamProvider + 'static, config: ModelConfig) -> SelfBuild from an explicit provider plus its ModelConfig (custom providers and test doubles — pair with ModelConfig::mock())
Agent::from_config_with(registry: &ProviderRegistry, config: ModelConfig) -> Result<Self, AgentBuildError>Like from_config, but resolves the provider from a caller-supplied registry

Agent::new(provider) with with_model / with_model_config (and the same on SubAgentTool) still compiles but is deprecated since 0.10.0 and hidden from the docs since 0.25; it will be removed in 1.0.

Builder Methods

All return Self for chaining (unless noted as Result).

Core

MethodDescription
with_system_prompt(prompt) -> SelfSet the system prompt
with_api_key(key) -> SelfOverride the env-resolved API key
with_thinking(level: ThinkingLevel) -> SelfSet thinking level (Off, Minimal, Low, Medium, High, XHigh, Max)
with_max_tokens(max: u32) -> SelfSet max output tokens
with_temperature(t: f32) -> SelfSet the sampling temperature (the newest reasoning models reject it)

Tools & Integrations

MethodDescription
with_tools(tools: Vec<Box<dyn AgentTool>>) -> SelfSet tools (replaces existing)
with_tool_source(source: impl ToolSource) -> SelfAdd a tool source consulted once at the start of every run; its tools are offered for that run only (the agent's own tools win on name collisions). See Tools
with_tool_middleware(m: impl ToolMiddleware) -> SelfAdd an approve/modify/deny hook gating every tool call
with_sub_agent(sub: SubAgentTool) -> SelfAdd a sub-agent tool
with_shared_state(state: SharedState) -> SelfRegister the shared_state tool and stash truncated tool output under a retrievable key
with_skills(skills: SkillSet) -> SelfLoad skills and append their index to the system prompt
async with_mcp_server_stdio(command, args, env) -> Result<Self, McpError>Connect to MCP server via stdio and add its tools (feature native)
async with_mcp_server_http(url) -> Result<Self, McpError>Connect to MCP server via HTTP and add its tools
async with_openapi_file(path, config, filter) -> Result<Self, OpenApiError>Load tools from an OpenAPI spec file (requires openapi feature)
async with_openapi_url(url, config, filter) -> Result<Self, OpenApiError>Fetch spec from URL and add tools (requires openapi feature)
with_openapi_spec(spec_str, config, filter) -> Result<Self, OpenApiError>Parse spec string and add tools (requires openapi feature)

Context & Limits

MethodDescription
with_context_config(config: ContextConfig) -> SelfSet context compaction config
with_execution_limits(limits: ExecutionLimits) -> SelfSet execution limits (max turns, tokens, duration)
with_compaction_strategy(strategy: impl CompactionStrategy) -> SelfSet a custom compaction strategy
without_context_management() -> SelfDisable automatic context compaction and execution limits

Behavior

MethodDescription
with_messages(msgs: Vec<AgentMessage>) -> SelfPre-load message history
with_cache_config(config: CacheConfig) -> SelfSet prompt caching configuration
with_tool_execution(strategy: ToolExecutionStrategy) -> SelfSet tool execution strategy (Parallel, Sequential, Batched)
with_retry_config(config: RetryConfig) -> SelfSet retry configuration
with_input_filter(filter: impl InputFilter) -> SelfAdd an input filter (runs on user messages before LLM call)
with_async_input_filter(filter: impl AsyncInputFilter) -> SelfAdd an input filter that awaits (same list and semantics)
with_turn_hook(hook: impl TurnHook) -> SelfAdd an async per-request hook that may append one transient note to the latest user turn
with_decision_model(model: DecisionModel) -> Self(feature decision) Advisory skill/tool hints from a decision model; never blocks; needs skills or 40+ tools
with_decision_advisory(advisory: Advisory) -> Self(feature decision) The same, with explicit thresholds and timeout
with_tool_gate(gate: ToolGate) -> Self(feature decision) Deny destructive, unrequested tool calls; runs last; fails closed
with_input_guard(guard: InputGuard) -> Self(feature decision) Reject injection / harmful prompts; fails closed; panics if the guard has no checks

Callbacks

MethodDescription
on_before_turn(f: Fn(&[AgentMessage], usize) -> bool) -> SelfCalled before each LLM call; return false to abort
on_after_turn(f: Fn(&[AgentMessage], &Usage)) -> SelfCalled after each LLM response and tool execution
on_error(f: Fn(&str)) -> SelfCalled when the LLM returns StopReason::Error (not for cancellations, which end StopReason::Aborted since 0.23)

Prompting

MethodDescription
async prompt(text) -> UnboundedReceiver<AgentEvent>Send a text prompt; spawns the loop concurrently and returns the event stream immediately for real-time consumption
async prompt_messages(messages) -> UnboundedReceiver<AgentEvent>Send messages as prompt; spawns concurrently, returns event stream immediately
async prompt_with_sender(text, tx: UnboundedSender<AgentEvent>)Send a text prompt, streaming events to a caller-provided sender; blocks until the loop finishes
async prompt_messages_with_sender(messages, tx)Send messages, streaming events to a caller-provided sender; blocks until the loop finishes
async prompt_structured::<T>(text, schema: serde_json::Value) -> Result<T, StructuredPromptError>Run to completion and parse a schema-constrained reply into T. See Structured Outputs
async continue_loop() -> UnboundedReceiver<AgentEvent>Resume from current context; spawns concurrently, returns event stream immediately
async continue_loop_with_sender(tx: UnboundedSender<AgentEvent>)Resume from current context, streaming events to a caller-provided sender; blocks until the loop finishes
async finish()Await a pending spawned loop and restore tools/messages/state. Called automatically at the start of each prompt method

State Access

MethodDescription
messages() -> &[AgentMessage]Get the full message history
is_streaming() -> boolWhether the agent is currently running
session_cost_usd() -> Option<f64>Cost of the current history at the current rates (excludes sub-agents); None = unpriced
sub_agent_spend() -> &SubAgentSpendWhat sub-agents spent on this agent's behalf since construction or reset()
compaction_spend() -> &CompactionSpendWhat LlmCompaction's summarization requests cost over the same window (sub-agents' included)
total_cost_usd() -> Option<f64>Everything this agent's runs spent: own turns, sub-agents, compaction summaries and decision-model requests
total_usage() -> UsageToken usage over the same window as total_cost_usd() (decision-model tokens excluded)

State Mutation

MethodDescription
set_tools(tools: Vec<Box<dyn AgentTool>>)Replace the tool set
set_model(config: ModelConfig)Switch model mid-session; re-resolves the env key, re-selects the provider only if it was not supplied explicitly
reprice()Re-run the price lookup for the current ModelConfig
clear_messages()Clear all messages
append_message(msg: AgentMessage)Add a message to history
replace_messages(msgs: Vec<AgentMessage>)Replace all messages
save_messages() -> Result<String, serde_json::Error>Serialize message history to JSON
restore_messages(json: &str) -> Result<(), serde_json::Error>Restore message history from JSON

Steering & Follow-Up Queues

MethodDescription
steer(msg: AgentMessage)Queue a steering message (interrupts mid-tool-execution)
follow_up(msg: AgentMessage)Queue a follow-up message (processed after agent finishes)
clear_steering_queue()Clear pending steering messages
clear_follow_up_queue()Clear pending follow-up messages
clear_all_queues()Clear both queues
steer_all(msgs: Vec<AgentMessage>)Queue multiple steering messages under one lock
follow_up_all(msgs: Vec<AgentMessage>)Queue multiple follow-up messages under one lock
steering_queue_snapshot() -> Vec<AgentMessage>Copy of pending steering messages (does not consume)
follow_up_queue_snapshot() -> Vec<AgentMessage>Copy of pending follow-up messages
steering_queue_len() -> usizeNumber of pending steering messages
follow_up_queue_len() -> usizeNumber of pending follow-up messages
take_steering_queue() -> Vec<AgentMessage>Atomically drain and return pending steering messages (messages already picked up by the loop are not included)
take_follow_up_queue() -> Vec<AgentMessage>Atomically drain and return pending follow-up messages
set_steering_mode(mode: QueueMode)Set delivery mode: OneAtATime or All
set_follow_up_mode(mode: QueueMode)Set delivery mode: OneAtATime or All

Control

MethodDescription
abort()Cancel the current run via CancellationToken. During an LLM call (or a retry's backoff) the turn ends with StopReason::Aborted; while tools run or between turns, the run ends with a [Agent stopped: cancelled] user message
async reset()Cancel any pending loop, recover tools, clear all state (messages, queues, streaming flag)

SubAgentTool

Delegates tasks to a child agent loop.

Construction

#![allow(unused)]
fn main() {
// Provider auto-selected from the config's protocol; env key resolved automatically:
let sub = SubAgentTool::from_config("name", ModelConfig::anthropic("claude-sonnet-5", "Claude Sonnet 5"));

// Or resolve against a custom registry: SubAgentTool::from_config_with(&registry, "name", config) -> Result<_, AgentBuildError>

// Or pass an explicit provider Arc (custom providers, or a shared handle across sub-agents):
let sub = SubAgentTool::from_provider("name", Arc::new(provider), ModelConfig::anthropic("claude-sonnet-5", "Claude Sonnet 5"));
}

Builder Methods

All return Self for chaining.

MethodDescription
with_description(desc) -> SelfWhat the parent LLM sees (helps it decide when to delegate)
with_system_prompt(prompt) -> SelfThe sub-agent's own instructions
with_api_key(key) -> SelfOverride the env-resolved API key
with_tools(tools: Vec<Arc<dyn AgentTool>>) -> SelfTools available to the sub-agent
with_tool_source(source: impl ToolSource) -> SelfAdd a tool source, consulted once per delegation
with_tool_middleware(m: impl ToolMiddleware) -> SelfGate the sub-agent's own tool calls
with_turn_hook(hook: impl TurnHook) -> SelfPer-request hook for the sub-agent's own LLM requests
with_async_input_filter(f: impl AsyncInputFilter) -> SelfFilter the task the parent hands over; a rejection fails the tool call
with_skills(skills: SkillSet) -> SelfAppend the skills index to the sub-agent's system prompt
with_shared_state(state: SharedState) -> SelfAttach a shared key-value store (injects shared_state tool automatically)
with_scoped_shared_state(state: SharedState, scope) -> SelfSame, restricted to keys under scope
with_context_config(config: ContextConfig) -> SelfGive the child loop its own context management (truncation, compaction)
with_max_turns(N) -> SelfTurn limit (default: 10)
with_thinking(level: ThinkingLevel) -> SelfEnable extended thinking
with_max_tokens(max: u32) -> SelfSet max output tokens
with_temperature(t: f32) -> SelfSet the sampling temperature
with_cache_config(config: CacheConfig) -> SelfPrompt caching settings
with_tool_execution(strategy: ToolExecutionStrategy) -> SelfTool execution strategy (Parallel, Sequential, Batched)
with_retry_config(config: RetryConfig) -> SelfCustom retry configuration
with_turn_delay(delay: Duration) -> SelfInter-turn delay to throttle API calls (skips first turn)
with_decision_model / with_decision_advisory / with_tool_gate / with_input_guard(feature decision) Mirror the Agent methods for the sub-agent's own turns
reprice() -> SelfRe-run the price lookup for the sub-agent's ModelConfig

SharedState

Pluggable key-value store for sub-agent communication. Backed by a SharedStateBackend trait.

Construction

#![allow(unused)]
fn main() {
use yoagent::shared_state::{SharedState, FileBackend};

let state = SharedState::new();                              // MemoryBackend, 10MB cap
let state = SharedState::with_max_bytes(50 * 1024 * 1024);  // MemoryBackend, 50MB cap
let state = SharedState::with_backend(FileBackend::new("./state-dir")); // FileBackend (feature `native`)
}

Methods

MethodDescription
async get(key) -> Option<String>Read a value by key
async set(key, value) -> Result<(), SharedStateError>Store a value
async remove(key) -> boolDelete a key, returns whether it existed
async keys() -> Vec<String>List all keys
async summary() -> StringHuman-readable summary of keys and sizes
async prompt_summary() -> StringLike summary(), minus truncation stashes (for system prompts)
scoped(scope) -> SharedStateA handle restricted to keys under scope
scope() -> Option<&str>This handle's scope, if any

Built-in Backends

BackendDescription
MemoryBackendIn-memory HashMap with byte capacity limit (default)
FileBackendOne file per key, percent-encoded filenames, persistent (feature native)

Custom Backends

Implement the SharedStateBackend trait:

#![allow(unused)]
fn main() {
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
pub trait SharedStateBackend: yoagent::rt::MaybeSend + yoagent::rt::MaybeSync {
    async fn get(&self, key: &str) -> Result<Option<String>, SharedStateError>;
    async fn set(&self, key: &str, value: String) -> Result<(), SharedStateError>;
    async fn remove(&self, key: &str) -> Result<bool, SharedStateError>;
    async fn keys(&self) -> Result<Vec<String>, SharedStateError>;
    async fn summary(&self) -> Result<String, SharedStateError>;
}
}

MaybeSend + MaybeSync is exactly Send + Sync on native targets, so a native-only implementation can keep plain #[async_trait]. See WebAssembly & Cloudflare Workers.

Retry

yoagent::retry — see Retry.

ItemDescription
RetryConfigRetry count and backoff (max_retries, initial_delay_ms, backoff_multiplier, max_delay_ms); RetryConfig::none() disables retries
retry_safe_events(rx) -> rxWraps an event receiver so each provider attempt's events are held until it succeeds; a retried attempt leaves only its ProviderRetry
RetrySafeEventsThe same filter for your own event loop: new(), push(event) -> Vec<AgentEvent>, finish() -> Vec<AgentEvent> (also resets it)

Re-exports

The crate re-exports key types from lib.rs:

#![allow(unused)]
fn main() {
pub use agent::{Agent, AgentBuildError, StructuredPromptError};
pub use agent_loop::{agent_loop, agent_loop_continue};
pub use context::{CompactionStrategy, DefaultCompaction};
pub use llm_compaction::LlmCompaction;
pub use retry::RetryConfig;
pub use session::{Session, SessionEntry, SessionError};
pub use shared_state::SharedState;
pub use skills::SkillSet;
pub use sub_agent::SubAgentTool;
pub use tool_source::ToolSource;
pub use types::*;  // Message, Content, AgentMessage, AgentEvent, etc.
}

Runtime shims (spawn, sleep, timeout, JoinHandle, Instant, MaybeSend, MaybeSync) live in yoagent::rt: Tokio's own on native targets, the host executor on wasm32.