### Creating a New Client with AgentOptions Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client Demonstrates the basic setup for creating a new `Client` instance using `AgentOptions`. This example shows how to configure the model and the base URL for the API endpoint. ```rust use open_agent::{Client, AgentOptions}; let client = Client::new(AgentOptions::builder() .model("gpt-4") .base_url("http://localhost:1234/v1") .build()?)?; ``` -------------------------------- ### Rust Query with Tools Example Source: https://docs.rs/open-agent-sdk/latest/open_agent/fn.query_search=std%3A%3Avec An example illustrating how to use the `query` function with custom tools in Rust. It defines a 'calculator' tool and includes it in `AgentOptions`. The example shows how to handle `ToolUse` blocks, noting that tool execution must be handled manually when using `query`. ```rust use open_agent::{query, AgentOptions, Tool, ContentBlock}; use futures::StreamExt; use serde_json::json; let calculator = Tool::new( "calculator", "Performs calculations", json!({{"type": "object"}}), |input| Box::pin(async move { Ok(json!({{"result": 42}})) }) ); let options = AgentOptions::builder() .model("gpt-4") .api_key("sk-...") .tools(vec![calculator]) .build()?; let mut stream = query("Calculate 2+2", &options).await?; while let Some(block) = stream.next().await { match block? { ContentBlock::ToolUse(tool_use) => { println!("Model wants to use: {}", tool_use.name()); // Note: You'll need to manually execute tools and continue // the conversation. For automatic execution, use Client. } ContentBlock::Text(text) => print!("{}", text.text), ContentBlock::ToolResult(_) | ContentBlock::Image(_) => {} // Ignored for this example } } ``` -------------------------------- ### Import Core Open-Agent SDK Components with Prelude Source: https://docs.rs/open-agent-sdk/latest/open_agent/prelude/index_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E This code snippet demonstrates how to import all the commonly used types and functions from the open-agent SDK's prelude module. This is the recommended way to get started for typical usage, simplifying your import statements. ```Rust use open_agent::prelude::*; ``` -------------------------------- ### Rust Search Examples Source: https://docs.rs/open-agent-sdk/latest/open_agent/type.Result_search= Provides examples of common search queries used within the Rust ecosystem. These examples illustrate how to search for specific types like `std::vec`, type conversions such as `u32` to `bool`, and generic patterns involving `Option`. ```text Example searches: * std::vec * u32 -> bool * Option, (T -> U) -> Option ``` -------------------------------- ### Rust Search Example Snippets Source: https://docs.rs/open-agent-sdk/latest/open_agent/type.Result_search=std%3A%3Avec Provides examples of search queries in Rust. These illustrate how to search for specific types, type transformations, and generic types with function pointers. These are common patterns for navigating and understanding Rust codebases. ```rust * std::vec * u32 -> bool * Option, (T -> U) -> Option ``` -------------------------------- ### Example: Building Weather Tool with Parameters (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolBuilder_search=std%3A%3Avec A practical example of creating a 'get_weather' tool using the `param` method to define required input parameters like 'location' and 'units'. The tool is then built with an async handler. ```Rust let weather_tool = tool("get_weather", "Get weather for a location") .param("location", "string") .param("units", "string") .build(|args| async move { // Implementation Ok(json!({"temp": 72})) }); ``` -------------------------------- ### Rust Basic Query Example Source: https://docs.rs/open-agent-sdk/latest/open_agent/fn.query_search=std%3A%3Avec An example demonstrating the basic usage of the `query` function in Rust. It shows how to set up `AgentOptions`, call `query`, and iterate through the resulting `ContentBlock` stream to print text content. It utilizes `tokio` for asynchronous execution and `futures::StreamExt` for stream manipulation. ```rust use open_agent::{query, AgentOptions}; use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), Box> { let options = AgentOptions::builder() .system_prompt("You are a helpful assistant") .model("gpt-4") .api_key("sk-...") .build()?; let mut stream = query("What's the capital of France?", &options).await?; while let Some(block) = stream.next().await { match block? { open_agent::ContentBlock::Text(text) => { print!("{}", text.text); } open_agent::ContentBlock::ToolUse(_) | open_agent::ContentBlock::ToolResult(_) | open_agent::ContentBlock::Image(_) => {} // Ignored for this example } } Ok(()) } ``` -------------------------------- ### Rust Example: Using retry_with_backoff_conditional Source: https://docs.rs/open-agent-sdk/latest/open_agent/retry/fn.retry_with_backoff_conditional_search=u32+-%3E+bool An example demonstrating how to use the retry_with_backoff_conditional function. It shows setting up RetryConfig and AgentOptions, then calling the function with an asynchronous operation that creates a client and sends a message. This example highlights the practical application of the retry mechanism. ```rust use open_agent::retry::{retry_with_backoff_conditional, RetryConfig}; use open_agent::{Client, AgentOptions}; let config = RetryConfig::default(); let options = AgentOptions::builder() .model("qwen3:8b") .base_url("http://localhost:11434/v1") .build()?; let result = retry_with_backoff_conditional(config, || async { let mut client = Client::new(options.clone())?; client.send("Hello").await?; Ok::<_, open_agent::Error>(()) }).await?; ``` -------------------------------- ### Get Base URL Function Signature and Examples (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/fn.get_base_url_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates how to get the base URL for API requests using environment variables, provider defaults, or a fallback string. It prioritizes environment variables, then provider defaults, then fallback, and finally a hardcoded default. Useful for development, testing, and production deployments. ```Rust pub fn get_base_url( provider: Option, fallback: Option<&str>, ) -> String ``` ```Rust use open_agent::{get_base_url, Provider}; // Use Ollama's default (http://localhost:11434/v1) let url = get_base_url(Some(Provider::Ollama), None); // With explicit fallback let url = get_base_url(None, Some("http://localhost:1234/v1")); // Override via environment (takes precedence over everything) // SAFETY: This is a doctest example showing how env vars work unsafe { std::env::set_var("OPEN_AGENT_BASE_URL", "http://custom-server:8080/v1"); } let url = get_base_url(Some(Provider::Ollama), None); // Returns "http://custom-server:8080/v1" despite provider being set ``` -------------------------------- ### Example: Simple Handler Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolBuilder_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates creating a basic tool handler that echoes its input arguments. ```APIDOC ## Example: Simple Handler This example shows how to define a simple tool named `echo` that takes a `message` parameter and returns the input arguments. ```rust let my_tool = tool("echo", "Echo back the input") .param("message", "string") .build(|args| async move { Ok(args) // Echo arguments back }); ``` ``` -------------------------------- ### Rust: Create and Validate BaseUrl Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.BaseUrl Demonstrates creating a BaseUrl instance with valid and invalid URLs in Rust. It uses the `BaseUrl::new` function, which returns a Result. Valid URLs must start with 'http://' or 'https://' and cannot be empty. The example shows how to unwrap successful creations and assert errors for invalid ones. ```Rust use open_agent::BaseUrl; // Valid base URLs let url = BaseUrl::new("http://localhost:1234/v1").unwrap(); assert_eq!(url.as_str(), "http://localhost:1234/v1"); let url = BaseUrl::new("https://api.openai.com/v1").unwrap(); assert_eq!(url.as_str(), "https://api.openai.com/v1"); // Invalid: no http/https prefix assert!(BaseUrl::new("localhost:1234").is_err()); // Invalid: empty string assert!(BaseUrl::new("").is_err()); ``` -------------------------------- ### Rust: Build Hooks Collection Example Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Hooks Demonstrates how to construct a `Hooks` collection using a builder pattern. This example shows chaining `.add_pre_tool_use()` and `.add_post_tool_use()` methods to register asynchronous handlers for different lifecycle events, including blocking a specific tool and logging tool execution. ```rust use open_agent::{Hooks, PreToolUseEvent, PostToolUseEvent, HookDecision}; let hooks = Hooks::new() // First: Security gate (highest priority) .add_pre_tool_use(|event| async move { if event.tool_name == "dangerous" { return Some(HookDecision::block("Security violation")); } None }) // Second: Rate limiting .add_pre_tool_use(|event| async move { // Check rate limits... None }) // Audit logging (happens after execution) .add_post_tool_use(|event| async move { println!("Tool '{}' executed", event.tool_name); None }); ``` -------------------------------- ### Initialize Rust ToolUseBlock with Parameters Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolUseBlock Provides an example of using the `ToolUseBlock::new` constructor to create a tool use request. This specific example initializes a block for a 'search' tool with a query parameter. The `new` function accepts string-like types for `id` and `name`, and a `serde_json::Value` for `input`. ```rust use open_agent::ToolUseBlock; use serde_json::json; let block = ToolUseBlock::new( "call_abc", "search", json!({"query": "Rust async programming"}) ); ``` -------------------------------- ### Basic Interruption Example (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client Provides a basic example of interrupting a long-running AI request. The code sends a request, then enters a loop to receive response blocks, interrupting the operation after receiving a specific number of blocks. ```rust use open_agent::{Client, AgentOptions}; let mut client = Client::new(AgentOptions::default())?; client.send("Tell me a long story").await?; // Interrupt after receiving some blocks let mut count = 0; while let Some(block) = client.receive().await? { count += 1; if count >= 5 { client.interrupt(); } } // Client is ready for new queries client.send("What's 2+2?").await?; ``` -------------------------------- ### Basic Multi-Turn Conversation Example Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client Demonstrates a basic multi-turn conversation using the `Client`, showcasing automatic history maintenance. ```APIDOC ## Client: Basic Multi-Turn Conversation ### Description This example illustrates how to initiate a conversation, ask a question, receive a text response, and then ask a follow-up question, relying on the client's automatic history management. ### Code Example ```rust use open_agent::{Client, AgentOptions, ContentBlock}; let mut client = Client::new(AgentOptions::builder() .model("gpt-4") .api_key("sk-...") .build()?) ?; // First question client.send("What's the capital of France?").await?; while let Some(block) = client.receive().await? { if let ContentBlock::Text(text) = block { println!("{}", text.text); // "Paris is the capital of France." } } // Follow-up question - history is automatically maintained client.send("What's its population?").await?; while let Some(block) = client.receive().await? { if let ContentBlock::Text(text) = block { println!("{}", text.text); // "Paris has approximately 2.2 million people." } } ``` ``` -------------------------------- ### Rust: Add Pre-Tool-Use Hook Example Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Hooks Illustrates adding a pre-tool-use hook using the `add_pre_tool_use` builder method. This example registers two handlers sequentially: one that prints a message and another that conditionally blocks a tool named 'blocked' based on a security policy. ```rust use open_agent::{Hooks, HookDecision}; let hooks = Hooks::new() .add_pre_tool_use(|event| async move { println!("About to execute: {}", event.tool_name); None }) .add_pre_tool_use(|event| async move { // This runs second (if first returns None) if event.tool_name == "blocked" { Some(HookDecision::block("Not allowed")) } else { None } }); ``` -------------------------------- ### Example: Handler with Error Handling Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolBuilder_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to implement error handling within a tool handler, specifically for division by zero. ```APIDOC ## Example: Handler with Error Handling This example defines a `divide` tool that handles potential errors like invalid input or division by zero. ```rust use anyhow::Result; // Assuming `Error::tool` is a defined error type for tool-specific errors // and `json!` macro is available for creating JSON values. let my_tool = tool("divide", "Divide two numbers") .param("a", "number") .param("b", "number") .build(|args| async move { let a = args["a"].as_f64().ok_or_else(|| Error::tool("Invalid 'a' parameter"))?; let b = args["b"].as_f64().ok_or_else(|| Error::tool("Invalid 'b' parameter"))?; if b == 0.0 { return Err(Error::tool("Division by zero")); } Ok(json!({"result": a / b})) }); ``` ``` -------------------------------- ### ToolBuilder - Initialization Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolBuilder_search=std%3A%3Avec Initialize a new ToolBuilder to start creating a tool. You can provide a name and description for the tool. ```APIDOC ## POST /tool/initialize ### Description Initializes a new `ToolBuilder` with a given name and description. This is the starting point for building a tool. ### Method POST ### Endpoint `/tool/initialize` ### Parameters #### Query Parameters - **name** (string) - Required - The unique identifier for the tool. - **description** (string) - Required - A human-readable explanation of the tool's purpose. ### Request Body (Not applicable for initialization) ### Request Example (No request body for this conceptual endpoint) ### Response #### Success Response (200) - **builder_id** (string) - An identifier for the created builder instance. #### Response Example ```json { "builder_id": "some-unique-builder-identifier" } ``` ``` -------------------------------- ### Enhance User Prompt with System Context (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.HookDecision This example shows how to use `HookDecision::modify_prompt` to prepend system context to a user's prompt. This is useful for guiding the agent's behavior or providing essential information before processing. ```rust use open_agent::{UserPromptSubmitEvent, HookDecision}; async fn add_context(event: UserPromptSubmitEvent) -> Option { // Add system context to every user prompt let enhanced = format!( "{} [System Context: You are in production mode. Be extra careful with destructive operations.]", event.prompt ); Some(HookDecision::modify_prompt( enhanced, "Added production safety context" )) } ``` -------------------------------- ### AgentOptionsBuilder: Set System Prompt (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.AgentOptionsBuilder Illustrates how to set a custom system prompt for an agent using the `system_prompt` method of AgentOptionsBuilder. The system prompt guides the agent's behavior and personality. This example chains `system_prompt` after setting the model and base URL. ```rust use open_agent::AgentOptions; let options = AgentOptions::builder() .model("qwen2.5-32b-instruct") .base_url("http://localhost:1234/v1") .system_prompt("You are a helpful coding assistant. Be concise.") .build() .unwrap(); ``` -------------------------------- ### Build AgentOptions with Tools and Configuration in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.AgentOptionsBuilder_search=u32+-%3E+bool Demonstrates the usage of the AgentOptionsBuilder to create a configured AgentOptions instance. This example shows how to set the model, base URL, system prompt, max turns, temperature, add a tool, and enable auto-execution. It uses the builder pattern with chained method calls and `build().expect()` for validation. ```rust use open_agent::AgentOptions; use open_agent::Tool; let calculator = Tool::new( "calculate", "Perform arithmetic", serde_json::json!({ "type": "object", "properties": { "expression": {"type": "string"} } }), |input| Box::pin(async move { Ok(serde_json::json!({"result": 42})) }), ); let options = AgentOptions::builder() .model("qwen2.5-32b-instruct") .base_url("http://localhost:1234/v1") .system_prompt("You are a helpful assistant") .max_turns(10) .temperature(0.8) .tool(calculator) .auto_execute_tools(true) .build() .expect("Valid configuration"); ``` -------------------------------- ### Basic Multi-Turn Conversation Example (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client Demonstrates how to initialize the Client, send a message, and process the response in a basic multi-turn conversation. It shows handling text blocks and maintaining conversation history automatically. ```rust use open_agent::{Client, AgentOptions, ContentBlock}; let mut client = Client::new(AgentOptions::builder() .model("gpt-4") .api_key("sk-...") .build()?)?; // First question client.send("What's the capital of France?").await?; while let Some(block) = client.receive().await? { if let ContentBlock::Text(text) = block { println!("{}", text.text); // "Paris is the capital of France." } } // Follow-up question - history is automatically maintained client.send("What's its population?").await?; while let Some(block) = client.receive().await? { if let ContentBlock::Text(text) = block { println!("{}", text.text); // "Paris has approximately 2.2 million people." } } ``` -------------------------------- ### Create a Simple Calculator Tool in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool Illustrates creating a basic 'add' tool with specific input validation using the `Tool::new` constructor. This example highlights error handling for missing or invalid parameters. Requires the `open_agent` and `serde_json` crates. ```Rust use open_agent::Tool; use serde_json::json; let add_tool = Tool::new( "add", "Add two numbers together", json!({ "a": "number", "b": "number" }), |args| { Box::pin(async move { let a = args.get("a") .and_then(|v| v.as_f64()) .ok_or_else(|| open_agent::Error::invalid_input("Parameter 'a' must be a number"))?; let b = args.get("b") .and_then(|v| v.as_f64()) .ok_or_else(|| open_agent::Error::invalid_input("Parameter 'b' must be a number"))?; Ok(json!({"result": a + b})) }) } ); ``` -------------------------------- ### Basic Calculator Tool Example (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/fn.tool_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates creating a 'add' tool that accepts two number parameters and returns their sum using the `tool` builder. It includes error handling for invalid input types. ```rust use open_agent::tool; use serde_json::json; let add_tool = tool("add", "Add two numbers") .param("a", "number") .param("b", "number") .build(|args| async move { let a = args.get("a") .and_then(|v| v.as_f64()) .ok_or_else(|| open_agent::Error::invalid_input("Parameter 'a' must be a number"))?; let b = args.get("b") .and_then(|v| v.as_f64()) .ok_or_else(|| open_agent::Error::invalid_input("Parameter 'b' must be a number"))?; Ok(json!({"result": a + b})) }); ``` -------------------------------- ### Sensitive Data Redaction Example with PostToolUseEvent (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.PostToolUseEvent_search= A Rust example showing how to redact sensitive information from tool results using PostToolUseEvent. This specific example targets API keys that might appear in the output of a 'Read' tool, replacing them with asterisks for security. ```rust use open_agent::{PostToolUseEvent, HookDecision}; use serde_json::json; async fn redact_secrets(event: PostToolUseEvent) -> Option { // Redact API keys from Read tool output if event.tool_name == "Read" { if let Some(content) = event.tool_result.get("content") { if let Some(text) = content.as_str() { if text.contains("API_KEY=") { let redacted = text.replace( |c: char| c.is_alphanumeric(), "*" ); // Note: PostToolUse hooks typically don't modify results, // but you could log this for security review println!("Warning: Potential API key detected in output"); } } } } None } ``` -------------------------------- ### ToolResultBlock Structure and Example in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolResultBlock Defines the structure of ToolResultBlock, which holds the outcome of a tool execution. The example shows its instantiation and assertion of the tool_use_id, highlighting its role in the agent's communication loop. ```rust use open_agent::{ToolResultBlock, ContentBlock}; use serde_json::json; let result = ToolResultBlock::new( "call_123", json!({"result": 4}) ); assert_eq!(result.tool_use_id(), "call_123"); ``` -------------------------------- ### Rust Example: Creating an Other Error Source: https://docs.rs/open-agent-sdk/latest/open_agent/enum.Error_search=std%3A%3Avec Provides an example of creating an `Error::Other` variant, serving as a catch-all for miscellaneous errors that do not fit into the more specific error categories. ```rust return Err(Error::other("Unexpected condition occurred")); ``` -------------------------------- ### Rust Temperature Struct Definition and Example Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Temperature Defines the Temperature struct with compile-time validation and provides a comprehensive example demonstrating its usage. This includes valid and invalid temperature instantiations, showcasing the error handling capabilities. ```rust pub struct Temperature(/* private fields */); // Valid temperatures let temp = Temperature::new(0.7).unwrap(); assert_eq!(temp.value(), 0.7); let temp = Temperature::new(0.0).unwrap(); assert_eq!(temp.value(), 0.0); let temp = Temperature::new(2.0).unwrap(); assert_eq!(temp.value(), 2.0); // Invalid: below range assert!(Temperature::new(-0.1).is_err()); // Invalid: above range assert!(Temperature::new(2.1).is_err()); ``` -------------------------------- ### Import Open Agent SDK Prelude in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/prelude/index_search= This code snippet demonstrates how to import the entire prelude module from the open-agent-sdk in Rust. This allows for easy access to commonly used types and functions like AgentOptions, Client, ContentBlock, and query(). It is the recommended way to start using the SDK for typical agent interactions. ```rust use open_agent::prelude::*; // Now you can use types and functions from the prelude // For example: // let options = AgentOptions::default(); // let client = Client::new(options)?; // let content = vec![TextBlock::from("Hello, world!")]; // let response = client.query(content).await?; ``` -------------------------------- ### Basic Manual Tool Execution with Open Agent SDK Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client Demonstrates how to manually execute a tool using the Open Agent SDK. This involves receiving a `ToolUse` content block, manually creating a result, adding it to the client's history, and sending an empty message to continue the conversation. ```rust use open_agent::{Client, AgentOptions, ContentBlock}; use serde_json::json; let mut client = Client::new(AgentOptions::default())?; client.send("Use the calculator").await?; while let Some(block) = client.receive().await? { match block { ContentBlock::ToolUse(tool_use) => { // Execute tool manually let result = json!({"result": 42}); // Add result to history client.add_tool_result(tool_use.id(), result)?; // Continue conversation to get model's response client.send("").await?; } ContentBlock::Text(text) => { println!("{}", text.text); } ContentBlock::ToolResult(_) | ContentBlock::Image(_) => {} } } ``` -------------------------------- ### Define and Use a Tool in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool Demonstrates how to create a Tool for function calling using the open-agent-sdk. It shows tool instantiation, accessing metadata, and the expected input/output format. Requires the `open_agent` and `serde_json` crates. ```Rust use open_agent::Tool; use serde_json::json; // Create a tool using the constructor let calculator = Tool::new( "multiply", "Multiply two numbers together", json!({ "a": "number", "b": "number" }), |args| Box::pin(async move { let a = args["a"].as_f64().unwrap_or(1.0); let b = args["b"].as_f64().unwrap_or(1.0); Ok(json!({"result": a * b})) }) ); // Access tool metadata println!("Tool: {}", calculator.name()); println!("Description: {}", calculator.description()); println!("Schema: {}", calculator.input_schema()); ``` -------------------------------- ### Rust Example: Creating an API Error Source: https://docs.rs/open-agent-sdk/latest/open_agent/enum.Error_search=std%3A%3Avec Provides an example of returning an `Error::Api` variant, indicating an error response from the model server. The associated string provides details about the specific API error. ```rust return Err(Error::api("Model 'gpt-4' not found on server")); ``` -------------------------------- ### Audit Logging Example with PostToolUseEvent (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.PostToolUseEvent_search= An example Rust function demonstrating how to use PostToolUseEvent for audit logging. It logs the tool's name, ID, and execution status (success or error) to the console. This functionality is useful for compliance and monitoring. ```rust use open_agent::{PostToolUseEvent, HookDecision}; async fn audit_logger(event: PostToolUseEvent) -> Option { // Log all tool executions to your audit system let is_error = event.tool_result.get("error").is_some(); println!( "[AUDIT] Tool: {}, ID: {}, Status: {}", event.tool_name, event.tool_use_id, if is_error { "ERROR" } else { "SUCCESS" } ); // Send to external logging service // log_to_service(&event).await; None // Don't interfere with execution } ``` -------------------------------- ### Rust: Example Usage of retry_with_backoff_conditional Source: https://docs.rs/open-agent-sdk/latest/open_agent/retry/fn.retry_with_backoff_conditional_search= Demonstrates how to use the retry_with_backoff_conditional function in Rust. It sets up a default RetryConfig and an AgentOptions, then calls the retry function with a closure that creates and uses an open_agent Client to send a message. The example shows handling the Result of the operation. ```rust use open_agent::retry::{retry_with_backoff_conditional, RetryConfig}; use open_agent::{Client, AgentOptions}; let config = RetryConfig::default(); let options = AgentOptions::builder() .model("qwen3:8b") .base_url("http://localhost:11434/v1") .build()?; let result = retry_with_backoff_conditional(config, || async { let mut client = Client::new(options.clone())?; client.send("Hello").await?; Ok::<_, open_agent::Error>(()) }).await?; ``` -------------------------------- ### Getting TypeId with Any Trait in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool_search=std%3A%3Avec Demonstrates how to get the TypeId of a type T using the 'Any' trait implementation in Rust. This is a blanket implementation applicable to any type T that is 'static and ?Sized. The `type_id` method returns a `TypeId` struct representing the runtime type of the object. ```rust impl Any for T where T: 'static + ?Sized, { fn type_id(&self) -> TypeId { // ... implementation details omitted for brevity } } ``` -------------------------------- ### Initialize ToolBuilder with Name and Description (Rust) Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolBuilder Starts building a new tool by providing its name and a human-readable description. This method initializes the builder with an empty schema, allowing subsequent addition of parameters or a complete schema. ```rust let builder = ToolBuilder::new("search", "Search for information"); // builder.param(...).build(...) ``` -------------------------------- ### Example Usage of Result Type Alias in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/type.Result Demonstrates how to use the Result type alias in a function signature. This example shows an asynchronous function that returns a Result, indicating either a successful string value or an Error. ```rust use open_agent::Result; async fn send_request() -> Result { // Function body Ok("Success".to_string()) } ``` -------------------------------- ### Create Simple Rust Handler Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.ToolBuilder Demonstrates how to create a basic handler for a tool. This handler takes arguments and echoes them back as the result. It requires the `tool` function and `async move` for asynchronous execution. ```rust let my_tool = tool("echo", "Echo back the input") .param("message", "string") .build(|args| async move { Ok(args) // Echo arguments back }); ``` -------------------------------- ### Rust Example: Block Dangerous Bash Commands with PreToolUseEvent Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.PreToolUseEvent_search=u32+-%3E+bool Demonstrates how to use PreToolUseEvent to implement a security gate. This example blocks any Bash commands that contain 'rm -rf', preventing potentially harmful operations. It returns a HookDecision::block to halt execution. ```rust use open_agent::{PreToolUseEvent, HookDecision}; use serde_json::json; async fn security_gate(event: PreToolUseEvent) -> Option { // Block all Bash commands containing 'rm -rf' if event.tool_name == "Bash" { if let Some(command) = event.tool_input.get("command") { if command.as_str()?.contains("rm -rf") { return Some(HookDecision::block( "Dangerous command blocked for safety" )); } } } None // Allow other tools } ``` -------------------------------- ### Rust Example: Using retry_with_backoff Source: https://docs.rs/open-agent-sdk/latest/open_agent/retry/fn.retry_with_backoff_search=u32+-%3E+bool Demonstrates how to use the `retry_with_backoff` function with `open_agent::Client`. It configures retry attempts and shows how to wrap an asynchronous client operation within the retry mechanism. ```rust use open_agent::retry::{retry_with_backoff, RetryConfig}; use open_agent::{Client, AgentOptions}; let config = RetryConfig::default().with_max_attempts(3); let options = AgentOptions::builder() .model("qwen3:8b") .base_url("http://localhost:11434/v1") .build()?; let result = retry_with_backoff(config, || async { let mut client = Client::new(options.clone())?; client.send("Hello").await?; Ok::<_, open_agent::Error>(()) }).await?; ``` -------------------------------- ### Rust Example: Inject Authentication Header with PreToolUseEvent Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.PreToolUseEvent_search=u32+-%3E+bool Illustrates using PreToolUseEvent to modify tool inputs. This example targets the 'WebFetch' tool and injects an 'Authorization' header with a bearer token, demonstrating input parameter modification. It returns HookDecision::modify_input with the updated parameters. ```rust use open_agent::{PreToolUseEvent, HookDecision}; use serde_json::json; async fn inject_auth(event: PreToolUseEvent) -> Option { // Add authentication header to all API calls if event.tool_name == "WebFetch" { let mut modified = event.tool_input.clone(); modified["headers"] = json!({ "Authorization": "Bearer secret-token" }); return Some(HookDecision::modify_input( modified, "Injected auth token" )); } None } ``` -------------------------------- ### Multiple Tool Calls Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client_search=u32+-%3E+bool Shows how to handle scenarios where the agent might request the execution of multiple tools in a single turn. The example collects all tool requests, executes them, and then reports the results. ```APIDOC ## Multiple Tool Calls ### Description This example handles the situation where the agent requests multiple tools to be executed concurrently. It collects all `ToolUse` blocks, processes them, and sends back all results. ### Method POST (conceptual, SDK interaction) ### Endpoint N/A (SDK function calls) ### Parameters None directly for this snippet, relies on `Client` methods. ### Request Example ```rust use open_agent::{Client, AgentOptions, ContentBlock}; use serde_json::json; client.send("Calculate 2+2 and 3+3").await?; let mut tool_calls = Vec::new(); // Collect all tool calls while let Some(block) = client.receive().await? { if let ContentBlock::ToolUse(tool_use) = block { tool_calls.push(tool_use); } } // Execute and add results for all tools for tool_call in tool_calls { let result = json!({{"result": 42}}); // Execute tool client.add_tool_result(tool_call.id(), result)?; } // Continue conversation client.send("").await?; ``` ### Response #### Success Response (200) Model's response, having processed the results of multiple tool executions. #### Response Example ```json { "text": "Okay, I have calculated 2+2 which is 4, and 3+3 which is 6." } ``` ``` -------------------------------- ### Client Initialization Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Client_search= Initializes a new `Client` instance for the Open Agent SDK. This involves configuring the model, API key, base URL, and other options. ```APIDOC ## Client Initialization ### Description This section details how to create a new `Client` instance for interacting with the Open Agent SDK. The `Client::new` function takes `AgentOptions` which allow for customization of the agent's behavior, including model selection, API endpoint, and tool definitions. ### Method `Client::new(options: AgentOptions) -> Result` ### Endpoint N/A (Client-side SDK usage) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```rust use open_agent::{Client, AgentOptions}; let client = Client::new(AgentOptions::builder() .model("gpt-4") .base_url("http://localhost:1234/v1") .build()?) ?; ``` ### Response #### Success Response (200) Returns a new `Client` instance configured with the provided options. #### Response Example N/A (This is a constructor, not an API call) #### Errors Returns an error if the HTTP client cannot be built. This can happen due to: * Invalid TLS configuration * System resource exhaustion * Invalid timeout values ``` -------------------------------- ### Create Basic AgentOptions with Builder in Rust Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.AgentOptions_search=u32+-%3E+bool Illustrates a minimal example of using the AgentOptions builder to construct agent configurations in Rust. This snippet focuses on essential settings like model and base URL, highlighting the builder's role in providing a discoverable API. Requires the 'open_agent' crate. ```Rust use open_agent::AgentOptions; let options = AgentOptions::builder() .model("qwen2.5-32b-instruct") .base_url("http://localhost:1234/v1") .build() .expect("Valid configuration"); ``` -------------------------------- ### Tool Definition and Usage Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool Demonstrates how to create a Tool with optional parameters and how its execution handler works. ```APIDOC ## POST /tool (Define Tool) ### Description Defines a reusable tool with a name, description, input schema, and an asynchronous handler function. ### Method POST (Conceptual - tools are created programmatically) ### Endpoint N/A (Programmatic) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body **name** (string) - Required - The unique name of the tool. **description** (string) - Required - A human-readable description of what the tool does. **input_schema** (JSON object) - Required - Defines the expected arguments for the tool's handler. Supports basic types and optionality. **handler** (async function) - Required - The logic to execute when the tool is called. ### Request Example ```json { "name": "search", "description": "Search for information", "input_schema": { "query": { "type": "string", "description": "What to search for" }, "max_results": { "type": "integer", "description": "Maximum results to return", "optional": true, "default": 10 } } } ``` ### Response #### Success Response (200) Represents the created `Tool` object (not directly returned via HTTP, but conceptually similar). #### Response Example ```json { "status": "Tool created successfully" } ``` ``` -------------------------------- ### Tool Creation using Builder Pattern Source: https://docs.rs/open-agent-sdk/latest/open_agent/fn.tool This section details how to create a tool using the `tool` function, which returns a `ToolBuilder` for fluent configuration. It explains the benefits over `Tool::new` and provides various usage examples. ```APIDOC ## Function tool ### Description Creates a tool using the builder pattern. This is the recommended way to create tools, returning a `ToolBuilder` for fluent configuration. ### Method Signature ```rust pub fn tool( name: impl Into, description: impl Into, ) -> ToolBuilder ``` ### Parameters * `name` (string) - Required - Unique identifier for the tool (snake_case recommended). * `description` (string) - Required - Human-readable explanation of what the tool does. ### Typical Usage Pattern ```rust tool(name, description) .param(name, type) // Add parameters (optional, can repeat) .build(handler) // Provide handler and create Tool ``` ### Why Use This Instead of Tool::new? * **More readable**: The builder pattern reads like natural language. * **Incremental schema building**: Add parameters one at a time. * **Flexible**: Can conditionally add parameters or use `.schema()` for complex cases. * **Type-safe**: Method chaining ensures you can’t forget the handler. ### Examples #### Basic Calculator Tool ```rust use open_agent::tool; use serde_json::json; let add_tool = tool("add", "Add two numbers") .param("a", "number") .param("b", "number") .build(|args| async move { let a = args.get("a") .and_then(|v| v.as_f64()) .ok_or_else(|| open_agent::Error::invalid_input("Parameter 'a' must be a number"))?; let b = args.get("b") .and_then(|v| v.as_f64()) .ok_or_else(|| open_agent::Error::invalid_input("Parameter 'b' must be a number"))?; Ok(json!({"result": a + b})) }); ``` #### Tool with External HTTP Client ```rust use open_agent::{tool, Error}; use serde_json::json; use std::sync::Arc; // Assume HttpClient is defined elsewhere and is cloneable/shareable struct HttpClient; impl HttpClient { fn new() -> Self { HttpClient } async fn get(&self, url: &str) -> Result { Ok(format!("Content from {}", url)) } // Dummy implementation } // Shared HTTP client (example - use your actual HTTP client) let http_client = Arc::new(HttpClient::new()); let fetch_tool = tool("fetch_url", "Fetch content from a URL") .param("url", "string") .build(move |args| { let client = http_client.clone(); async move { let url = args["url"].as_str().unwrap_or(""); let content = client.get(url).await .map_err(|e| Error::tool(format!("Failed to fetch: {}", e)))?; Ok(json!({"content": content})) } }); ``` #### Tool with Complex Schema ```rust use open_agent::tool; use serde_json::json; let search_tool = tool("search", "Search for information") .schema(json!({ "query": { "type": "string", "description": "Search query" }, "filters": { "type": "object", "description": "Optional filters", "optional": true, "properties": { "date_from": {"type": "string"}, "date_to": {"type": "string"} } }, "max_results": { "type": "integer", "default": 10, "optional": true } })) .build(|args| async move { // Implementation Ok(json!({"results": []})) }); ``` #### Conditional Parameter Addition ```rust use open_agent::tool; use serde_json::json; let enable_advanced = true; // Example condition let mut builder = tool("process", "Process data") .param("input", "string"); // Conditionally add parameters if enable_advanced { builder = builder.param("advanced_mode", "boolean"); } let my_tool = builder.build(|args| async move { Ok(json!({"status": "processed"})) }); ``` #### Integration with Agent ```rust use open_agent::{Client, AgentOptions, tool}; use serde_json::json; let weather_tool = tool("get_weather", "Get weather for a location") .param("location", "string") .build(|args| async move { Ok(json!({"temp": 72, "conditions": "sunny"})) }); let options = AgentOptions::builder() .model("gpt-4") .base_url("http://localhost:1234/v1") .tool(weather_tool) .build()?; let client = Client::new(options)?; // Client can now use the tool when responding to queries ``` ### See Also * `Tool::new` - Direct constructor if you prefer not using the builder. * `ToolBuilder` - The builder type returned by this function. * `Tool` - The final tool type produced by `.build()`. ``` -------------------------------- ### Get Tool Description Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool_search= Retrieves the description of a specific tool. ```APIDOC ## GET /tool/{tool_id}/description ### Description Returns the description of the specified tool. ### Method GET ### Endpoint `/tool/{tool_id}/description` ### Parameters #### Path Parameters - **tool_id** (string) - Required - The unique identifier of the tool. ### Response #### Success Response (200) - **description** (string) - The description of the tool. #### Response Example ```json { "description": "Search for information" } ``` ``` -------------------------------- ### Tool Definition and Execution Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates how to create a Tool with optional parameters and how its `execute` method functions, including argument handling and error propagation. ```APIDOC ## Tool Definition and Execution ### Description This section covers the creation of a `Tool` with optional parameters and the execution flow of the `execute` method. The `execute` method is the primary way to run a tool's logic by invoking its handler function with provided arguments. ### Methods #### `Tool::new` (Constructor) Creates a new `Tool` instance. **Parameters** - `name` (string) - Required - The name of the tool. - `description` (string) - Required - A description of what the tool does. - `input_schema` (JSON Value) - Required - A JSON schema defining the expected arguments for the tool. - `handler` (function) - Required - An asynchronous function that takes arguments and returns a `Result`. #### `Tool::execute` Asynchronously executes the tool with the provided arguments. **Parameters** - `arguments` (JSON Value) - Required - A JSON object matching the tool's `input_schema`. **Returns** - `Result` - The result of the tool's execution or an error. **Execution Flow** 1. Calls the tool's handler function with the provided arguments. 2. Awaits the asynchronous future returned by the handler. 3. Returns the `Result` from the handler. **Error Handling** Errors from the handler are propagated directly. The calling agent should manage error handling. ### Request Example (Tool with Optional Parameters) ```rust use open_agent::Tool; use serde_json::json; let search_tool = Tool::new( "search", "Search for information", json!({ "query": { "type": "string", "description": "What to search for" }, "max_results": { "type": "integer", "description": "Maximum results to return", "optional": true, "default": 10 } }), |args| Box::pin(async move { let query = args["query"].as_str().unwrap_or(""); let max = args.get("max_results") .and_then(|v| v.as_i64()) .unwrap_or(10); // Perform search... Ok(json!({"results": [], "query": query, "limit": max})) }) ); ``` ### Request Example (Tool Execution) ```rust let calculator = Tool::new( "add", "Add numbers", json!({"a": "number", "b": "number"}), |args| Box::pin(async move { let sum = args["a"].as_f64().unwrap() + args["b"].as_f64().unwrap(); Ok(json!({"result": sum})) }) ); // Execute the tool let result = calculator.execute(json!({"a": 5.0, "b": 3.0})).await?; // assert_eq!(result["result"], 8.0); ``` ### Response Example (Success Response) ```json { "results": [], "query": "example query", "limit": 5 } ``` ### Response Example (Success Response - Calculator) ```json { "result": 8.0 } ``` ``` -------------------------------- ### Get Tool Name Source: https://docs.rs/open-agent-sdk/latest/open_agent/struct.Tool_search= Retrieves the name of a specific tool. ```APIDOC ## GET /tool/{tool_id}/name ### Description Returns the registered name of the specified tool. ### Method GET ### Endpoint `/tool/{tool_id}/name` ### Parameters #### Path Parameters - **tool_id** (string) - Required - The unique identifier of the tool. ### Response #### Success Response (200) - **name** (string) - The name of the tool. #### Response Example ```json { "name": "search" } ``` ```