Write tools agents can call
The rules every WebMCP tool on your site should follow, whether you write it or Agent Nic does. Schemas, handlers, errors, and how to test before you ship.
Write tools agents can call
An agent picks a tool by reading its name, description and input schema, then calls it with the arguments it thinks fit. It can't see your code, can't retry with a debugger, and rereads every tool's text on every page. A tool that works only when called the way its author imagined fails for real agents.
These are the rules Agent Nic follows when it writes tools into your code, and the checks it runs before it opens a pull request. Follow them in tools you write yourself.
Name and description
- Name:
snake_case, verb first, unique on the page:search_products,add_to_cart,book_table. - Description: one or two sentences on what the tool does and when to use it. Don't repeat what the schema already says (parameter names, types, choices, defaults, limits): agents read both, and every word costs tokens on every page.
- Annotations:
readOnlyHintfor tools that only read;consequentialHintfor payments, orders, bookings, messages and anything irreversible;untrustedContentHintfor tools that return user-written content.
Input schema
The schema is JSON Schema with type: "object".
- Required means required. List a field in
requiredonly if the tool can't do anything without it. A search box, a filter or a sort order is optional: leaving it empty is a normal call. - Choices (
enum) only for fixed values. Useenumwhen the allowed values are fixed in your code:["price", "newest"]. Never build an enum from what your page renders:<option value={category.slug}>is data, and copying it into a schema gives agents the literal textcategory.slug. Describe the field instead ("A category slug, e.g. electronics") or add a tool that lists the categories. - No empty choices. An option like
<option value="">All</option>means "leave it out", not a value: drop it from the enum and make the field optional. - Types an agent can produce:
string,number,integer,boolean,array,object. Put formats in the description or informat("email","date"). - Every
requiredentry must exist inproperties.
The handler (execute)
- Validate in code; reject only what's required. The browser doesn't check arguments against the schema or fill defaults. Check required fields, and do what your site does when an optional field is left empty: an empty search lists everything, no category means all categories. Leave optional fields out of the request instead of rejecting the call.
- Return errors as values; never throw them. Return
{ error: "What went wrong", hint: "What to try instead" }for bad input or a failed request. Throwing is only for cancellation. - Honour the
AbortSignal. Passsignalto everyfetch, and stop when it's aborted. - Call your site the way your site does. Same API route, method, body shape and headers as your own code, or the same server action with the same arguments.
- Return something useful. The parsed JSON, or a short summary of it; never
undefined.
What the SDK adds when your tools go through it
Tools registered through the Agentronics SDK (client.registerTool, which is how Agent Nic's code registers them) get a safety layer between the agent and your handler:
- Any call shape works. Agents and workbenches call
execute(args),execute(args, { signal }), or pass the arguments as a JSON string. The handler always gets an object and anAbortSignal. - Errors reach the agent as text. A thrown error, a denied access rule or a refused review comes back as
{ error: "…" }instead of an exception the agent can't read. Only the agent's own cancellation rejects. - Always a usable result.
undefinedbecomes{ ok: true }; afetchResponsereturned by mistake is read for you; values that can't be serialised become text. - No call hangs forever. After 30 seconds (
toolTimeoutMs) the call is aborted, yourfetchgets the abort, and the agent is told it timed out.
Your handlers should still follow the rules above: the SDK keeps a bad handler from crashing the agent, but it can't make a wrong request right.
Test before you ship
Call every tool the way an agent would, before it goes live:
- With no arguments, or only the required ones. It must not return an error about missing input.
- With every field filled with a sensible value.
- Check it returns a value (never
undefined), doesn't throw, finishes, and calls your API (or server action).
Agent Nic runs exactly these calls on every handler it writes, in an isolated sandbox with a fake page and API, and fixes or drops any tool that fails before it opens the pull request.
Content-Security-Policy
If your site sends a Content-Security-Policy, the SDK needs https://cdn.jsdelivr.net in script-src (the SDK file) and https://api.agentronics.dev in connect-src (rules, tool registry and events). Agent Nic adds both to the policies it finds in your repo (Next.js headers(), middleware, vercel.json, netlify.toml, _headers, <meta http-equiv>) and lists any it couldn't edit in the pull request.