Reference/Agent patterns
Tool schemas and registries
Name → callable, JSON args, error dicts, allowlists. The model never gets globals()[name].
A registry is a dict:
TOOLS = {"geocode": fn, "weather": fn, "finish": fn}
Dispatch
python
def dispatch(name, args):
if name not in TOOLS:
return {class="tok-s">"error": class="tok-s">"unknown_tool", class="tok-s">"name": name}
err = validate(name, args)
if err:
return {class="tok-s">"error": class="tok-s">"bad_args", class="tok-s">"detail": err}
return TOOLS[name](**args)Schema fields to document for the model
| Field | Example |
|---|---|
| name | geocode |
| description | one sentence |
| args | city: str, 1–80 chars |
| returns | lat, lon or error |
Safety knobs
| Knob | Default |
|---|---|
| allowlist | registry keys only |
| extra args | reject |
| timeouts | return timeout dict |
| rate limit | 429-shaped error |
| side effects | none unless named mutate |
Mutate vs read
Ops agents split registries. Read tools always allowed. Mutate tools go through HUMAN_APPROVAL + digest.
Watch out:lambda **kw: eval(kw["code"]) is not a tool. It is a remote shell.