Crate claude_code_agent_sdk

Crate claude_code_agent_sdk 

Source
Expand description

§Claude Agent SDK for Rust

Rust SDK for interacting with Claude Code CLI, enabling programmatic access to Claude’s capabilities with full bidirectional streaming support and 100% feature parity with the official Python SDK.

§Features

  • Simple Query API: One-shot queries with both collecting ([query]) and streaming (query_stream) modes
  • Bidirectional Streaming: Real-time streaming communication with ClaudeClient
  • Dynamic Control: Interrupt, change permissions, switch models mid-execution
  • Hooks System: Intercept and control Claude’s behavior at runtime with 6 hook types
  • Custom Tools: In-process MCP servers with ergonomic tool! macro
  • Plugin System: Load custom plugins to extend Claude’s capabilities
  • Permission Management: Fine-grained control over tool execution
  • Cost Control: Budget limits and fallback models for production reliability
  • Extended Thinking: Configure maximum thinking tokens for complex reasoning
  • Session Management: Resume, fork, and manage conversation sessions
  • Multimodal Input: Send images alongside text using base64 or URLs

§Quick Start

§Simple Query

use claude_agent_sdk_rs::{query, Message, ContentBlock};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // One-shot query that collects all messages
    let messages = query("What is 2 + 2?", None).await?;

    for message in messages {
        if let Message::Assistant(msg) = message {
            for block in &msg.message.content {
                if let ContentBlock::Text(text) = block {
                    println!("Claude: {}", text.text);
                }
            }
        }
    }

    Ok(())
}

§Streaming Query

use claude_agent_sdk_rs::{query_stream, Message, ContentBlock};
use futures::StreamExt;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Streaming query for memory-efficient processing
    let mut stream = query_stream("Explain Rust ownership", None).await?;

    while let Some(result) = stream.next().await {
        let message = result?;
        if let Message::Assistant(msg) = message {
            for block in &msg.message.content {
                if let ContentBlock::Text(text) = block {
                    println!("Claude: {}", text.text);
                }
            }
        }
    }

    Ok(())
}

§Bidirectional Client

use claude_agent_sdk_rs::{ClaudeClient, ClaudeAgentOptions, Message, PermissionMode};
use futures::StreamExt;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let options = ClaudeAgentOptions::builder()
        .permission_mode(PermissionMode::BypassPermissions)
        .max_turns(5)
        .build();

    let mut client = ClaudeClient::new(options);
    client.connect().await?;

    // Send query
    client.query("What is Rust?").await?;

    // Receive responses
    {
        let mut stream = client.receive_response();
        while let Some(result) = stream.next().await {
            match result? {
                Message::Assistant(msg) => {
                    println!("Got assistant message");
                }
                Message::Result(_) => break,
                _ => {}
            }
        }
    } // stream is dropped here

    client.disconnect().await?;
    Ok(())
}

§Multimodal Input (Images)

The SDK supports sending images alongside text in your prompts using structured content blocks. Both base64-encoded images and URL references are supported.

§Supported Formats

  • JPEG (image/jpeg)
  • PNG (image/png)
  • GIF (image/gif)
  • WebP (image/webp)

§Size Limits

  • Maximum base64 data size: 15MB (results in ~20MB decoded)
  • Large images may timeout or fail - resize before encoding

§Example: Query with Image

use claude_agent_sdk_rs::{query_with_content, UserContentBlock, Message, ContentBlock};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // For real usage, load and base64-encode an image file
    // This example uses a pre-encoded 1x1 red PNG pixel
    let base64_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";

    // Query with text and image
    let messages = query_with_content(vec![
        UserContentBlock::text("What color is this image?"),
        UserContentBlock::image_base64("image/png", base64_data)?,
    ], None).await?;

    for message in messages {
        if let Message::Assistant(msg) = message {
            for block in &msg.message.content {
                if let ContentBlock::Text(text) = block {
                    println!("Claude: {}", text.text);
                }
            }
        }
    }

    Ok(())
}

§Example: Using Image URLs

use claude_agent_sdk_rs::{query_with_content, UserContentBlock};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let messages = query_with_content(vec![
        UserContentBlock::text("Describe this architecture diagram"),
        UserContentBlock::image_url("https://example.com/diagram.png"),
    ], None).await?;

    Ok(())
}

§Example: Streaming with Images

use claude_agent_sdk_rs::{query_stream_with_content, UserContentBlock, Message, ContentBlock};
use futures::StreamExt;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Minimal 1x1 PNG for example purposes
    let png_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";

    let mut stream = query_stream_with_content(vec![
        UserContentBlock::image_base64("image/png", png_base64)?,
        UserContentBlock::text("What's in this image?"),
    ], None).await?;

    while let Some(result) = stream.next().await {
        let message = result?;
        if let Message::Assistant(msg) = message {
            for block in &msg.message.content {
                if let ContentBlock::Text(text) = block {
                    print!("{}", text.text);
                }
            }
        }
    }

    Ok(())
}

§Configuration

The SDK provides extensive configuration through ClaudeAgentOptions:

use claude_agent_sdk_rs::{ClaudeAgentOptions, PermissionMode, SdkPluginConfig};

let options = ClaudeAgentOptions::builder()
    .model("claude-opus-4")
    .fallback_model("claude-sonnet-4")
    .max_budget_usd(10.0)
    .max_thinking_tokens(2000)
    .max_turns(10)
    .permission_mode(PermissionMode::Default)
    .plugins(vec![SdkPluginConfig::local("./my-plugin")])
    .build();

§Examples

The SDK includes 22 comprehensive examples covering all features. See the examples directory for detailed usage patterns.

§Documentation

Re-exports§

pub use errors::ClaudeError;
pub use errors::ImageValidationError;
pub use errors::Result;
pub use types::mcp::McpServerConfig;
pub use types::mcp::McpServers;
pub use types::mcp::SdkMcpServer;
pub use types::mcp::SdkMcpTool;
pub use types::mcp::ToolDefinition;
pub use types::mcp::ToolHandler;
pub use types::mcp::ToolResult;
pub use types::mcp::ToolResultContent as McpToolResultContent;
pub use types::mcp::create_sdk_mcp_server;
pub use types::mcp::ACP_TOOL_PREFIX;
pub use types::mcp::acp_tool_name;
pub use types::mcp::is_acp_tool;
pub use types::mcp::strip_acp_prefix;
pub use client::ClaudeClient;
pub use query::query;
pub use query::query_stream;
pub use query::query_stream_with_content;
pub use query::query_with_content;
pub use types::config::*;
pub use types::hooks::*;
pub use types::messages::*;
pub use types::permissions::*;
pub use types::plugin::*;

Modules§

client
ClaudeClient for bidirectional streaming interactions with hook support
errors
Error types for the Claude Agent SDK
query
Simple query function for one-shot interactions
types
Type definitions for the Claude Agent SDK
version
Version information for the Claude Agent SDK

Macros§

tool
Macro to create a tool