### Running Claudius Examples via Cargo Source: https://github.com/rescrv/claudius/blob/main/README.md Provides instructions on how to execute the example Rust programs included in the Claudius repository. It covers setting the `CLAUDIUS_API_KEY` environment variable and then using `cargo run --example` commands for various examples like `basic_chat`, `streaming`, `agent`, `models_example`, and `retry_example`. ```bash # Set your API key export CLAUDIUS_API_KEY="your-api-key" # Run the basic chat example cargo run --example basic_chat # Run the streaming example cargo run --example streaming # Run the agent framework example cargo run --example agent # Run the models example cargo run --example models_example # Run the retry example cargo run --example retry_example ``` -------------------------------- ### Test Prompts with Claudius SDK (Rust and YAML) Source: https://context7.com/rescrv/claudius/llms.txt Provides examples for testing prompts using the Claudius SDK. Includes a programmatic approach in Rust and a configuration using YAML files. Also shows command-line execution for CI/CD integration. ```rust use claudius::{Anthropic, PromptTestConfig}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::new(None)?; // Programmatic test configuration let config = PromptTestConfig::new("What is 2 + 2?") .with_name("Simple Math Test") .with_model("claude-haiku-4-5") .with_max_tokens(50) .with_temperature(0.0) .expect_contains("4") .expect_not_contains("5") .with_min_length(1) .with_max_length(10); let result = config.run(&client).await?; println!("Response: {}", result.response); println!("Passed: {}", result.assertions_passed); println!("Duration: {:?}", result.duration); println!("Tokens: {} in, {} out", result.input_tokens, result.output_tokens); if !result.assertions_passed { for failure in &result.assertion_failures { eprintln!("Failed: {}", failure); } } Ok(()) } ``` ```yaml # prompts/math_test.yaml name: "Math Test" prompt: "What is 2 + 2?" model: "claude-haiku-4-5" max_tokens: 50 temperature: 0.0 system: "You are a helpful math assistant." expected_contains: - "4" expected_not_contains: - "5" min_response_length: 1 max_response_length: 10 ``` ```bash # Run prompt tests from command line cargo run --bin claudius-prompt -- prompts/math_test.yaml # Test mode with exit codes for CI/CD cargo run --bin claudius-prompt -- --test prompts/*.yaml # Verbose output with timing cargo run --bin claudius-prompt -- --verbose prompts/test.yaml ``` -------------------------------- ### Basic Chat Interaction with Claudius SDK Source: https://github.com/rescrv/claudius/blob/main/README.md Illustrates a basic chat interaction using the Claudius Rust SDK. This example shows how to create a client, formulate a user message, configure request parameters including a system prompt, send the request, and iterate through the content blocks of the response. ```rust // Create a client let client = Anthropic::new(None)?; // Uses CLAUDIUS_API_KEY env var and falls back to ANTHROPIC_API_KEY // Create a user message let message = MessageParam::new_with_string( "What are three interesting facts about rust programming language?", MessageRole::User, ); // Set up request parameters let params = MessageCreateParams::new( 1000, // max_tokens vec![message], Model::Known(KnownModel::Claude37SonnetLatest), ) .with_system_string("Be concise and informative.".to_string()); // Send the request and get the response let response = client.send(params).await?; // Process the response for content in response.content { match content { ContentBlock::Text(text_block) => { println!("{}", text_block.text); } _ => println!("Received non-text content block"), } } ``` -------------------------------- ### Rust Custom Tool Implementation Source: https://context7.com/rescrv/claudius/llms.txt Shows how to implement a custom tool for agents using the `claudius::Tool` trait in Rust. This example defines a `WeatherTool` that simulates fetching weather information for a given location. It includes defining the tool's name, callback logic for computing results, and its parameter schema for agent interaction. Dependencies include `claudius`, `async_trait`, and `serde`. ```rust use std::ops::ControlFlow; use std::sync::Arc; use claudius::{ Agent, Anthropic, Tool, ToolCallback, ToolResult, ToolUnionParam, ToolParam, ToolUseBlock, ToolResultBlock, ToolResultBlockContent, IntermediateToolResult, }; struct WeatherTool; #[async_trait::async_trait] impl ToolCallback for WeatherTool { async fn compute_tool_result( &self, _client: &Anthropic, _agent: &A, tool_use: &ToolUseBlock, ) -> Box { #[derive(serde::Deserialize)] struct WeatherInput { location: String } let input: WeatherInput = match serde_json::from_value(tool_use.input.clone()) { Ok(i) => i, Err(e) => return Box::new(ControlFlow::Continue(Err(ToolResultBlock { tool_use_id: tool_use.id.clone(), content: Some(ToolResultBlockContent::String(e.to_string())), is_error: Some(true), cache_control: None, }))), }; // Simulate weather lookup let weather = format!("Weather in {}: 72°F, Sunny", input.location); Box::new(ControlFlow::Continue(Ok(ToolResultBlock { tool_use_id: tool_use.id.clone(), content: Some(ToolResultBlockContent::String(weather)), is_error: None, cache_control: None, }))) } async fn apply_tool_result( &self, _client: &Anthropic, _agent: &mut A, _tool_use: &ToolUseBlock, intermediate: Box, ) -> ToolResult { intermediate.as_any().downcast_ref::() .cloned() .unwrap_or(ControlFlow::Break(claudius::Error::unknown("downcast failed"))) } } impl Tool for WeatherTool { fn name(&self) -> String { "get_weather".to_string() } fn callback(&self) -> Box + '_> { Box::new(WeatherTool) } fn to_param(&self) -> ToolUnionParam { ToolUnionParam::CustomTool(ToolParam { name: "get_weather".to_string(), description: Some("Get current weather for a location".to_string()), input_schema: serde_json::json!({ "type": "object", "properties": { "location": { "type": "string", "description": "City name or location" } }, "required": ["location"] }), cache_control: None, strict: None, }) } } ``` -------------------------------- ### Get Model Information with Claudius SDK Source: https://context7.com/rescrv/claudius/llms.txt Shows how to retrieve information about available models using the Claudius SDK. This includes listing all models, paginating through the model list, and fetching details for a specific model. ```rust use claudius::{Anthropic, ModelListParams, Result}; #[tokio::main] async fn main() -> Result<()> { let client = Anthropic::new(None)?; // List all available models let response = client.list_models(None).await?; for model in &response.data { println!("Model: {} ({})", model.id, model.display_name); } // Paginate through models let params = ModelListParams { limit: Some(10), after_id: None, before_id: None, }; let page = client.list_models(Some(params)).await?; // Get specific model info let model = client.get_model("claude-3-5-sonnet-20241022").await?; println!("Model: {}", model.display_name); println!("Created: {:?}", model.created_at); Ok(()) } ``` -------------------------------- ### GET /v1/models Source: https://context7.com/rescrv/claudius/llms.txt Retrieves a list of available models or details for a specific model ID. ```APIDOC ## GET /v1/models ### Description Lists available models or retrieves metadata for a specific model. ### Method GET ### Endpoint /v1/models ### Query Parameters - **limit** (integer) - Optional - Number of models to return. - **after_id** (string) - Optional - Cursor for pagination. ### Response #### Success Response (200) - **data** (array) - List of model objects containing id, display_name, and created_at. ### Response Example { "data": [ { "id": "claude-3-5-sonnet-20241022", "display_name": "Claude 3.5 Sonnet" } ] } ``` -------------------------------- ### Build AI Applications with Agent Framework in Rust Source: https://context7.com/rescrv/claudius/llms.txt Illustrates how to use the Agent framework in Rust for building AI-powered applications. It covers automatic message management, tool use handling, and budget tracking, along with setting up a custom agent with filesystem access. ```rust use std::sync::Arc; use claudius::{ Agent, Anthropic, Budget, FileSystem, MessageParam, MessageParamContent, MessageRole, Model, KnownModel, SystemPrompt, }; use utf8path::Path; struct MyAgent { root: Path<'static>, } #[async_trait::async_trait] impl Agent for MyAgent { async fn filesystem(&self) -> Option<&dyn FileSystem> { Some(&self.root) // Path implements FileSystem } async fn system(&self) -> Option { Some(SystemPrompt::from_string( "You are a helpful assistant with filesystem access.".to_string() )) } async fn model(&self) -> Model { Model::Known(KnownModel::ClaudeSonnet40) } async fn max_tokens(&self) -> u32 { 4096 } } #[tokio::main] async fn main() -> claudius::Result<()> { let client = Anthropic::new(None)?; let budget = Arc::new(Budget::from_dollars_flat_rate(0.25, 1000)); let mut agent = MyAgent { root: Path::from("./workspace"), }; // Initialize conversation let mut messages = vec![MessageParam { role: MessageRole::User, content: MessageParamContent::String( "Search for any .rs files and show me their contents.".to_string() ), }]; // Agent handles tool calls automatically let outcome = agent.take_turn(&client, &mut messages, &budget).await?; println!("Stop reason: {:?}", outcome.stop_reason); println!("Total tokens: {} in, {} out", outcome.usage.input_tokens, outcome.usage.output_tokens ); println!("API requests: {}", outcome.request_count); Ok(()) } ``` -------------------------------- ### Create and Authenticate Anthropic Client in Rust Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to initialize the Anthropic client in Rust, handling authentication via environment variables or direct API keys. It also shows how to configure custom base URLs, timeouts, and retry policies for robust API interaction. ```Rust use claudius::{Anthropic, Result}; use std::time::Duration; #[tokio::main] async fn main() -> Result<()> { // Create client using CLAUDIUS_API_KEY or ANTHROPIC_API_KEY env var let client = Anthropic::new(None)?; // Or provide API key directly let client = Anthropic::new(Some("your-api-key".to_string()))?; // Configure custom base URL (for Minimax or other providers) let client = Anthropic::new(None)? .with_base_url("https://api.minimax.io/anthropic".to_string()); // Configure timeout and retry settings let client = Anthropic::new(None)? .with_timeout(Duration::from_secs(60))? .with_max_retries(5) .with_backoff_params(1.0 / 60.0, 1.0 / 60.0); Ok(()) } ``` -------------------------------- ### Mount Hierarchy for Filesystem Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to create a mount hierarchy with different permissions for controlled access to filesystem paths. ```APIDOC ## Mount Hierarchy for Filesystem Create layered filesystem mounts with different permissions for controlled access. ### Description This example shows how to initialize a `MountHierarchy`, add multiple mounts with varying permissions (ReadOnly, ReadWrite, WriteOnly), and then interact with these mounts to perform operations like viewing file content or attempting to modify files on read-only mounts. ### Method N/A (This is a library usage example, not a direct API endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example ```rust use claudius::{MountHierarchy, Permissions, FileSystem}; use utf8path::Path; #[tokio::main] async fn main() -> Result<(), String> { let mut hierarchy = MountHierarchy::default(); // First mount must be root hierarchy.mount( "/".into(), Permissions::ReadOnly, Path::from("/var/data"), )?; // Add more specific mounts hierarchy.mount( "/workspace".into(), Permissions::ReadWrite, Path::from("/home/user/project"), )?; hierarchy.mount( "/logs".into(), Permissions::WriteOnly, Path::from("/var/log/app"), )?; // Use with agent - operations route to appropriate mount let content = hierarchy.view("/workspace/src/main.rs", None).await.unwrap(); println!("{}", content); // Read-only mount prevents writes let result = hierarchy.str_replace("/config.toml", "old", "new").await; assert!(result.is_err()); // PermissionDenied Ok(()) } ``` ### Response N/A (This is a library usage example) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Budget Management in Claudius Source: https://github.com/rescrv/claudius/blob/main/README.md Explains how to use the `Budget` system for token allocation and tracking. It shows how to create a budget, allocate tokens for a request, consume tokens from an allocation, and how remaining tokens are automatically returned. ```rust use claudius::Budget; use std::sync::Arc; // Create a budget with 1000 tokens let budget = Arc::new(Budget::new(1000)); // Allocate tokens for a request if let Some(mut allocation) = budget.allocate(500) { // Use tokens as needed let consumed = allocation.consume(200); // Returns true if successful println!("Consumed 200 tokens: {}", consumed); // Remaining tokens are automatically returned when allocation is dropped } // Check remaining budget (approximately, due to concurrent access) ``` -------------------------------- ### Initialize and Send Message with Claudius SDK Source: https://github.com/rescrv/claudius/blob/main/README.md Demonstrates how to initialize the Claudius client, create a user message, set up request parameters for the Anthropic API, send the request, and process the text response. It utilizes the `tokio` runtime for asynchronous operations. ```rust use claudius:: Anthropic, ContentBlock, KnownModel, MessageCreateParams, MessageParam, MessageRole, Model, TextBlock, ; use tokio; #[tokio::main] async fn main() -> claudius::Result<()> { // Initialize the client (uses CLAUDIUS_API_KEY or ANTHROPIC_API_KEY environment variable) let client = Anthropic::new(None)?; // Create a message from the user let message = MessageParam::new_with_string( "Explain the significance of the name 'Claudius' in Roman history.", MessageRole::User, ); // Set up request parameters let params = MessageCreateParams::new( 1000, // max tokens vec![message], Model::Known(KnownModel::Claude37SonnetLatest), ) .with_system_string("You are Claude, an AI assistant made by Anthropic.".to_string()); // Send the request let response = client.send(params).await?; // Process the response if let Some(content) = response.content.first() { match content { ContentBlock::Text(TextBlock { text, .. }) => { println!("Claude's response: {}", text); } _ => println!("Received non-text content block"), } } Ok(()) } ``` -------------------------------- ### Configure Mount Hierarchy in Rust Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to initialize a MountHierarchy, define root and sub-directory mounts with specific permissions, and perform file operations. It highlights how the hierarchy enforces permission constraints, such as preventing writes to read-only mounts. ```rust use claudius::{MountHierarchy, Permissions, FileSystem}; use utf8path::Path; #[tokio::main] async fn main() -> Result<(), String> { let mut hierarchy = MountHierarchy::default(); // First mount must be root hierarchy.mount( "/".into(), Permissions::ReadOnly, Path::from("/var/data"), )?; // Add more specific mounts hierarchy.mount( "/workspace".into(), Permissions::ReadWrite, Path::from("/home/user/project"), )?; hierarchy.mount( "/logs".into(), Permissions::WriteOnly, Path::from("/var/log/app"), )?; // Use with agent - operations route to appropriate mount let content = hierarchy.view("/workspace/src/main.rs", None).await.unwrap(); println!("{}", content); // Read-only mount prevents writes let result = hierarchy.str_replace("/config.toml", "old", "new").await; assert!(result.is_err()); // PermissionDenied Ok(()) } ``` -------------------------------- ### Configure Base URL for Third-Party Providers Source: https://github.com/rescrv/claudius/blob/main/README.md Shows how to configure the client for third-party providers like Minimax. The client appends /v1/ to the provided base URL, enabling correct routing to the provider's API endpoints. ```rust // Now works correctly with Minimax let client = Anthropic::new(None)? .with_base_url("https://api.minimax.io/anthropic".to_string()); // Requests go to: https://api.minimax.io/anthropic/v1/messages ``` -------------------------------- ### Basic Agent Usage Source: https://github.com/rescrv/claudius/blob/main/README.md Demonstrates the fundamental usage of the Claudius agent framework. It initializes a simple agent, sets up a conversation with user messages, and allows the agent to take its turn, updating the message history. ```rust use claudius::{Agent, Anthropic, Budget, MessageParam, MessageParamContent, MessageRole}; use std::sync::Arc; #[tokio::main] async fn main() -> claudius::Result<()> { let client = Anthropic::new(None)?; let budget = Arc::new(Budget::new(2048)); // 2048 token budget // Use the unit type as a basic agent let agent = (); // Initialize conversation let mut messages = vec![MessageParam { role: MessageRole::User, content: MessageParamContent::String("Hello! How can you help me today?".to_string()), }]; // Let the agent take a turn agent.take_turn(&client, &mut messages, &budget).await?; // Messages now contain the full conversation history println!("Conversation has {} messages", messages.len()); Ok(()) } ``` -------------------------------- ### Programmatic Prompt Testing in Rust Source: https://github.com/rescrv/claudius/blob/main/README.md Demonstrates how to programmatically run prompt tests using the Claudius Rust library. It covers creating a test configuration with various assertion types and executing the test against an Anthropic client. The output includes test results, assertion status, and token usage. ```rust use claudius::{Anthropic, PromptTestConfig}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::new(None)?; // Create a test configuration let config = PromptTestConfig::new("What is 2 + 2?") .with_name("Simple Math Test") .with_model("claude-haiku-4-5") .with_max_tokens(50) .with_temperature(0.0) .expect_contains("4") .expect_not_contains("5") .with_min_length(1) .with_max_length(10); // Run the test let result = config.run(&client).await?; // Check results println!("Response: {}", result.response); println!("Assertions passed: {}", result.assertions_passed); println!("Duration: {:?}", result.duration); println!("Input tokens: {}", result.input_tokens); println!("Output tokens: {}", result.output_tokens); if !result.assertions_passed { for failure in &result.assertion_failures { eprintln!("Assertion failed: {}", failure); } } Ok(()) } ``` -------------------------------- ### CI/CD Integration with claudius-prompt Binary Source: https://github.com/rescrv/claudius/blob/main/README.md Shows how to integrate the `claudius-prompt` binary into a CI/CD pipeline, specifically for GitHub Actions. It demonstrates running prompt tests using a wildcard pattern for YAML files and setting the necessary API key environment variable. The binary's exit codes facilitate automated pipeline success/failure detection. ```yaml # .github/workflows/prompt-tests.yml - name: Run prompt tests run: | cargo run --bin claudius-prompt -- --test --verbose prompts/*.yaml env: CLAUDIUS_API_KEY: ${{ secrets.CLAUDIUS_API_KEY }} ``` -------------------------------- ### Implement Budget Management System in Rust Source: https://context7.com/rescrv/claudius/llms.txt Shows how to implement a thread-safe budget management system for API usage costs using micro-cent precision to prevent floating-point errors. It includes creating budgets with custom token rates and allocating/consuming usage. ```rust use claudius::{Budget, Usage}; use std::sync::Arc; fn main() { // Create a $5.00 budget with realistic token rates (micro-cents per token) let budget = Arc::new(Budget::from_dollars_with_rates( 5.0, // $5.00 total budget 300, // ~$0.0003 per input token 1500, // ~$0.0015 per output token 150, // ~$0.00015 per cache creation token 75, // ~$0.000075 per cache read token )); // Allocate budget for API call (reserves max possible cost) if let Some(mut allocation) = budget.allocate(1000) { println!("Allocated for {} tokens", allocation.remaining_tokens()); // Simulate API response with actual usage let usage = Usage::new(150, 75) .with_cache_read_input_tokens(50); // Consume actual cost (unused allocation returned on drop) if allocation.consume_usage(&usage) { println!("Consumed budget for actual usage"); } } else { println!("Insufficient budget"); } // Check remaining budget let remaining_dollars = budget.remaining_micro_cents() as f64 / 100_000_000.0; println!("Remaining: ${:.4}", remaining_dollars); // Simple flat-rate budget let simple_budget = Budget::from_dollars_flat_rate(1.0, 500); assert_eq!(simple_budget.remaining_micro_cents(), 100_000_000); } ``` -------------------------------- ### Advanced Client Configuration Source: https://github.com/rescrv/claudius/blob/main/README.md Shows how to customize the Claudius client with a custom base URL, timeout, and how to configure request parameters like system prompts, temperature, top_p, top_k, and stop sequences. ```rust use claudius::{Anthropic, MessageCreateParams, Model, KnownModel, MessageParamContent, MessageRole}; use std::time::Duration; // Assuming 'message' is defined // let message = MessageParam { ... }; // let model = Model::Known(KnownModel::Claude37SonnetLatest); // Customize the client let client = Anthropic::new(Some("your-api-key".to_string()))? .with_base_url("https://custom-api.example.com".to_string()) .with_timeout(Duration::from_secs(60))?; // Use with Minimax (international) let client_minimax_intl = Anthropic::new(Some("your-api-key".to_string()))? .with_base_url("https://api.minimax.io/anthropic".to_string()); // Use with Minimax (China) let client_minimax_china = Anthropic::new(Some("your-api-key".to_string()))? .with_base_url("https://api.minimaxi.com/anthropic".to_string()); // Configure request parameters let params = MessageCreateParams::new( 1000, // max_tokens vec![MessageParam { role: MessageRole::User, content: MessageParamContent::String("Hello".to_string()) }], Model::Known(KnownModel::Claude37SonnetLatest), ) .with_system_string("You are Claude, an AI assistant...".to_string()) .with_temperature(0.7) .with_top_p(0.9) .with_top_k(40) .with_stop_sequences(vec!["END".to_string()]); ``` -------------------------------- ### Execute Claudius Prompt Tests via CLI Source: https://github.com/rescrv/claudius/blob/main/prompts/README.md Demonstrates various ways to run prompt tests using the cargo binary, including running single or multiple files, enabling test mode for exit codes, and specifying output formats. ```bash cargo run --bin claudius-prompt -- prompts/simple_math.yaml cargo run --bin claudius-prompt -- prompts/simple_math.yaml prompts/creative_writing.yaml cargo run --bin claudius-prompt -- --test prompts/simple_math.yaml cargo run --bin claudius-prompt -- --verbose prompts/simple_math.yaml cargo run --bin claudius-prompt -- --format json prompts/simple_math.yaml cargo run --bin claudius-prompt -- --format yaml prompts/simple_math.yaml ``` -------------------------------- ### Configure Base URL for Anthropic SDK Source: https://github.com/rescrv/claudius/blob/main/README.md Demonstrates the updated method for setting the base URL in the Anthropic client. The /v1/ suffix is now handled automatically by the client, allowing for cleaner configuration. ```rust // New format - base URL only, /v1/ is added automatically let client = Anthropic::new(None)? .with_base_url("https://api.anthropic.com".to_string()); ``` -------------------------------- ### Custom Agent with Filesystem Access Source: https://github.com/rescrv/claudius/blob/main/README.md Shows how to create a custom agent that has access to the filesystem. The `MyAgent` struct implements the `Agent` trait, providing a `filesystem` method that returns a reference to a `Path` object, enabling file operations. ```rust use claudius::{Agent, FileSystem, Anthropic, Budget, SystemPrompt}; use utf8path::Path; use std::sync::Arc; struct MyAgent { root: Path<'static>, } #[async_trait::async_trait] impl Agent for MyAgent { async fn filesystem(&self) -> Option<&dyn FileSystem> { Some(&self.root) // Path implements FileSystem } async fn system(&self) -> Option { Some(SystemPrompt::from_string( "You are a helpful assistant with access to the filesystem.".to_string() )) } } #[tokio::main] async fn main() -> claudius::Result<()> { let agent = MyAgent { root: Path::from("./workspace"), }; let client = Anthropic::new(None)?; let budget = Arc::new(Budget::new(4096)); let mut messages = vec![MessageParam { role: MessageRole::User, content: MessageParamContent::String( "Can you search for any .rs files and show me their contents?".to_string() ), }]; agent.take_turn(&client, &mut messages, &budget).await?; Ok(()) } ``` -------------------------------- ### Define Custom Tools in YAML Configuration Source: https://github.com/rescrv/claudius/blob/main/prompts/README.md Shows how to define a custom tool using JSON Schema within the YAML configuration file, including tool choice settings and expected tool call assertions. ```yaml tools: - type: "custom" name: "calculator" description: "Performs arithmetic operations" input_schema: type: "object" properties: operation: type: "string" enum: ["add", "subtract", "multiply", "divide"] a: type: "number" b: type: "number" required: ["operation", "a", "b"] tool_choice: type: "auto" expected_tool_calls: - "calculator" ``` -------------------------------- ### Agent Framework API Source: https://context7.com/rescrv/claudius/llms.txt High-level abstractions for building AI agents with tool and filesystem capabilities. ```APIDOC ## Agent Framework ### Description Defines the `Agent` trait for building AI applications that handle message management, tool use, and budget tracking automatically. ### Implementation - **filesystem**: Returns a `FileSystem` implementation for the agent. - **system**: Defines the system prompt for the agent. - **take_turn**: Executes an agent turn, handling tool calls and budget updates. ### Example ```rust #[async_trait::async_trait] impl Agent for MyAgent { async fn model(&self) -> Model { Model::Known(KnownModel::ClaudeSonnet40) } async fn take_turn(&self, client: &Anthropic, messages: &mut Vec, budget: &Budget) -> Result { ... } } ``` ``` -------------------------------- ### Implementing Custom Tools in Rust Source: https://github.com/rescrv/claudius/blob/main/README.md Provides a template for creating custom tools within the Claudius framework by implementing the `Tool` trait in Rust. It outlines the required methods: `name`, `callback` (for tool logic), and `to_param` (for defining the tool's parameter schema). This enables extending Claudius with custom functionalities. ```rust use claudius::{Tool, ToolUnionParam, ToolResultCallback, Agent}; struct MyCustomTool; impl Tool for MyCustomTool { fn name(&self) -> String { "my_custom_tool".to_string() } fn callback(&self) -> ToolResultCallback { Box::new(|tool_use| { Box::pin(async move { // Your tool implementation here // Return a ToolResultApplier }) }) } fn to_param(&self) -> ToolUnionParam { // Define the tool's parameter schema } } ``` -------------------------------- ### YAML Prompt Test Configuration Source: https://github.com/rescrv/claudius/blob/main/README.md YAML files define prompt tests with configurations for model, system prompts, and assertions. Supported assertions include checking for expected content, disallowing specific content, and validating response length. Advanced features include multi-turn conversations, tool usage, and configuration inheritance. ```yaml name: "Simple Math Test" prompt: "What is 2 + 2? Please respond with just the number." model: "claude-haiku-4-5" max_tokens: 50 temperature: 0.0 system: "You are a helpful math assistant." # Assertion configuration expected_contains: - "4" expected_not_contains: - "5" - "3" min_response_length: 1 max_response_length: 10 ``` ```yaml name: "Multi-turn Conversation Test" messages: - role: "user" content: "I'm learning Rust programming." - role: "assistant" content: "That's great! What would you like to learn about first?" - role: "user" content: "Tell me about ownership and borrowing." system: "You are a helpful Rust programming tutor." model: "claude-haiku-4-5" max_tokens: 400 temperature: 0.3 expected_contains: - "ownership" - "borrowing" expected_not_contains: - "garbage collection" min_response_length: 100 ``` ```yaml #base.yaml name: "Base Configuration" model: "claude-haiku-4-5" max_tokens: 100 temperature: 0.5 system: "You are a helpful assistant." # specific_test.yaml inherits: "../base.yaml" name: "Specific Test" prompt: "What is the capital of France?" expected_contains: - "Paris" ``` ```yaml # Using external files for prompt and system content name: "File Reference Test" prompt: "prompt.yaml" # Contents loaded from prompt.yaml system: "system.md" # Contents loaded from system.md model: "claude-haiku-4-5" max_tokens: 400 expected_contains: - "helpful" ``` ```yaml # In subdirectory: prompts/test.yaml name: "Modular Configuration" prompt: "prompt.yaml" # Loaded from prompts/prompt.yaml system: "../common/system.md" # Loaded from common/system.md inherits: "../base.yaml" # Configuration inheritance ``` -------------------------------- ### Add Claudius Dependency to Cargo.toml Source: https://github.com/rescrv/claudius/blob/main/README.md Shows how to add the Claudius Rust SDK as a dependency to your project by including it in the `Cargo.toml` file. ```toml [dependencies] claudius = "0.16.0" ``` -------------------------------- ### Rust FileSystem Operations Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates various file system operations using the `claudius::FileSystem` trait in Rust. This includes searching for text, viewing file content (full or line ranges), replacing text, inserting text at a specific line, and creating new files. It requires the `claudius` and `utf8path` crates. ```rust use claudius::FileSystem; use utf8path::Path; #[tokio::main] async fn main() -> std::io::Result<()> { let base = Path::from("./project"); // Search files for text pattern let results = base.search("function").await?; println!("Search results:\n{}", results); // View file contents (full file) let content = base.view("src/main.rs", None).await?; println!("File content:\n{}", content); // View specific line range (1-based, inclusive) let lines = base.view("src/main.rs", Some((10, 20))).await?; println!("Lines 10-20:\n{}", lines); // Replace text in file (must match exactly once) base.str_replace("config.toml", "old_value", "new_value").await?; // Insert text at line (0 prepends, 1 inserts after first line) base.insert("notes.txt", 5, "New line content").await?; // Create new file (fails if exists) base.create("new_file.txt", "Initial content").await?; Ok(()) } ``` -------------------------------- ### Provide API Key Directly to Claudius Client Source: https://github.com/rescrv/claudius/blob/main/README.md Illustrates how to provide the Anthropic API key directly as a string argument when initializing the Claudius client. ```rust let client = Anthropic::new(Some("your-api-key".to_string()))?; ``` -------------------------------- ### Basic Chat Completion with Claudius SDK in Rust Source: https://context7.com/rescrv/claudius/llms.txt Shows how to send messages to the Anthropic API using the Claudius Rust SDK and receive non-streaming responses. It illustrates both a verbose API for detailed control and a simple API for common use cases, including system prompts and temperature settings. ```Rust use claudius::{ Anthropic, ContentBlock, KnownModel, MessageCreateParams, MessageParam, MessageRole, Model, Result, TextBlock, }; #[tokio::main] async fn main() -> Result<()> { let client = Anthropic::new(None)?; // Verbose API for full control let message = MessageParam::new_with_string( "What are three interesting facts about Rust?".to_string(), MessageRole::User, ); let params = MessageCreateParams::new( 1000, // max_tokens vec![message], Model::Known(KnownModel::Claude37SonnetLatest), ) .with_system_string("Be concise and informative.".to_string()) .with_temperature(0.7); let response = client.send(params).await?; // Process response content blocks for content in response.content { match content { ContentBlock::Text(TextBlock { text, .. }) => { println!("{}", text); } _ => println!("Received non-text content"), } } // Ergonomic simple API let params = MessageCreateParams::simple( "Tell me a joke about programming.", KnownModel::Claude37SonnetLatest, ) .with_system("You are a friendly assistant."); let response = client.send(params).await?; println!("Response ID: {}", response.id); println!("Input tokens: {}", response.usage.input_tokens); println!("Output tokens: {}", response.usage.output_tokens); Ok(()) } ``` -------------------------------- ### Count Tokens with Claudius SDK Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to use the Claudius SDK to count tokens for a given set of messages. This is useful for estimating API costs and validating context length before making actual API calls. ```rust use claudius::{ Anthropic, KnownModel, MessageCountTokensParams, MessageParam, MessageRole, Model, Result, }; #[tokio::main] async fn main() -> Result<()> { let client = Anthropic::new(None)?; let messages = vec![ MessageParam::new_with_string( "Hello, can you help me understand Rust?".to_string(), MessageRole::User, ), ]; let params = MessageCountTokensParams { model: Model::Known(KnownModel::Claude37SonnetLatest), messages, system: None, tools: None, tool_choice: None, thinking: None, }; let count = client.count_tokens(params).await?; println!("Input tokens: {}", count.input_tokens); Ok(()) } ``` -------------------------------- ### Rust Filesystem Operations for Agents Source: https://github.com/rescrv/claudius/blob/main/README.md Agents can perform common filesystem operations using the FileSystem trait. This includes searching for text within files, viewing file contents, replacing text, and inserting text at specific lines. These operations are asynchronous and return a Result. ```rust // Through the FileSystem trait, agents can: agent.search("function").await?; // Search for text in files agent.view("src/main.rs", None).await?; // View file contents agent.str_replace("config.toml", "old", "new").await?; // Replace text agent.insert("notes.txt", 5, "New line").await?; // Insert at line ``` -------------------------------- ### Streaming Responses with Claudius Source: https://github.com/rescrv/claudius/blob/main/README.md Demonstrates how to create streaming request parameters, obtain a stream of events from the client, and process these events incrementally. It handles different event types such as content block deltas for text updates. ```rust use claudius::MessageCreateParams; use claudius::Model; use claudius::KnownModel; use futures::StreamExt; use tokio::pin; // Assuming 'client' and 'message' are already defined // let client = Anthropic::new(Some("your-api-key".to_string()))?; // let message = MessageParam { ... }; // Create streaming request parameters let params = MessageCreateParams::new_streaming( 1000, // max_tokens vec![message], Model::Known(KnownModel::Claude37SonnetLatest), ); // Get a stream of events let mut stream = client.stream(params).await?; // Pin the stream so it can be polled pin!(stream); // Process the stream events while let Some(event) = stream.next().await { match event { Ok(event) => { // Handle different event types match event { claudius::MessageStreamEvent::ContentBlockDelta(delta) => { // Process incremental text updates // ... } // Handle other event types _ => {} } } Err(e) => { eprintln!("Error: {}", e); } } } ``` -------------------------------- ### Bash claudius-prompt for Prompt Testing Source: https://github.com/rescrv/claudius/blob/main/README.md The `claudius-prompt` binary is a command-line interface for testing prompts against the Anthropic API. It supports various modes including basic text prompts, YAML configurations with assertions, verbose output, and different output formats, making it suitable for CI/CD integration. ```bash # Run a simple text prompt file cargo run --bin claudius-prompt -- prompts/basic_hello.txt # Run a YAML configuration with assertions cargo run --bin claudius-prompt -- prompts/simple_math.yaml # Run multiple tests cargo run --bin claudius-prompt -- prompts/test1.yaml prompts/test2.yaml # Test mode with exit codes (useful for CI/CD) cargo run --bin claudius-prompt -- --test prompts/*.yaml # Get verbose output with timing and token information cargo run --bin claudius-prompt -- --verbose prompts/simple_math.yaml # Output in different formats cargo run --bin claudius-prompt -- --format json prompts/test.yaml cargo run --bin claudius-prompt -- --format yaml prompts/test.yaml ``` -------------------------------- ### Streaming Responses with Claudius SDK in Rust Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to handle real-time responses from the Anthropic API using the streaming capabilities of the Claudius Rust SDK. It shows how to process incremental content updates as the model generates them, suitable for interactive applications. ```Rust use claudius::{Anthropic, KnownModel, MessageCreateParams, MessageStreamEvent, Result}; use futures::StreamExt; use tokio::pin; #[tokio::main] async fn main() -> Result<()> { let client = Anthropic::new(None)?; let params = MessageCreateParams::simple_streaming( "Write a haiku about Rust programming.", KnownModel::Claude37SonnetLatest, ) .with_system("You are a creative poet."); let stream = client.stream(¶ms).await?; pin!(stream); println!("Streaming response:"); while let Some(event) = stream.next().await { match event { Ok(MessageStreamEvent::ContentBlockDelta(delta)) => { // Handle incremental text updates if let claudius::ContentBlockDelta::TextDelta(text_delta) = delta.delta { print!("{}", text_delta.text); } } Ok(MessageStreamEvent::MessageStart(start)) => { println!("Message started: {}", start.message.id); } Ok(MessageStreamEvent::MessageStop(_)) => { println!("\nMessage complete."); } Ok(_) => {} // Handle other event types Err(e) => eprintln!("Stream error: {}", e), } } Ok(()) } ``` -------------------------------- ### Rust Bash Tool for Shell Commands Source: https://github.com/rescrv/claudius/blob/main/README.md The ToolBash20250124 allows agents to execute shell commands directly. This tool is integrated into agent workflows, enabling programmatic interaction with the operating system's command line. ```rust use claudius::{ToolBash20250124, Tool}; // Execute shell commands let bash_tool = ToolBash20250124::new(); // Integrated into agent workflows ``` -------------------------------- ### Set Anthropic API Key Environment Variable Source: https://github.com/rescrv/claudius/blob/main/README.md Demonstrates how to set the Anthropic API key as an environment variable, which the Claudius SDK can use for authentication. ```bash export ANTHROPIC_API_KEY="your-api-key" ``` -------------------------------- ### Select Anthropic Models in Rust Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to select Anthropic models using typed enums or custom identifiers in Rust. Supports latest versions, specific versions, and custom model names. ```rust use claudius::{KnownModel, Model}; // Use latest version of a model let model = Model::Known(KnownModel::Claude37SonnetLatest); let model = Model::Known(KnownModel::ClaudeSonnet40); // Use specific model version let model = Model::Known(KnownModel::Claude37Sonnet20250219); // Use custom model identifier let model = Model::Custom("custom-model-id".to_string()); // Available known models: // - Claude37SonnetLatest, Claude37Sonnet20250219 // - ClaudeSonnet40 // - ClaudeOpusLatest, Claude3Opus20240229 // - ClaudeHaiku35Latest, Claude35Haiku20241022 ``` -------------------------------- ### Model Selection in Claudius Source: https://github.com/rescrv/claudius/blob/main/README.md Illustrates how to select different Anthropic models using the `Model` enum. This includes using the latest version of a known model, a specific version, or a custom model identifier. ```rust use claudius::Model; use claudius::KnownModel; // Use a known model (latest version) let model = Model::Known(KnownModel::Claude37SonnetLatest); // Use a specific model version let model = Model::Known(KnownModel::Claude37Sonnet20250219); // Use a custom model identifier let model = Model::Custom("custom-model-identifier".to_string()); ``` -------------------------------- ### Handle Errors with Claudius SDK Source: https://context7.com/rescrv/claudius/llms.txt Demonstrates how to handle various error types returned by the Claudius SDK, including authentication, rate limiting, retryable errors, and validation errors. It also shows how to extract the request ID for debugging purposes. ```rust use claudius::{Anthropic, Error, KnownModel, MessageCreateParams}; #[tokio::main] async fn main() { let client = Anthropic::new(None).unwrap(); let params = MessageCreateParams::simple( "Hello!", KnownModel::Claude37SonnetLatest, ); match client.send(params).await { Ok(response) => { println!("Success: {}", response.id); } Err(err) => { // Check error type if err.is_authentication() { eprintln!("Invalid API key"); } else if err.is_rate_limit() { if let Error::RateLimit { retry_after, .. } = &err { eprintln!("Rate limited. Retry after: {:?}s", retry_after); } } else if err.is_retryable() { // Timeout, connection, server errors are retryable eprintln!("Retryable error: {}", err); } else if err.is_validation() { eprintln!("Invalid parameters: {}", err); } else { eprintln!("Error: {}", err); } // Get request ID for debugging if let Some(request_id) = err.request_id() { eprintln!("Request ID: {}", request_id); } } } } ```