Expand description
§Open Agent SDK - Rust Implementation
A production-ready, streaming-first Rust SDK for building AI agents over two wire protocols: OpenAI chat completions and Anthropic messages.
§Overview
The protocol is a property of the endpoint. Select it with
AgentOptions::builder().protocol(..); it defaults to ApiProtocol::OpenAiChat.
ApiProtocol::OpenAiChat posts to {base_url}/chat/completions with bearer auth:
- LM Studio, Ollama, llama.cpp, vLLM, and other local servers
- OpenAI, OpenRouter, z.ai, and other hosted OpenAI-compatible endpoints
ApiProtocol::Anthropic posts to {base_url}/messages with x-api-key and
anthropic-version:
- Anthropic
- Moonshot Kimi for Coding, MiniMax, and other Anthropic-shaped endpoints
§Key Features
- Two Wire Protocols: OpenAI chat completions or Anthropic messages, per endpoint
- Local or Hosted: Zero-cost inference on your own hardware, or a vendor endpoint
- High Performance: Native async/await with Tokio runtime
- Streaming Responses: Text and reasoning reach the caller fragment by fragment, while the stream is still open
- Finish Reasons: Every stream reports why generation stopped
- Reasoning Channel: Extended thinking and reasoning deltas kept out of content
- Tool Calling: Define and execute tools with automatic schema generation
- Lifecycle Hooks: Intercept and control execution at key points
- Interrupts: Gracefully cancel long-running operations
- Context Management: Manual token estimation and history truncation
- Retry Logic: Exponential backoff with jitter for reliability
§Two Interaction Modes
§1. Simple Query Function (query())
For single-turn interactions without conversation state:
use open_agent::{query, AgentOptions, ContentBlock, FinishReason, StreamEvent};
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure the agent with required settings
let options = AgentOptions::builder()
.system_prompt("You are a helpful assistant")
.model("qwen2.5-32b-instruct")
.base_url("http://localhost:1234/v1")
.build()?;
// Send a single query and stream the response
let mut stream = query("What's the capital of France?", &options).await?;
// Process each event as it arrives; the stream always ends with one Finish
while let Some(event) = stream.next().await {
match event? {
StreamEvent::Block(ContentBlock::Text(text_block)) => {
print!("{}", text_block.text);
}
StreamEvent::Block(ContentBlock::ToolUse(tool_block)) => {
println!("Tool called: {}", tool_block.name());
}
StreamEvent::Finish(FinishReason::Length) => {
eprintln!("response was truncated at the token cap");
}
_ => {}
}
}
Ok(())
}§2. Client Object (Client)
For multi-turn conversations with persistent state:
use open_agent::{Client, AgentOptions, ContentBlock};
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = AgentOptions::builder()
.system_prompt("You are a helpful assistant")
.model("qwen2.5-32b-instruct")
.base_url("http://localhost:1234/v1")
.build()?;
// Create a stateful client that maintains conversation history
let mut client = Client::new(options)?;
// First turn
client.send("What's 2+2?").await?;
while let Some(block) = client.receive().await? {
match block {
ContentBlock::Text(text) => print!("{}", text.text),
ContentBlock::ToolUse(_) | ContentBlock::ToolResult(_) | ContentBlock::Image(_) => {}
}
}
// Second turn - client remembers previous context
client.send("What about if we multiply that by 3?").await?;
while let Some(block) = client.receive().await? {
match block {
ContentBlock::Text(text) => print!("{}", text.text),
ContentBlock::ToolUse(_) | ContentBlock::ToolResult(_) | ContentBlock::Image(_) => {}
}
}
Ok(())
}§Architecture
The SDK is organized into several modules, each with a specific responsibility:
- client: Core streaming query engine and multi-turn client, and the transport boundary where the protocol is applied
- types: Data structures for messages, content blocks, configuration, and the OpenAI and Anthropic wire formats
- tools: Tool definition system with automatic JSON schema generation
- hooks: Lifecycle event system for intercepting execution
- config: Provider-specific configuration helpers
- error: Comprehensive error types and conversions
- context: Token estimation and message truncation utilities
- retry: Exponential backoff retry logic with jitter
- utils: Internal utilities for SSE parsing and tool aggregation
Modules§
- prelude
- Convenience module containing the most commonly used types and functions.
Import with
use open_agent::prelude::*;to get everything you need for typical usage. - retry
- Retry utilities with exponential backoff and jitter. Made public as a module so users can access retry configuration and functions for their own operations that need retry logic. Retry utilities with exponential backoff
Structs§
- Agent
Options - Configuration options for an AI agent instance.
- Agent
Options Builder - Builder for constructing
AgentOptionswith validation. - Anthropic
Error Body - The body of a mid-stream
errorevent. - Anthropic
Message - One conversation turn.
- Anthropic
Message Delta - Top-level message changes, carrying the reason generation stopped.
- Anthropic
Request - Request payload for
POST {base_url}/messages. - BaseUrl
- Validated base URL with compile-time type safety.
- Client
- Stateful client for multi-turn conversations with automatic history management.
- Hook
Decision - Decision returned by a hook handler to control agent execution flow.
- Hooks
- Container for registering and managing lifecycle hooks.
- Image
Block - Image content block for vision-capable models.
- Message
- A complete message in a conversation.
- Model
Name - Validated model name with compile-time type safety.
- OpenAI
Function - OpenAI function call details.
- OpenAI
Message - OpenAI
Request - Complete request payload for OpenAI chat completions API.
- OpenAI
Tool Call - OpenAI tool call representation in API messages.
- Post
Tool UseEvent - Event fired after a tool completes execution, enabling audit, filtering, or validation.
- PreTool
UseEvent - Event fired before a tool is executed, enabling validation, modification, or blocking.
- Temperature
- Validated temperature value with compile-time type safety.
- Text
Block - Simple text content in a message.
- Tool
- Tool definition for function calling, over either wire protocol.
- Tool
Builder - Builder for creating tools with a fluent API.
- Tool
Result Block - Tool execution result sent back to the model.
- Tool
UseBlock - Tool use request from the AI model.
- User
Prompt Submit Event - Event fired before processing user input, enabling content moderation and prompt enhancement.
Enums§
- Anthropic
Block Start - The declaration that opens a content block.
- Anthropic
Delta - One fragment appended to an open block.
- Anthropic
Event - One event from an Anthropic streaming response.
- ApiProtocol
- The wire protocol an endpoint exposes.
- Content
Block - Multi-modal content blocks that can appear in messages.
- Error
- Comprehensive error type covering all failure modes in the SDK.
- Finish
Reason - Why the model stopped generating.
- Image
Detail - Image detail level for vision API calls.
- Message
Role - Identifies the sender/role of a message in the conversation.
- OpenAI
Content - OpenAI API message format for serialization.
- OpenAI
Content Part - A single content part in an OpenAI message.
- Provider
- Enum representing supported local LLM server providers.
- Stream
Event - One item in the stream returned by
query().
Constants§
- HOOK_
POST_ TOOL_ USE - String constant for the PostToolUse hook event name.
- HOOK_
PRE_ TOOL_ USE - String constant for the PreToolUse hook event name.
- HOOK_
USER_ PROMPT_ SUBMIT - String constant for the UserPromptSubmit hook event name.
Functions§
- anthropic_
finish_ reason - Maps an Anthropic
stop_reasononto the SDK’s protocol-neutralFinishReason. - coalesce_
text_ blocks - Joins runs of adjacent
ContentBlock::Text, leaving every other block untouched. - estimate_
tokens - Estimate token count for message list
- get_
base_ url - Get the base URL for API requests with environment variable support.
- get_
model - Get the model name with optional environment variable override.
- is_
approaching_ limit - Check if history is approaching a token limit
- query
- Simple query function for single-turn interactions without conversation history.
- tool
- Create a tool using the builder pattern (convenience function).
- truncate_
messages - Truncate message history, keeping recent messages
Type Aliases§
- Event
Stream - A pinned, boxed stream of events from the model.
- Result
- Type alias for
Result<T, Error>used throughout the SDK.