reading · 8 min
What Is a Tool?
Objective: define a tool as the agent’s action surface and the contract a tool must present.
Tools are the “act” step
Every agent loop iterates three phases: perceive an observation, decide what to do, act on that decision. Until now the “act” step has been a simple return value — the policy prints an answer and the loop stops. Tools extend that step into the world: a tool call is the agent writing a file, querying a database, fetching a URL, or calling any other external operation you choose to expose.
The perceive-decide-act cycle makes the role of a tool precise. The model decides — it selects which tool to invoke and what argument to pass. The runtime acts — it executes the registered function and returns a result. That result is the next observation, fed back into the loop. The model never reaches outside the cycle on its own; every side-effect is mediated by a tool you own.
The tool contract
A tool is not just a Python function. It is a named, described, typed, deterministic unit the policy can reason about. The contract has four parts:
- Name — a short, unambiguous identifier the model uses to select this tool. Names should read like verbs:
get_weather,search_documents,write_file. - Description — a natural-language sentence the model reads to understand when to use the tool and what it does. This description is part of the instruction; author it with the same care as code. Vague descriptions produce wrong selections.
- Typed arguments — each tool accepts a declared, validated argument shape. Validation happens in your runtime, before execution, every time. An argument that does not match the schema is an error the loop can handle; an unvalidated argument reaching a database or file system is a vulnerability.
- Deterministic implementation — given the same arguments, a tool should return the same result (or a stable, predictable error). Side-effectful tools (network calls, file writes) should be designed for idempotency where possible and isolated for testing. Real network and I/O wiring is a production concern (real integration: subsystem D).
The model selects; your registry executes
A critical security and correctness property: the model never executes arbitrary code. It selects a name from the set of tools you have registered and proposes an argument. Your runtime maps that name to a function in your registry and calls it. If the name is not in the registry, that is an observable error — not a crash, not an eval.
This means the attack surface for a tool-using agent is exactly the set of tools you register. A well-designed registry is small, with each tool doing one thing well. Large, vague tools are harder to describe, harder to test, and harder to reason about — both for you and for the model.
Best practice: keep each tool small, independently testable, and precisely described — the model only chooses the tool by name; argument parsing and execution are your code, not the model’s.
Tools are individually testable
Because a tool is a plain function with declared inputs and outputs, it can be tested without a model, without a loop, and without any agent infrastructure. Write unit tests for each tool in isolation before wiring it into the registry. A tool that is hard to test in isolation is a tool whose contract is unclear — fix the contract, then the test becomes easy.
Next: A Tool-Using Loop