Ctrl K
ComunidadGuías…

docs/src/tool-registry.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Tool Registry

The tool registry manages all tools available to the agent during a
conversation. It tracks where each tool comes from, which audience may use it,
and supports filtering by both properties.

## Tool Sources

Every registered tool has a `ToolSource` that identifies its origin:

- **`Builtin`** — tools shipped with the binary (exec, web_fetch, etc.)
- **`Mcp { server }`** — tools provided by an MCP server, tagged with the
  server name
- **`Wasm { component_hash }`** — tools provided by a WASM component

This replaces the previous convention of identifying MCP tools by their
`mcp__` name prefix, providing type-safe filtering instead of string matching.

## Registration

Every entry also has a `ToolAudience`:

- **`Trusted`** — authenticated owner and authorized operator turns
- **`Public`** — eligible for explicitly configured untrusted origins such as
  webhook payloads

Registration is fail-closed. Built-in tools are trusted-only by default, and
all MCP and WASM tools are trusted-only. A reviewed built-in must explicitly use
`register_public` to become public. Tool descriptions and third-party metadata
cannot grant public access.

Public registration does not grant a tool to messaging-channel guests or
shared rooms. Those turns receive an additional deny-all request policy. A
webhook also receives no tools unless its configuration explicitly opts in.

```rust
// Trusted-only built-in tool (the default)
registry.register(Box::new(MyTool::new()));

// Built-in reviewed as safe for untrusted input
registry.register_public(Box::new(PublicTool::new()));

// Trusted-only MCP tool, tagged with server name
registry.register_mcp(Box::new(adapter), "github".into());
```

Duplicate names are rejected rather than overwritten. Intentional wrappers use
`replace`, which preserves the original source and audience metadata.

## Filtering

When MCP tools are disabled for a session, the registry can produce a filtered
copy:

```rust
// Type-safe: filters by ToolSource::Mcp variant
let no_mcp = registry.clone_without_mcp();

// Remove all MCP tools in-place (used during sync)
let removed_count = registry.unregister_mcp();

// Keep only tools explicitly reviewed for public use
let public = registry.clone_for_audience(ToolAudience::Public);
```

## Schema Output

`list_schemas()` includes source metadata in every tool schema:

```json
{
  "name": "exec",
  "description": "Execute a command",
  "parameters": { ... },
  "source": "builtin",
  "audience": "trusted"
}
```

```json
{
  "name": "mcp__github__search",
  "description": "Search GitHub",
  "parameters": { ... },
  "source": "mcp",
  "mcpServer": "github",
  "audience": "trusted"
}
```

The source and audience fields are available to the UI for diagnostics. The
audience is enforced by registry filtering before model tool schemas are built;
it is not an instruction that the model is expected to follow.

## Lazy Registry Mode

By default every LLM turn includes full JSON schemas for all registered tools.
With many MCP servers this can burn 15,000+ tokens per turn. **Lazy mode**
replaces all tool schemas with a single `tool_search` meta-tool that the model
uses to discover and activate tools on demand.

### Configuration

```toml
[tools]
registry_mode = "lazy"   # default: "full"
```

### How it works

1. The model receives only `tool_search` in its tool list.
2. `tool_search(query="memory")` returns name + description pairs (max 15), no schemas.
3. `tool_search(name="memory_search")` returns the full schema and **activates** the tool.
4. On the next iteration the model calls `memory_search` directly — standard pipeline, hooks fire normally.

The runner re-computes schemas each iteration, so activated tools appear
immediately. The iteration limit is tripled in lazy mode to account for the
extra discovery round-trips.

### When to use

- Many MCP servers connected (50+ tools)
- Long conversations where input token cost matters
- Sub-agent runs that only need a few specific tools

In **full** mode (default), all schemas are sent every turn — no behavioral change from before this feature.