Skip to main content

define_tool

Function define_tool 

Source
pub fn define_tool<P, F, Fut>(
    name: impl Into<String>,
    description: impl Into<String>,
    handler: F,
) -> Box<dyn ToolHandler>
where P: JsonSchema + DeserializeOwned + Send + 'static, F: Fn(ToolInvocation, P) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<ToolResult, Error>> + Send + 'static,
Expand description

Define a tool from an async function (or closure) that takes a typed, JsonSchema-derived parameter struct.

The returned Box<dyn ToolHandler> plugs directly into ToolHandlerRouter::new. JSON Schema for the parameter type is generated via schema_for at construction time.

The handler bound (Fn(ToolInvocation, P) -> Fut + Send + Sync + 'static) accepts both bare async fn items and closures — the same shape as tower::service_fn and hyper::service::service_fn. Prefer a free async fn for non-trivial tools so it shows up in stack traces by name.

The closure receives the full ToolInvocation alongside the deserialized parameters so handlers can use inv.session_id, inv.tool_call_id, or other invocation metadata. Handlers that don’t need that metadata can destructure with |_inv, params|.

§Example

use github_copilot_sdk::tool::{define_tool, JsonSchema};
use github_copilot_sdk::types::ToolInvocation;
use github_copilot_sdk::{Error, ToolResult};
use serde::Deserialize;

#[derive(Deserialize, JsonSchema)]
struct GetWeatherParams {
    /// City name
    city: String,
}

async fn get_weather(
    inv: ToolInvocation,
    params: GetWeatherParams,
) -> Result<ToolResult, Error> {
    // `inv.session_id` and `inv.tool_call_id` are available for telemetry,
    // streaming updates, scoping DB lookups, etc.
    let _ = inv.session_id;
    Ok(ToolResult::Text(format!("Sunny in {}", params.city)))
}

// Pass a free async fn — preferred for non-trivial tools.
let tool = define_tool("get_weather", "Get weather for a city", get_weather);

// ...or an inline closure when the body is trivial.
let tool = define_tool(
    "echo",
    "Echo the input",
    |_inv, params: GetWeatherParams| async move {
        Ok(ToolResult::Text(params.city))
    },
);