--- adr_number: 11 title: Tool System status_history: - - '2026-02-16' - Proposed - Jeffrey Phillips Freeman - - '2026-02-16' - Accepted - Jeffrey Phillips Freeman tier: 2 authors: - Jeffrey Phillips Freeman superseded_by: null related_adrs: - number: 2 title: Namespace System relationship: Tools use namespaced identifiers for discovery and conflict resolution - number: 4 title: Data Validation relationship: Tool input/output schemas are Pydantic models with JSON Schema generation - number: 8 title: Resource System relationship: Tools declare resource bindings that determine which resources they operate on - number: 10 title: Actor and Agent Architecture relationship: Tools serve as atomic execution nodes within actor graphs - number: 12 title: Skill System relationship: Skills compose tools into reusable collections for actor assignment - number: 13 title: Validation Abstraction relationship: Validations are a specialized Tool subtype with structured pass/fail semantics - number: 15 title: Sandbox and Checkpoint relationship: Tool invocations create checkpoints for rollback and recovery - number: 28 title: Agent Skills Standard (AgentSkills.io) relationship: Agent Skills are a tool source (`agent_skill`) integrated into the Tool Registry - number: 29 title: Model Context Protocol (MCP) Adoption relationship: MCP tools are registered as Tool records and follow the four-stage tool lifecycle - number: 30 title: Skill Abstraction Definition relationship: Tools are the atomic operations that skills collect and present to actors - number: 37 title: Tool Reachability and Access Projection relationship: Extends resource bindings with transitive reachability, access projection, and read/write routing acceptance: votes_for: - voter: Jeffrey Phillips Freeman comment: The four-stage lifecycle with dual role as skill component and graph node is a clean unification votes_against: [] abstentions: [] --- ## Context CleverAgents must integrate tools from multiple sources — built-in file/git operations, MCP server-hosted tools, Agent Skills (SKILL.md-based instructions), and custom user-defined tools. Each source has different discovery mechanisms, execution protocols, and capability characteristics. The system needs a uniform tool abstraction that normalizes these differences while preserving source-specific capabilities like checkpointing, resource binding, and sandbox awareness. ## Decision Drivers - Must integrate tools from four distinct sources (built-in, MCP servers, Agent Skills, custom) with different discovery and execution protocols - Tools must serve a dual role: as LLM tool-calling targets within skills and as deterministic graph nodes in actor workflows - Resource bindings must decouple tools from specific resources, enabling portability across projects - Need a uniform four-stage lifecycle (discover, activate, execute, deactivate) to normalize source-specific differences - Change tracking must be driven by tool invocations, not by parsing LLM output, to ensure reliable auditable changesets - Capability metadata (read-only, checkpointable, side effects) must be declared per tool to enable safety enforcement at runtime ## Decision A **tool** is the atomic unit of execution — the smallest piece of functionality that can read, write, or transform resources. Tools are namespaced, independently registered, and follow a **four-stage lifecycle** (discover, activate, execute, deactivate). Every tool has a uniform interface regardless of source, and plays a **dual role**: as a component of a skill (available for LLM tool-calling) and as a tool node in an actor graph (deterministic, non-LLM execution step). ## Design ### Tool Identity and Registration Tools follow the namespace system (`[[server:]namespace/]name`). They are defined in YAML, registered via `agents tool add --config `, and stored in the persistent **Tool Registry**. The registry stores: name, description, source, config path, input/output schemas (JSON Schema), capability metadata, resource slots, and implementation code or server reference. ### Tool Sources | Source | Discovery | Execution | Examples | |--------|-----------|-----------|---------| | **Built-in** | Hardcoded descriptors | Native Python calls | `read_file`, `write_file`, `edit_file`, `search_files` | | **MCP** | MCP server `tools/list` | JSON-RPC `tools/call` | Any MCP-compliant server tool | | **Agent Skill** | SKILL.md frontmatter parsing | Agent-mediated instruction following | Instruction-based tools from SKILL.md files | | **Custom** | YAML registration | User-defined implementation | User-created tools | ### Four-Stage Lifecycle **discover()**: Find and catalog the tool. Built-in: return hardcoded descriptors. MCP: spawn server, `initialize` handshake, `tools/list`. Agent Skill: parse SKILL.md frontmatter (~50-100 tokens). Custom: parse YAML definition. **activate()**: Prepare the tool for use. Built-in: no-op. MCP: ensure server running, register for `notifications/tools/list_changed`. Agent Skill: load full SKILL.md body into agent context. Custom: load implementation. **execute(params, ctx)**: Run the tool. Built-in: call native Python. MCP: translate to `tools/call` JSON-RPC, rewrite sandbox paths, validate params, record changes. Agent Skill: agent-mediated execution following instructions. Custom: user-defined execution. **deactivate()**: Clean up. MCP: clean server shutdown. Agent Skill: remove instructions from context. Others: no-op. ### Dual Role **As a skill component**: When an actor references a skill, all tools in that skill become available for LLM tool-calling. The LLM generates tool call requests, and the Tool Router validates and dispatches them. **As an actor graph node**: `type: tool` nodes in actor graphs execute deterministically without LLM involvement. Can reference a named registered tool or define an anonymous inline tool. ### Tool Interface ``` Tool: Identity: name, qualified_name, source (mcp | agent_skill | builtin | custom) Schema: input_schema (JSONSchema), output_schema (JSONSchema) CapabilityMetadata: read_only, writes, write_scope, idempotent, checkpointable, checkpoint_scope, side_effects, cost_profile, human_approval_required ResourceBindings: slots (Map) Lifecycle: discover(), activate(), execute(params, ctx), deactivate() ``` ### Tool Adapter Layer Each source has an adapter that translates to the uniform interface: - **MCPToolAdapter**: Manages MCP server lifecycle, JSON-RPC communication, sandbox path rewriting, and capability inference from tool names. - **AgentSkillAdapter**: Three-tier progressive disclosure (metadata ~50-100 tokens → instructions < 5000 tokens → resources variable). - **BuiltinToolAdapter**: Direct native Python execution with hardcoded capability metadata. - **CustomToolAdapter**: User-defined implementation with manually declared capabilities. ### Resource Bindings Tools declare **resource slots** — named slots specifying what resource type and access mode is needed. Three binding modes: - **Contextual** (default): Resolved from the plan's project at activation time. - **Static**: Hardcoded to a specific resource by name via `bind` field. - **Parameter**: Passed as argument at invocation time via `from_param` field. Built-in tool groups have implicit resource slots (e.g., `file_operations` implicitly binds a `directory` slot of type `fs-directory` or `git-checkout`). ### Capability Metadata Every tool declares capabilities: `read_only`, `writes`, `write_scope` (file paths, resource slots, environment), `idempotent`, `checkpointable`, `checkpoint_scope` (file, transaction, commit, snapshot), `side_effects`, `cost_profile`, and `human_approval_required`. Metadata origin varies by source: built-in (hardcoded, not overridable), MCP (inferred + overrides), Agent Skill (SKILL.md frontmatter + overrides), custom (manually declared). ### Metadata Overrides When referencing a named tool in a skill or actor graph, `capability` and `description` fields can be overridden at the point of use. Overrides are shallow-merged, never persist back to the registry, and cannot override schema or built-in metadata. ### Anonymous Tools Inline tool definitions in skill YAML or actor graph nodes. Same format as named tools but unregistered, unnamespaced, and scoped only to their defining context. ### Tool Execution Flow Six-step pipeline: LLM generates call → Tool Router validates → Resource binding resolution and sandbox setup → Adapter-specific execution → Change recording → Result return. ### Change Tracking The changeset is built from tool invocations, not by parsing LLM output. Each tool execution receives a `ToolExecutionContext` with sandbox, plan, resources, and a changes recorder. Write operations record their changes directly. ## Constraints - Tools must not parse LLM output to extract code or changes. All resource modification happens through tool invocations. - `read_only: true` actions can only use tools where `read_only: true`. Enforced at runtime. - Tool input/output schemas are JSON Schema, generated from Pydantic models where applicable. - Anonymous tools share the same format as named tools but are scoped only to their defining skill or actor graph. - Maximum tool calls per actor step is controlled by `plan.tool.max-calls-per-step` (default: 25). - Maximum retries for transient failures is controlled by `plan.tool.max-retries` (default: 3). ## Consequences ### Positive - A single tool interface normalizes four different sources (built-in, MCP, Agent Skill, custom) behind the same lifecycle and capability model. - The dual role (skill component + graph node) maximizes tool reuse across LLM-driven and deterministic execution. - Resource bindings decouple tools from specific resources, enabling portability across projects. - Change tracking from tool invocations ensures reliable, auditable changesets. ### Negative - The adapter layer adds complexity — each source requires its own adapter implementation with source-specific behavior. - Capability inference for MCP tools (from tool names) is heuristic and may be inaccurate. - The four-stage lifecycle adds overhead for simple tools that need no activation or deactivation. ### Risks - MCP server availability is an external dependency. Server crashes or network failures during execution require retry and recovery logic. - Agent Skill tools depend on LLM instruction-following quality, which is less reliable than programmatic execution. - The capability metadata for custom and MCP tools is self-declared and may be inaccurate. ## Alternatives Considered None — specification-driven requirement. The tool system with its four-stage lifecycle, dual role, adapter layer, and resource binding model is prescribed by the specification. ## Compliance - **Adapter conformance tests**: Each adapter (MCP, Agent Skill, Built-in, Custom) has tests verifying correct lifecycle behavior across all four stages. - **Resource binding tests**: Tests verify all three binding modes with correct resolution and error handling for missing bindings. - **Capability enforcement tests**: Tests verify that `read_only` actions reject tools with `writes: true`, and that `human_approval_required` tools trigger approval gates. - **Change tracking tests**: Tests verify that the changeset accurately reflects all tool invocations and contains no changes from LLM output parsing. - **Schema validation**: Tool registration validates input/output schemas against JSON Schema specification.