### Deserialize Tool Input Source: https://github.com/cortesi/misanthropy/blob/main/README.md Example of deserializing tool input when the AI uses a defined tool. ```rust if let Some(tool_use) = response.content.iter().find_map(|content| { if let Content::ToolUse(tool_use) = content { Some(tool_use) } else { None } }) { if tool_use.name == "GetWeather" { let weather_input: GetWeather = serde_json::from_value(tool_use.input.clone())?; println!("Weather requested for: {}", weather_input.location); // Here you would typically call an actual weather API } } ``` -------------------------------- ### Define Tool Input Structure Source: https://github.com/cortesi/misanthropy/blob/main/README.md Example of defining a tool input structure with derive macros for JSON schema generation. ```rust use schemars::JsonSchema; use serde::{Deserialize, Serialize}; /// Get the current weather for a location. #[derive(JsonSchema, Serialize, Deserialize)] struct GetWeather { /// The city and country, e.g., "London, UK" location: String, /// Temperature unit: "celsius" or "fahrenheit" unit: Option, } ``` -------------------------------- ### Install Misanthropy Dependencies Source: https://context7.com/cortesi/misanthropy/llms.txt Add the necessary crates to your Cargo.toml file to use the Misanthropy SDK. ```toml [dependencies] misanthropy = "0.0.8" tokio = { version = "1.38.0", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" schemars = "0.8" # Required for tool definitions ``` -------------------------------- ### Stream Responses with Server-Sent Events in Rust Source: https://context7.com/cortesi/misanthropy/llms.txt Process responses in real-time as they are generated. Ensure `stream` is set to `true` in the request. This example flushes stdout after each text delta to display output incrementally. ```rust use misanthropy::{ Anthropic, Content, ContentBlockDelta, MessagesRequest, StreamEvent }; use std::io::{self, Write}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; // Enable streaming in the request let mut request = MessagesRequest::default() .with_max_tokens(1024) .with_stream(true); // Must be true for streaming request.add_user(Content::text("Explain quantum computing in simple terms.")); // Get streaming response let mut stream = client.messages_stream(&request)?; // Process events as they arrive while let Some(event) = stream.next().await { match event { Ok(StreamEvent::ContentBlockDelta { delta, .. }) => { if let ContentBlockDelta::TextDelta { text } = delta { print!("{}", text); io::stdout().flush()?; } } Ok(StreamEvent::MessageStop) => { println!("\n--- Stream complete ---"); break; } Ok(StreamEvent::MessageStart { message }) => { println!("Model: {}", message.model); } Ok(StreamEvent::Error { error }) => { eprintln!("Stream error: {}", error.message); break; } Err(e) => { eprintln!("Error: {}", e); break; } _ => {} // Ignore Ping and other events } } // Access the complete assembled response println!("\nFull response: {}", stream.content_text()); println!("Total tokens: {:?}", stream.response.usage.output_tokens); Ok(()) } ``` -------------------------------- ### Basic Library Usage Source: https://github.com/cortesi/misanthropy/blob/main/README.md Demonstrates how to initialize the Anthropic client from environment variables and send a simple text message. ```rust use misanthropy::{Anthropic, MessagesRequest, Content}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; let mut request = MessagesRequest::default(); request.add_user(Content::text("Hello, Claude!")); let response = client.messages(request).await?; println!("{}", response.format_nicely()); Ok(()) } ``` -------------------------------- ### CLI Help Command Source: https://github.com/cortesi/misanthropy/blob/main/README.md Shows how to access usage instructions for the misan CLI tool. ```bash misan --help ``` -------------------------------- ### Create Tool from Structure Source: https://github.com/cortesi/misanthropy/blob/main/README.md Shows how to create a `Tool` object from a defined input structure. ```rust use misanthropy::{Anthropic, MessagesRequest, Tool}; let weather_tool = Tool::new::(); ``` -------------------------------- ### Initialize Anthropic Client Source: https://context7.com/cortesi/misanthropy/llms.txt Create an Anthropic client instance using environment variables or an explicit API key. ```rust use misanthropy::{Anthropic, Result}; fn main() -> Result<()> { // Create client from environment variable ANTHROPIC_API_KEY let client = Anthropic::from_env()?; // Or create client with explicit API key let client = Anthropic::new("sk-ant-api03-your-key-here"); // Or use string if available, fallback to environment let api_key = std::env::var("CUSTOM_API_KEY").unwrap_or_default(); let client = Anthropic::from_string_or_env(&api_key)?; Ok(()) } ``` -------------------------------- ### Use the Misan CLI Tool Source: https://context7.com/cortesi/misanthropy/llms.txt Interact with Claude via the command line for chat, single messages, and debugging. ```bash # Display tool information and API configuration misan info # Send a single message misan message -u "What is the capital of France?" # Send message with system prompt misan message -u "Write a haiku" -s "You are a poet" # Send message with custom model and max tokens misan --model claude-sonnet-4-20250514 --max-tokens 2048 message -u "Explain gravity" # Stream a response in real-time misan stream -u "Tell me a story about a brave knight" # Start an interactive chat session misan chat misan chat -s "You are a helpful coding assistant" # Include images in messages misan message -u "Describe this image" --uimg /path/to/image.png # Multi-turn message with alternating roles misan message -u "Hello" -a "Hi there!" -u "How are you?" # Output as JSON misan --json message -u "Hello" # Verbose output for debugging misan -vv message -u "Test" ``` -------------------------------- ### Configure API Key Environment Variable Source: https://context7.com/cortesi/misanthropy/llms.txt Set the required environment variable for Anthropic API authentication. ```bash # Set your Anthropic API key export ANTHROPIC_API_KEY="your-api-key-here" ``` -------------------------------- ### Add Tool to Request Source: https://github.com/cortesi/misanthropy/blob/main/README.md Demonstrates adding a defined tool and system prompt to a MessagesRequest. ```rust let request = MessagesRequest::default() .with_tool(weather_tool) .with_system(vec![Content::text("You can use the GetWeather tool to check the weather.")]); ``` -------------------------------- ### Implement Extended Thinking Mode Source: https://context7.com/cortesi/misanthropy/llms.txt Enable extended thinking for complex reasoning tasks by allocating a token budget. Streaming is recommended to capture and display the thinking process in real-time. ```rust use misanthropy::{ Anthropic, Content, ContentBlockDelta, MessagesRequest, StreamEvent }; use std::io::{self, Write}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; // Enable thinking with token budget (minimum 1024, must be less than max_tokens) let mut request = MessagesRequest::default() .with_thinking(1024) // Allocate tokens for thinking process .with_max_tokens(2048) // Must be greater than thinking budget .with_stream(true); // Best used with streaming request.add_user(Content::text( "Solve this step by step: What is 453 + 897? Show your reasoning." )); let mut stream = client.messages_stream(&request)?; println!("--- Thinking Process ---"); let mut in_thinking = false; while let Some(event) = stream.next().await { match event { Ok(StreamEvent::ContentBlockStart { content_block, .. }) => { match content_block { Content::Thinking(_) => { in_thinking = true; println!("[THINKING]"); } Content::Text(_) => { if in_thinking { println!("\n[RESPONSE]"); in_thinking = false; } } _ => {} } } Ok(StreamEvent::ContentBlockDelta { delta, .. }) => { match delta { ContentBlockDelta::ThinkingDelta { thinking } => { print!("{}", thinking); io::stdout().flush()?; } ContentBlockDelta::TextDelta { text } => { print!("{}", text); io::stdout().flush()?; } _ => {} } } Ok(StreamEvent::MessageStop) => break, Err(e) => { eprintln!("Error: {}", e); break; } _ => {} } } // Access thinking content from complete response for content in &stream.response.content { if let Content::Thinking(thinking) = content { println!("\nThinking summary: {} chars", thinking.thinking.len()); } } Ok(()) } ``` -------------------------------- ### Configure Request Parameters Source: https://context7.com/cortesi/misanthropy/llms.txt Customize model, sampling parameters, and system prompts using builder methods on the MessagesRequest object. ```rust use misanthropy::{Anthropic, Content, MessagesRequest, DEFAULT_MODEL}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; let mut request = MessagesRequest::default() .with_model("claude-sonnet-4-20250514") // Specify model .with_max_tokens(2048) // Maximum response tokens .with_temperature(0.7) // Randomness (0.0-1.0) .with_top_k(40) // Consider top 40 tokens .with_top_p(0.9) // Nucleus sampling at 90% .with_metadata("user-12345") // Track user for analytics .with_stop_sequences(vec![ // Custom stop sequences "END".to_string(), "STOP".to_string(), ]); // Add system prompt request = request.with_system(vec![ Content::text("You are a helpful coding assistant. Be concise and precise.") ]); request.add_user(Content::text("Write a creative story about a robot.")); let response = client.messages(&request).await?; println!("{}", response.format_content()); Ok(()) } ``` -------------------------------- ### Configure Text Editor Tool in Rust Source: https://context7.com/cortesi/misanthropy/llms.txt Use the TextEditor tool to perform file operations like viewing, replacing, creating, and inserting text. Ensure the version constant matches the target Claude model. ```rust use misanthropy::{ tools::TextEditor, Anthropic, Content, MessagesRequest, TEXT_EDITOR_4, TEXT_EDITOR_37, TEXT_EDITOR_35 }; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; // Add text editor tool - use version matching your model // TEXT_EDITOR_4 for Claude 4, TEXT_EDITOR_37 for Claude 3.7, TEXT_EDITOR_35 for Claude 3.5 let mut request = MessagesRequest::default() .with_max_tokens(1024) .with_text_editor(TEXT_EDITOR_37) .with_system(vec![Content::text("You are a helpful editor assistant.")]); request.add_user(Content::text("Please view the file /path/to/file.py")); let response = client.messages(&request).await?; // Parse text editor commands from response for content in &response.content { if let Content::ToolUse(tool_use) = content { let editor_cmd: TextEditor = serde_json::from_value(tool_use.input.clone())?; match editor_cmd { TextEditor::View { path, view_range } => { println!("View file: {}", path); if let Some([start, end]) = view_range { println!("Lines {} to {}", start, end); } } TextEditor::StrReplace { path, old_str, new_str } => { println!("Replace in {}: '{}' -> '{}'", path, old_str, new_str); } TextEditor::Create { path, file_text } => { println!("Create file: {} with {} bytes", path, file_text.len()); } TextEditor::Insert { path, insert_line, new_str } => { println!("Insert at {}:{}: {}", path, insert_line, new_str); } TextEditor::UndoEdit { path } => { println!("Undo edit in: {}", path); } } } } Ok(()) } ``` -------------------------------- ### Streaming Responses Source: https://github.com/cortesi/misanthropy/blob/main/README.md Illustrates how to handle streaming responses from the Anthropic API using the misanthropy library. ```rust let mut stream = client.messages_stream(request)?; while let Some(event) = stream.next().await { match event { Ok(event) => { // Handle the streaming event } Err(e) => eprintln!("Error: {}", e), } } ``` -------------------------------- ### Define and Use Custom Tools with JSON Schemas in Rust Source: https://context7.com/cortesi/misanthropy/llms.txt Integrate strongly-typed tools that Claude can invoke. Tools are defined using Rust structs annotated with `JsonSchema`, `Serialize`, and `Deserialize`. The `Tool::custom` method creates a tool from these definitions. ```rust use misanthropy::{ Anthropic, Content, MessagesRequest, Tool, ToolChoice }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; /// Get the current weather for a location. #[derive(JsonSchema, Serialize, Deserialize, Debug)] struct GetWeather { /// The city and country, e.g., "London, UK" location: String, /// Temperature unit: "celsius" or "fahrenheit" unit: Option, } /// Get the current stock price for a ticker symbol. #[derive(JsonSchema, Serialize, Deserialize, Debug)] struct GetStockPrice { /// The stock ticker symbol, e.g. AAPL for Apple Inc. ticker: String, } #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; // Create tools from schema definitions let weather_tool = Tool::custom::("get_weather")?; let stock_tool = Tool::custom::("get_stock_price")?; let mut request = MessagesRequest::default() .with_max_tokens(1024) .with_tool(weather_tool) .with_tool(stock_tool) .with_system(vec![Content::text( "You can check weather and stock prices using available tools." )]); // Optionally force a specific tool // request = request.with_tool_choice(ToolChoice::Tool { // name: "get_weather".to_string(), // }); request.add_user(Content::text("What's the weather in Tokyo?")); let response = client.messages(&request).await?; // Process tool use in response for content in &response.content { if let Content::ToolUse(tool_use) = content { println!("Tool called: {}", tool_use.name); println!("Tool ID: {}", tool_use.id); if tool_use.name == "get_weather" { let input: GetWeather = serde_json::from_value(tool_use.input.clone())?; println!("Location requested: {}", input.location); // Provide tool result back to Claude request.add_assistant(content.clone()); request.add_user(Content::tool_result( tool_use, "Currently 22°C, partly cloudy with light winds." )); // Continue conversation with tool result let final_response = client.messages(&request).await?; println!("{}", final_response.format_content()); } } } Ok(()) } ``` -------------------------------- ### Add schemars Dependency Source: https://github.com/cortesi/misanthropy/blob/main/README.md Specifies the schemars crate version required for defining tool inputs. ```toml [dependencies] schemars = "0.8" ``` -------------------------------- ### Handle API Errors in Rust Source: https://context7.com/cortesi/misanthropy/llms.txt Implement robust error handling for common API scenarios like rate limits, authentication, and network failures. ```rust use misanthropy::{Anthropic, Content, Error, MessagesRequest}; #[tokio::main] async fn main() { let client = match Anthropic::from_env() { Ok(c) => c, Err(Error::EnvVarError(_)) => { eprintln!("ANTHROPIC_API_KEY environment variable not set"); return; } Err(e) => { eprintln!("Failed to create client: {}", e); return; } }; let mut request = MessagesRequest::default(); request.add_user(Content::text("Hello")); match client.messages(&request).await { Ok(response) => { println!("{}", response.format_content()); } Err(Error::RateLimitExceeded(msg)) => { eprintln!("Rate limited, please wait: {}", msg); } Err(Error::Unauthorized(msg)) => { eprintln!("Authentication failed: {}", msg); } Err(Error::BadRequest(msg)) => { eprintln!("Invalid request: {}", msg); } Err(Error::ApiOverloaded(msg)) => { eprintln!("API overloaded, retry later: {}", msg); } Err(Error::HttpError(e)) => { eprintln!("Network error: {}", e); } Err(e) => { eprintln!("Unexpected error: {}", e); } } } ``` -------------------------------- ### Add Images to Messages in Rust Source: https://context7.com/cortesi/misanthropy/llms.txt Include images by loading them from local file paths, which are automatically base64 encoded. ```rust use misanthropy::{Anthropic, Content, MessagesRequest}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; let mut request = MessagesRequest::default() .with_max_tokens(1024); // Add text and image to the same user message request.add_user(Content::text("What do you see in this image?")); // Load image from file (supports png, jpg, jpeg, gif, webp) let image_content = Content::image("/path/to/image.png")?; request.add_user(image_content); let response = client.messages(&request).await?; println!("{}", response.format_content()); Ok(()) } ``` -------------------------------- ### Send Simple Message to Claude Source: https://context7.com/cortesi/misanthropy/llms.txt Send a basic text message and process the response, including content extraction and token usage tracking. ```rust use misanthropy::{Anthropic, Content, MessagesRequest}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; // Create request with default model (claude-sonnet-4-20250514) and max_tokens (1024) let mut request = MessagesRequest::default(); request.add_user(Content::text("Hello, Claude! How are you today?")); // Send request and get response let response = client.messages(&request).await?; // Print formatted response println!("{}", response.format_content()); // Access raw content blocks for content in &response.content { if let Content::Text(text) = content { println!("Text: {}", text.text); } } // Check token usage println!("Input tokens: {:?}", response.usage.input_tokens); println!("Output tokens: {:?}", response.usage.output_tokens); Ok(()) } ``` -------------------------------- ### Manage Multi-turn Conversations in Rust Source: https://context7.com/cortesi/misanthropy/llms.txt Maintain conversation context by merging previous responses into the request object using merge_response. ```rust use misanthropy::{Anthropic, Content, MessagesRequest, Role}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Anthropic::from_env()?; let mut request = MessagesRequest::default() .with_max_tokens(1024) .with_system(vec![Content::text("You are a helpful math tutor.")]); // First turn request.add_user(Content::text("What is 25 * 4?")); let response1 = client.messages(&request).await?; println!("User: What is 25 * 4?"); println!("Claude: {}", response1.format_content()); // Merge response into conversation history request.merge_response(&response1); // Second turn - Claude remembers the previous exchange request.add_user(Content::text("Now multiply that result by 2")); let response2 = client.messages(&request).await?; println!("\nUser: Now multiply that result by 2"); println!("Claude: {}", response2.format_content()); // Continue the conversation request.merge_response(&response2); request.add_user(Content::text("What was my original question?")); let response3 = client.messages(&request).await?; println!("\nUser: What was my original question?"); println!("Claude: {}", response3.format_content()); Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.