How a tool is classified
First match wins:- An editor’s call, set on Tools or through the mapping endpoint (
action: read, or any confirm/edit/none = write). - The app’s annotations. Declared side effects come first:
destructiveHint: true, oropenWorldHint: trueon a tool not markedreadOnlyHint: true, make it a write even when it’s named like a read (get_and_archive). ThenreadOnlyHint:trueis a read,falsea write, whatever the name says. A read-only tool that reaches the outside world (a web search:readOnlyHintandopenWorldHintboth true) stays a read. - Claros’s guess, proposed once per tool when it’s registered. It may mark a tool write, but it can never mark a write-looking name (
create_,update_,delete_,submit_,send_,pay_,call_,execute_…) as read. Only an expert can. - The name, until Claros answers:
get,list,search,read,find,describe,fetchprefixes,check_,run_,export_, or exactlyversion/ping. Everything else is a write.
GET /v1/tools/kinds?app=<server> after registering tools, on every tools/list and at most every 30 s on writes.
Registration
Everytools/list the server answers is passed to the agent unchanged, then its tools are sent to Claros (POST /v1/tools): only new tools or tools whose definition changed. It’s fire and forget: a failure is logged and retried on the next tools/list, and never delays a call.
Other paths
- A JSON-RPC batch that contains a write
tools/callis rejected. - Only
tools/callis inspected; everything else is relayed byte for byte.