pub trait ToolHandler<Ctx = ()>: Send + Sync {
// Required methods
fn definition(&self) -> ToolDefinition;
fn execute<'a>(
&'a self,
input: Value,
ctx: &'a Ctx,
) -> Pin<Box<dyn Future<Output = Result<ToolOutput, ToolError>> + Send + 'a>>;
}Expand description
A single tool that can be invoked by the LLM.
Implement this trait for tools that need complex state or lifetime
management. For simple tools, use super::tool_fn to wrap a closure.
The trait is generic over a context type Ctx which is passed to
execute(). This allows tools to access shared state like database
connections or user identity without closure capture. The default
context type is () for backwards compatibility.
The trait is object-safe (uses boxed futures) so handlers can be
stored as Arc<dyn ToolHandler<Ctx>>.
§Example with Context
use llm_stack::tool::{ToolHandler, ToolOutput, ToolError};
use llm_stack::{ToolDefinition, JsonSchema};
use serde_json::{json, Value};
use std::future::Future;
use std::pin::Pin;
struct AppContext {
user_id: String,
}
struct UserInfoTool;
impl ToolHandler<AppContext> for UserInfoTool {
fn definition(&self) -> ToolDefinition {
ToolDefinition {
name: "get_user_info".into(),
description: "Get current user info".into(),
parameters: JsonSchema::new(json!({"type": "object"})),
retry: None,
}
}
fn execute<'a>(
&'a self,
_input: Value,
ctx: &'a AppContext,
) -> Pin<Box<dyn Future<Output = Result<ToolOutput, ToolError>> + Send + 'a>> {
Box::pin(async move {
Ok(ToolOutput::new(format!("User: {}", ctx.user_id)))
})
}
}Required Methods§
Sourcefn definition(&self) -> ToolDefinition
fn definition(&self) -> ToolDefinition
Returns the tool’s definition (name, description, parameter schema).
Sourcefn execute<'a>(
&'a self,
input: Value,
ctx: &'a Ctx,
) -> Pin<Box<dyn Future<Output = Result<ToolOutput, ToolError>> + Send + 'a>>
fn execute<'a>( &'a self, input: Value, ctx: &'a Ctx, ) -> Pin<Box<dyn Future<Output = Result<ToolOutput, ToolError>> + Send + 'a>>
Executes the tool with the given JSON arguments and context.
Returns a ToolOutput containing the content for the LLM and
optional metadata for application use. Providers expect tool results
as text content — callers should serde_json::to_string() if they
have structured data.