multi-agent-lab / docs /adr /0012-capability-based-tool-contract.md
agharsallah
Refactor code structure for improved readability and maintainability
5424fe6
|
Raw
History Blame Contribute Delete
1.64 kB
# ADR-0012: Capability-Based Tool Contract
## Status
Accepted
## Context
The manifest carried a `tools` list, but nothing stood behind it — the fourth
stable contract (tools) was named, not implemented. Agents need to call tools
(image generation, retrieval, oracles), and "the Artist gets image-gen, the
Critic does not" must be enforced by the runtime, not by convention.
## Decision
Add `ToolRegistry` (`src/tools/registry.py`) as a capability-checked broker.
Agents never hold a tool; they ask the registry, which checks the calling agent's
`manifest.tools` grant before dispatching, raising `CapabilityViolation` on a
denied call. Tools are `(name, description, run)` triples; `run(**params)`
returns a JSON-serialisable dict the agent folds into its event.
`ManifestAgent` exposes `call_tool()` (capability-checked) and injects granted
tool descriptions into the prompt. A built-in deterministic `oracle` tool plus a
`fortune-teller` handler agent exercise the whole path end-to-end (scenario
`oracle-grove`), with its result recorded on the ledger.
Live MCP servers are deliberately **deferred**: the same `(name, description,
run)` interface fronts an in-process callable today and an MCP-server-backed tool
later, so swapping one for the other is invisible to agents.
## Consequences
- Least-privilege tool access is enforced at runtime and is testable.
- Tool output is first-class ledger data, not a side channel.
- The contract is stable across in-process tools and future MCP servers.
- A tool-using agent and a tool-less agent can sit in the same cast, scoped
independently — demonstrated in `oracle-grove`.