Skip to main content

Crate agent_sdk

Crate agent_sdk 

Source
Expand description

§Agent SDK

A Rust SDK for building AI agents powered by large language models (LLMs).

This crate provides the infrastructure to build agents that can:

  • Converse with users via multiple LLM providers
  • Execute tools to interact with external systems
  • Stream events in real-time for responsive UIs
  • Persist conversation history and state

§Quick Start

use agent_sdk::{
    builder, AgentEvent, AgentInput, ThreadId, ToolContext,
    providers::AnthropicProvider,
};

// 1. Create an LLM provider
let api_key = std::env::var("ANTHROPIC_API_KEY")?;
let provider = AnthropicProvider::sonnet(api_key);

// 2. Build the agent
let agent = builder::<()>()
    .provider(provider)
    .build();

// 3. Run a conversation
let thread_id = ThreadId::new();
let ctx = ToolContext::new(());
let (mut events, _final_state) = agent.run(
    thread_id,
    AgentInput::Text("Hello!".to_string()),
    ctx,
);

// 4. Process streaming events
while let Some(event) = events.recv().await {
    match event {
        AgentEvent::Text { message_id: _, text } => print!("{text}"),
        AgentEvent::Done { .. } => break,
        _ => {}
    }
}

§Core Concepts

§Agent Loop

The AgentLoop orchestrates the conversation cycle:

  1. User sends a message
  2. Agent sends message to LLM
  3. LLM responds with text and/or tool calls
  4. Agent executes tools and feeds results back to LLM
  5. Repeat until LLM responds with only text

Use builder() to construct an agent:

use agent_sdk::{builder, AgentConfig, providers::AnthropicProvider};

let agent = builder::<()>()
    .provider(AnthropicProvider::sonnet(api_key))
    .config(AgentConfig {
        max_turns: 20,
        system_prompt: "You are a helpful assistant.".into(),
        ..Default::default()
    })
    .build();

§Tools

Tools let the LLM interact with external systems. Implement the Tool trait:

use agent_sdk::{DynamicToolName, Tool, ToolContext, ToolResult, ToolTier};
use serde_json::{json, Value};
use std::future::Future;

struct WeatherTool;

// No #[async_trait] needed - Rust 1.75+ supports native async traits
impl Tool<()> for WeatherTool {
    type Name = DynamicToolName;

    fn name(&self) -> DynamicToolName { DynamicToolName::new("get_weather") }

    fn display_name(&self) -> &'static str { "Weather" }

    fn description(&self) -> &'static str {
        "Get current weather for a city"
    }

    fn input_schema(&self) -> Value {
        json!({
            "type": "object",
            "properties": {
                "city": { "type": "string" }
            },
            "required": ["city"]
        })
    }

    fn tier(&self) -> ToolTier { ToolTier::Observe }

    fn execute(
        &self,
        _ctx: &ToolContext<()>,
        input: Value,
    ) -> impl Future<Output = anyhow::Result<ToolResult>> + Send {
        async move {
            let city = input["city"].as_str().unwrap_or("Unknown");
            Ok(ToolResult::success(format!("Weather in {city}: Sunny, 72°F")))
        }
    }
}

Register tools with ToolRegistry:

use agent_sdk::{builder, DynamicToolName, ToolRegistry, providers::AnthropicProvider};

let mut tools = ToolRegistry::new();
tools.register(WeatherTool);

let agent = builder::<()>()
    .provider(AnthropicProvider::sonnet(api_key))
    .tools(tools)
    .build();

§Tool Tiers

Tools are classified by permission level via ToolTier:

TierDescriptionExample
ToolTier::ObserveRead-only, always allowedGet balance, read file
ToolTier::ConfirmRequires user confirmationSend email, transfer funds

§Lifecycle Hooks

Implement AgentHooks to intercept and control agent behavior:

use agent_sdk::{AgentHooks, ToolDecision, ToolResult, ToolTier};
use async_trait::async_trait;
use serde_json::Value;

struct MyHooks;

#[async_trait]
impl AgentHooks for MyHooks {
    async fn pre_tool_use(
        &self,
        tool_name: &str,
        _input: &Value,
        tier: ToolTier,
    ) -> ToolDecision {
        println!("Tool called: {tool_name}");
        match tier {
            ToolTier::Observe => ToolDecision::Allow,
            ToolTier::Confirm => ToolDecision::RequiresConfirmation(
                "Please confirm this action".into()
            ),
        }
    }

    async fn post_tool_use(&self, tool_name: &str, result: &ToolResult) {
        println!("{tool_name} completed: {}", result.success);
    }
}

Built-in hook implementations:

§Events

The agent emits AgentEvents during execution for real-time updates:

EventDescription
AgentEvent::StartAgent begins processing
AgentEvent::TextText response from LLM
AgentEvent::TextDeltaStreaming text chunk
AgentEvent::ToolCallStartTool execution starting
AgentEvent::ToolCallEndTool execution completed
AgentEvent::TurnCompleteOne LLM round-trip finished
AgentEvent::DoneAgent completed successfully
AgentEvent::ErrorAn error occurred

§Task Tracking

Use TodoWriteTool and TodoReadTool to track task progress:

use agent_sdk::todo::{TodoState, TodoWriteTool, TodoReadTool};
use std::sync::Arc;
use tokio::sync::RwLock;

let state = Arc::new(RwLock::new(TodoState::new()));
let write_tool = TodoWriteTool::new(Arc::clone(&state));
let read_tool = TodoReadTool::new(state);

Task states: Pending (○), InProgress (⚡), Completed (✓)

§Custom Context

Pass application-specific data to tools via the generic type parameter:

use agent_sdk::{DynamicToolName, Tool, ToolContext, ToolResult, ToolTier};
use serde_json::Value;
use std::future::Future;

// Your application context
struct AppContext {
    user_id: String,
    // database: Database,
}

struct UserInfoTool;

impl Tool<AppContext> for UserInfoTool {
    type Name = DynamicToolName;

    fn name(&self) -> DynamicToolName { DynamicToolName::new("get_user_info") }
    fn display_name(&self) -> &'static str { "User Info" }
    fn description(&self) -> &'static str { "Get info about current user" }
    fn input_schema(&self) -> Value { serde_json::json!({"type": "object"}) }

    fn execute(
        &self,
        ctx: &ToolContext<AppContext>,
        _input: Value,
    ) -> impl Future<Output = anyhow::Result<ToolResult>> + Send {
        let user_id = ctx.app.user_id.clone();
        async move {
            Ok(ToolResult::success(format!("User: {user_id}")))
        }
    }
}

§Modules

ModuleDescription
providersLLM provider implementations
primitive_toolsBuilt-in file operation tools (Read, Write, Edit, Glob, Grep, Bash)
llmLLM abstraction layer
subagentNested agent execution with SubagentFactory
mcpModel Context Protocol support
[todo]Task tracking tools (TodoWriteTool, TodoReadTool)
user_interactionUser question/confirmation tools (AskUserQuestionTool)
webWeb search and fetch tools
skillsCustom skill/command loading
remindersSystem reminder infrastructure for agent guidance

§System Reminders

The SDK includes a reminder system that provides contextual guidance to the AI agent using the <system-reminder> XML tag pattern. Claude is trained to recognize these tags and follow the instructions without mentioning them to users.

use agent_sdk::reminders::{wrap_reminder, ReminderConfig, ReminderTracker};

// Wrap guidance in system-reminder tags
let reminder = wrap_reminder("Verify the output before proceeding.");

// Configure reminder behavior
let config = ReminderConfig::new()
    .with_todo_reminder_turns(5)
    .with_repeated_action_threshold(3);

§Feature Flags

All features are enabled by default. The crate has no optional features currently.

Re-exports§

pub use llm::LlmProvider;
pub use llm::ThinkingConfig;
pub use user_interaction::AskUserQuestionTool;
pub use user_interaction::ConfirmationRequest;
pub use user_interaction::ConfirmationResponse;
pub use user_interaction::QuestionOption;
pub use user_interaction::QuestionRequest;
pub use user_interaction::QuestionResponse;
pub use subagent::SubagentConfig;
pub use subagent::SubagentFactory;
pub use subagent::SubagentTool;
pub use todo::TodoItem;
pub use todo::TodoReadTool;
pub use todo::TodoState;
pub use todo::TodoStatus;
pub use todo::TodoWriteTool;
pub use reminders::ReminderConfig;
pub use reminders::ReminderTracker;
pub use reminders::ReminderTrigger;
pub use reminders::ToolReminder;
pub use reminders::append_reminder;
pub use reminders::wrap_reminder;

Modules§

context
Context compaction for long-running conversations.
llm
mcp
Model Context Protocol (MCP) client support.
primitive_tools
Primitive tools that work with the Environment abstraction.
providers
LLM Provider implementations.
reminders
System reminder infrastructure for agent guidance.
skills
Skills system for loading agent behavior from markdown files.
subagent
Subagent support for spawning child agents.
todo
TODO task tracking for agents.
user_interaction
User interaction types and tools.
web
Web tools for search and fetching.

Structs§

AgentCapabilities
Capabilities that control what the agent can do.
AgentConfig
Configuration for the agent loop
AgentContinuation
Continuation state that allows resuming the agent loop.
AgentError
Error from the agent loop.
AgentLoop
The main agent loop that orchestrates LLM calls and tool execution.
AgentLoopBuilder
Builder for constructing an AgentLoop.
AgentState
Snapshot of agent state for checkpointing
AllowAllHooks
Hooks that allow all tools without confirmation
DefaultHooks
Default hooks implementation that uses tier-based decisions
DynamicToolName
Dynamic tool name for runtime-created tools (MCP bridges, subagents).
ExecResult
Result from command execution
FileEntry
Entry in a directory listing
GrepMatch
Match result from grep operation
InMemoryExecutionStore
In-memory implementation of ToolExecutionStore.
InMemoryFileSystem
In-memory filesystem for testing
InMemoryStore
In-memory implementation of MessageStore and StateStore. Useful for testing and simple use cases.
LocalFileSystem
Local filesystem implementation using std::fs
LoggingHooks
Hooks that log all events (useful for debugging)
NullEnvironment
A null environment that rejects all operations. Useful as a default when no environment is configured.
PendingToolCallInfo
Information about a pending tool call that was extracted from the LLM response.
RetryConfig
Configuration for retry behavior on transient errors.
ThreadId
Unique identifier for a conversation thread
TokenUsage
Token usage statistics
ToolContext
Context passed to tool execution
ToolExecution
Record of a tool execution for idempotency.
ToolRegistry
Registry of available tools.
ToolResult
Result of a tool execution

Enums§

AgentEvent
Events emitted by the agent loop during execution. These are streamed to the client for real-time UI updates.
AgentInput
Input to start or resume an agent run.
AgentRunState
Outcome of running the agent loop.
ErasedToolStatus
Type-erased status for the agent loop.
ExecutionStatus
Status of a tool execution for idempotency tracking.
PrimitiveToolName
Tool names for SDK’s built-in primitive tools.
ToolDecision
Decision returned by pre-tool hooks
ToolOutcome
Result of tool execution - may indicate async operation in progress.
ToolStatus
Status update from an async tool operation.
ToolTier
Permission tier for tools
TurnOutcome
Outcome of running a single turn.

Traits§

AgentHooks
Lifecycle hooks for the agent loop. Implement this trait to customize agent behavior.
AsyncTool
A tool that performs long-running async operations.
Environment
Environment abstraction for file and command operations.
ErasedAsyncTool
Type-erased async tool trait for registry storage.
ErasedTool
Type-erased tool trait for registry storage.
MessageStore
Trait for storing and retrieving conversation messages. Implement this trait to persist messages to your storage backend.
ProgressStage
Marker trait for tool progress stages (type-safe, like ToolName).
StateStore
Trait for storing agent state checkpoints. Implement this to enable conversation recovery and resume.
Tool
Definition of a tool that can be called by the agent.
ToolExecutionStore
Store for tracking tool executions (idempotency).
ToolName
Marker trait for tool names.

Functions§

builder
Create a new builder for constructing an AgentLoop.
stage_to_string
Helper to get string representation of a progress stage via serde.
tool_name_from_str
Parse a tool name from string via serde.
tool_name_to_string
Helper to get string representation of a tool name via serde.