Files
cleveragents-core/docs/adr/ADR-011-tool-system.md
freemo c2db74ba81
CI / lint (push) Successful in 15s
CI / build (push) Successful in 16s
CI / quality (push) Successful in 20s
CI / security (push) Successful in 35s
CI / typecheck (push) Successful in 42s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m38s
CI / integration_tests (push) Successful in 3m11s
CI / docker (push) Successful in 39s
CI / coverage (push) Successful in 4m58s
CI / benchmark-publish (push) Successful in 17m32s
Docs: Restyled ADR pages
2026-03-10 12:38:35 -04:00

12 KiB

adr_number, title, status_history, tier, authors, superseded_by, related_adrs, acceptance
adr_number title status_history tier authors superseded_by related_adrs acceptance
11 Tool System
2026-02-16
Proposed
Jeffrey Phillips Freeman
2026-02-16
Accepted
Jeffrey Phillips Freeman
2
Jeffrey Phillips Freeman
null
number title relationship
2 Namespace System Tools use namespaced identifiers for discovery and conflict resolution
number title relationship
4 Data Validation Tool input/output schemas are Pydantic models with JSON Schema generation
number title relationship
8 Resource System Tools declare resource bindings that determine which resources they operate on
number title relationship
10 Actor and Agent Architecture Tools serve as atomic execution nodes within actor graphs
number title relationship
12 Skill System Skills compose tools into reusable collections for actor assignment
number title relationship
13 Validation Abstraction Validations are a specialized Tool subtype with structured pass/fail semantics
number title relationship
15 Sandbox and Checkpoint Tool invocations create checkpoints for rollback and recovery
number title relationship
28 Agent Skills Standard (AgentSkills.io) Agent Skills are a tool source (`agent_skill`) integrated into the Tool Registry
number title relationship
29 Model Context Protocol (MCP) Adoption MCP tools are registered as Tool records and follow the four-stage tool lifecycle
number title relationship
30 Skill Abstraction Definition Tools are the atomic operations that skills collect and present to actors
number title relationship
37 Tool Reachability and Access Projection Extends resource bindings with transitive reachability, access projection, and read/write routing
votes_for votes_against abstentions
voter comment
Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com> The four-stage lifecycle with dual role as skill component and graph node is a clean unification

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 <FILE>, 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<String, ResourceSlot>)
  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.