# Open Agent SDK (Rust) A lightweight, open-source Rust SDK for building AI agents. Run the full agent loop in-process — no CLI or subprocess required. Deploy anywhere: cloud, serverless, Docker, CI/CD. Also available in [TypeScript](https://github.com/codeany-ai/open-agent-sdk-typescript) and [Go](https://github.com/codeany-ai/open-agent-sdk-go). ## Features - **Multi-Provider** — Supports both Anthropic Messages API and OpenAI Chat Completions API, with auto-detection by model name - **Agent Loop** — Streaming agentic loop with tool execution, multi-turn conversations, and cost tracking - **25+ Built-in Tools** — Bash, Read, Write, Edit, Glob, Grep, WebFetch, WebSearch, Agent (subagents), AskUser, Tasks, Teams, Plans, Worktrees, Todos, Cron, LSP, Config, MCP Resources, ToolSearch - **Session Persistence** — Save, load, fork, and resume conversations across sessions - **MCP Support** — Connect to MCP servers via stdio, HTTP, and SSE transports - **Permission System** — Configurable tool approval with allow/deny rules and filesystem path validation - **Hook System** — 20+ hook events: PreToolUse, PostToolUse, SessionStart/End, SubagentStart/Stop, TaskCreated/Completed, FileChanged, PreCompact/PostCompact, and more - **Extended Thinking** — Support for extended thinking with budget tokens - **Cost Tracking** — Per-model token usage and pricing for Anthropic, OpenAI, and DeepSeek models - **Custom Tools** — Implement the `Tool` trait to add your own tools - **Auto-Compaction** — Multi-tier context compression (micro-compact, LLM summarization, image stripping) - **Sandbox Config** — Network and filesystem restrictions for tool execution - **File State Cache** — LRU cache for file state tracking and staleness detection ## Quick Start ```toml [dependencies] open-agent-sdk = "0.1.0" tokio = { version = "1", features = ["full"] } ``` ```rust use open_agent_sdk::{Agent, AgentOptions, SDKMessage}; use open_agent_sdk::types; #[tokio::main] async fn main() { let mut agent = Agent::new(AgentOptions::default()).await.unwrap(); // Streaming let (mut rx, handle) = agent.query("What files are in this directory?").await; while let Some(event) = rx.recv().await { match event { SDKMessage::Assistant { message, .. } => { print!("{}", types::extract_text(&message)); } SDKMessage::Result { text, cost_usd, .. } => { println!("\nDone (${:.4})", cost_usd); } _ => {} } } handle.await.unwrap(); // Or use the blocking API let result = agent.prompt("Count lines in Cargo.toml").await.unwrap(); println!("{}", result.text); agent.close().await; } ``` ## Examples | # | Example | Description | | --- | --------------------------------------------------------------- | ------------------------------------------------ | | 01 | [Simple Query](examples/01-simple-query.rs) | Streaming query with tool calls | | 02 | [Multi-Tool](examples/02-multi-tool.rs) | Glob + Bash multi-tool orchestration | | 03 | [Multi-Turn](examples/03-multi-turn.rs) | Multi-turn conversation with session persistence | | 04 | [Prompt API](examples/04-prompt-api.rs) | Blocking `prompt()` for one-shot queries | | 05 | [Custom System Prompt](examples/05-custom-system-prompt.rs) | Custom system prompt for code review | | 06 | [MCP Server](examples/06-mcp-server.rs) | MCP server integration (stdio transport) | | 07 | [Custom Tools](examples/07-custom-tools.rs) | Define and use custom tools | | 08 | [One-shot Query](examples/08-oneshot-query.rs) | Quick one-shot agent query | | 09 | [Subagents](examples/09-subagents.rs) | Specialized subagent with restricted tools | | 10 | [Permissions](examples/10-permissions.rs) | Read-only agent with allowed tools | | 11 | [Web Chat](examples/web/) | Web-based chat UI with streaming | Run any example: ```bash export CODEANY_BASE_URL=https://openrouter.ai/api export CODEANY_API_KEY=your-api-key export CODEANY_MODEL=anthropic/claude-sonnet-4 cargo run --example 01-simple-query ``` For the web chat UI: ```bash cargo run --example web-chat # Open http://localhost:8082 ``` ## Custom Tools Implement the `Tool` trait: ```rust use async_trait::async_trait; use open_agent_sdk::*; use serde_json::{json, Value}; use std::collections::HashMap; use std::sync::Arc; struct MyTool; #[async_trait] impl Tool for MyTool { fn name(&self) -> &str { "MyTool" } fn description(&self) -> &str { "Does something useful" } fn input_schema(&self) -> ToolInputSchema { ToolInputSchema { schema_type: "object".to_string(), properties: HashMap::from([( "input".to_string(), json!({"type": "string", "description": "The input"}), )]), required: vec!["input".to_string()], additional_properties: Some(false), } } fn is_read_only(&self, _: &Value) -> bool { true } async fn call(&self, input: Value, _ctx: &ToolUseContext) -> Result { Ok(ToolResult::text("result")) } } // Use it let agent = Agent::new(AgentOptions { custom_tools: vec![Arc::new(MyTool)], ..Default::default() }).await.unwrap(); ``` ## Session Persistence ```rust use open_agent_sdk::session::*; // Save current session save_session(&session_data).await.unwrap(); // List all sessions let sessions = list_sessions().await.unwrap(); // Resume a session let data = load_session("session-id").await.unwrap(); // Fork a session let new_id = fork_session("session-id").await.unwrap(); ``` ## MCP Servers ```rust use open_agent_sdk::types::McpServerConfig; let agent = Agent::new(AgentOptions { mcp_servers: HashMap::from([( "filesystem".to_string(), McpServerConfig::Stdio { command: "npx".to_string(), args: vec!["-y".to_string(), "@modelcontextprotocol/server-filesystem".to_string(), "/tmp".to_string()], env: HashMap::new(), }, )]), ..Default::default() }).await.unwrap(); ``` ## Built-in Tools | Tool | Description | Read-Only | |------|-------------|-----------| | **Bash** | Execute shell commands | No | | **Read** | Read files with line numbers | Yes | | **Write** | Create/overwrite files | No | | **Edit** | String replacement in files | No | | **Glob** | File pattern matching | Yes | | **Grep** | Regex search (ripgrep) | Yes | | **NotebookEdit** | Edit Jupyter notebook cells | No | | **WebFetch** | Fetch URL content | Yes | | **WebSearch** | Web search (pluggable) | Yes | | **AskUserQuestion** | Interactive user prompts | No | | **SendMessage** | Inter-agent messaging | No | | **TeamCreate/Delete** | Multi-agent team management | No | | **EnterPlanMode/ExitPlanMode** | Structured planning mode | No | | **EnterWorktree/ExitWorktree** | Git worktree isolation | No | | **TodoWrite** | Session todo list | No | | **TaskCreate/Get/List/Update/Stop/Output** | Task tracking (6 tools) | Mixed | | **CronCreate/Delete/List** | Scheduled task management | Mixed | | **Config** | Session configuration | Mixed | | **LSP** | Language Server Protocol operations | Yes | | **ListMcpResources/ReadMcpResource** | MCP resource access | Yes | | **ToolSearch** | Discover available tools | Yes | ## Multi-Provider Support The SDK automatically detects which API format to use based on the model name: | Models | API Format | Auto-detected | |--------|-----------|---------------| | Claude (sonnet, opus, haiku) | Anthropic Messages | Yes | | GPT-4o, O1, O3, O4 | OpenAI Chat Completions | Yes | | DeepSeek, Qwen, Mistral | OpenAI Chat Completions | Yes | | LLaMA, Gemma, Gemini, Yi, GLM | OpenAI Chat Completions | Yes | Override with `CODEANY_API_TYPE=openai-completions` or `CODEANY_API_TYPE=anthropic-messages`. Works with any OpenAI-compatible endpoint (OpenRouter, vLLM, Ollama, LiteLLM, etc.): ```bash export CODEANY_BASE_URL=https://openrouter.ai/api export CODEANY_API_KEY=your-key export CODEANY_MODEL=anthropic/claude-sonnet-4 cargo run --example 01-simple-query ``` ## Architecture ``` open-agent-sdk-rust/ ├── src/ │ ├── agent/ # Agent loop, query engine, options │ ├── api/ # Multi-provider API abstraction │ │ ├── provider.rs # LLMProvider trait + auto-detection │ │ ├── anthropic.rs# Anthropic Messages API (SSE streaming) │ │ └── openai.rs # OpenAI Chat Completions API (SSE streaming) │ ├── types/ # Core types: Message, Tool, ContentBlock, MCP, Sandbox │ ├── tools/ # 25+ built-in tool implementations + registry + executor │ ├── mcp/ # MCP client (stdio, HTTP, SSE) + tool wrapping │ ├── permissions/ # Permission rules, filesystem validation │ ├── hooks/ # 20+ hook events with pre/post tool-use lifecycle │ ├── costtracker/ # Token usage and cost tracking (Anthropic, OpenAI, DeepSeek) │ ├── context/ # System/user context injection (git status, AGENT.md) │ ├── session/ # Session persistence (save, load, fork, resume) │ └── utils/ # Token estimation, retry, messages, compaction, file cache ├── tests/ # Comprehensive test suite (116 tests) └── examples/ # 11 runnable examples + web chat UI ``` ## Configuration Environment variables: | Variable | Description | | ---------------------------- | ----------------------------------------------------- | | `CODEANY_API_KEY` | API key (required) | | `CODEANY_MODEL` | Default model (default: `sonnet-4-6`) | | `CODEANY_BASE_URL` | API base URL override | | `CODEANY_API_TYPE` | Force API format: `anthropic-messages` or `openai-completions` | | `CODEANY_CUSTOM_HEADERS` | Custom headers (comma-separated `key:value`) | | `API_TIMEOUT_MS` | API request timeout in ms | | `HTTPS_PROXY` / `HTTP_PROXY` | Proxy URL | ## Links - Website: [codeany.ai](https://codeany.ai) - TypeScript SDK: [github.com/codeany-ai/open-agent-sdk-typescript](https://github.com/codeany-ai/open-agent-sdk-typescript) - Go SDK: [github.com/codeany-ai/open-agent-sdk-go](https://github.com/codeany-ai/open-agent-sdk-go) - Issues: [github.com/codeany-ai/open-agent-sdk-rust/issues](https://github.com/codeany-ai/open-agent-sdk-rust/issues) ## License MIT