# FunctionTool

A tool defined at runtime by a name, a description, a JSON Schema, and a handler that receives JSON.

`FunctionTool` fits tools whose schema is known only at runtime, such as tools loaded from configuration. The handler implements `FunctionHandler` and returns JSON or an error string. For a tool known at compile time, [`#[tool]`](/docs/api/rust/tool-macro) derives the schema from the function.

```rust
use std::{future::Future, pin::Pin, sync::Arc};

use nanocode::tool_contract::ToolContext;
use nanocode::{FunctionHandler, FunctionTool, Tools};
use serde_json::{Value, json};

struct Inventory;

// 1. Implement the handler that receives the call's JSON input
impl FunctionHandler for Inventory {
    fn call<'a>(
        &'a self,
        _name: &'a str,
        input: Value,
        _context: ToolContext<'a>,
    ) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send + 'a>>
    {
        Box::pin(async move {
            let sku =
                input["sku"].as_str().ok_or("sku must be a string")?;
            Ok(json!({ "sku": sku, "in_stock": 12 }))
        })
    }
}

// 2. Describe the tool and register it
let inventory = FunctionTool::new(
    "inventory",
    "Report how many units of a SKU are in stock",
    json!({
        "type": "object",
        "properties": { "sku": { "type": "string" } },
        "required": ["sku"],
        "additionalProperties": false
    }),
    Arc::new(Inventory),
)
.parallel_tool_calls(true);
let tools = Tools::builder()
    .without_defaults()
    .tool(inventory)
    .build()?;
```

## Signature

```rust
// Makes a tool that calls handler with the decoded JSON input
impl FunctionTool {
    pub fn new(
        name: impl Into<String>,
        description: impl Into<String>,
        parameters: serde_json::Value,
        handler: Arc<dyn FunctionHandler>,
    ) -> Self;

    pub const fn parallel_tool_calls(self, parallel: bool) -> Self;
}
```

## Parameters

### name

* **Type:** `impl Into<String>`

The tool name that the model calls. `Tools::build` rejects an empty name and a name that is already registered.

```rust
// The model calls tools.inventory(...) in Code Mode
let tool =
    FunctionTool::new("inventory", "Report stock", schema, handler);
```

### description

* **Type:** `impl Into<String>`

The description that the model reads.

```rust
// States what the tool returns
let tool = FunctionTool::new(
    "inventory",
    "Report how many units of a SKU are in stock",
    schema,
    handler,
);
```

### parameters

* **Type:** `serde_json::Value`

The JSON Schema of the input object.

```rust
use serde_json::json;

// Requires one string field
let schema = json!({
    "type": "object",
    "properties": { "sku": { "type": "string" } },
    "required": ["sku"]
});
```

### handler

* **Type:** `Arc<dyn FunctionHandler>`

The handler that runs each call. One handler can serve several tools, because `call` receives the tool name.

```rust
use std::sync::Arc;

// Shares one handler between two tools
let handler = Arc::new(Inventory);
let stock = FunctionTool::new(
    "stock",
    "Report stock",
    schema.clone(),
    handler.clone(),
);
let reserve =
    FunctionTool::new("reserve", "Reserve a unit", schema, handler);
```

### parallel_tool_calls

* **Type:** `bool`
* **Default:** `false`

Whether the model can call this tool in parallel with other calls.

```rust
// Marks a read-only tool as safe to run in parallel
let tool =
    FunctionTool::new("inventory", "Report stock", schema, handler)
        .parallel_tool_calls(true);
```

## FunctionHandler

```rust
// Implemented by the host. HostFuture is a boxed, Send future on native
// targets.
pub trait FunctionHandler: Send + Sync + 'static {
    fn call<'a>(
        &'a self,
        name: &'a str,
        input: serde_json::Value,
        context: ToolContext<'a>,
    ) -> HostFuture<'a, Result<serde_json::Value, String>>;
}
```

`call` receives the tool name, the decoded JSON input, and the `ToolContext` of the call. An `Ok` value becomes the tool output. An `Err` string becomes a tool error output, and the model reads its text.

```rust
// Returns an error the model can act on
Box::pin(async move {
    Err::<serde_json::Value, String>("SKU A-7 is discontinued".into())
})
```
