v1.3.11

Tool Dispatch

Last updated


How one round of tool calls is checked, run, and recorded: the three passes, deferred schemas, which tools run concurrently, and how repeated calls are deduplicated.

Three-pass tool concurrency


toolCall.go splits each round's tool calls into three serial passes; only Pass 2 fans out:
PassModeWork
1 — pre-flightSerialUnwrap run_tool into the named tool; refuse a tool called directly that is not in the loaded set (with a hint to fetch its schema with find_tools and call run_tool); duplicate-call dedupe (tool|args hash); return the schema, and ask for a re-invoke, when a tool is called before its schema was fetched; existence check, so a name with no registered handler never runs (since v1.2.0); confirm gate; JSON-schema validation
2 — executeConcurrent for IsConcurrent-tagged tools, at most MAX_CONCURRENT_TOOLS at a time — half the CPU cores, at least 3, since v1.3.0 (a fixed 5 from v1.0.20) — with the rest queued; serial otherwisetools.Execute
3 — commitSerialLand sessionData.Tools and ToolHistories, update the dedupe map, write the result cache, emit EventToolResult

Since v1.2.0 tool schemas are deferred. For every provider except claude-code, the request's tools array holds only find_tools, run_tool, reasoning_guide, write_todo, chat_history, ask_user and write_result (plus client tools; reasoning_guide joined in v1.2.1, write_todo in v1.2.3, the last three in v1.3.5); every other tool is listed by name in the turn context, its schema is fetched with find_tools, and it is called as run_tool(name, args). claude-code gets every tool except run_tool, but all of them except find_tools and client tools start unmarked, so the first call to each returns its schema instead of running. Since v1.3.5 a failed tool result ends with a next: hint: store_secret when the error points to a missing or rejected credential, otherwise write_error(outcome=resolved) once a different fix works (before v1.3.11 it pointed to error_history(mode=write), Removed in v1.3.11). The per-tool AlwaysLoad flag was removed; use find_tools to load a schema. Removed in v1.2.0.
Concurrent-tagged built-in tools (21): read_files, find_files, find_tools, file_history, chat_history, error_history, write_error (since v1.3.11), fetch_page, search_web, http_request, public_api_list, download_file, test_tool, calculate, subagents, background_subagents, list_chatbot, send_to_chatbot, reasoning_guide, html_template, write_todo (since v1.0.26; find_note left the set when it was removed in v1.0.23). generate_audio and generate_image do not carry the flag. script_* / ext_* tools run concurrently only when their own definition declares it; user-defined api_* tools were dropped (Removed in v1.3.2), use the built-in public_api_list with http_request instead. edit_file, remove_file, restore_file, run_command, background_command, interactive tools, and MCP tools always run serially — the parallel run_command_readonly tool added in v1.0.23 was removed in v1.0.25. run_command_background was renamed background_command (Removed in v1.3.2), and run_websocket was dropped (Removed in v1.3.2) with no replacement.
Dedupe is per run, not per session: a repeated tool|args pair returns the earlier result instead of executing again, and a successful edit_file, remove_file or restore_file invalidates the read_files entries covering the paths it touched. A separate 30-minute result cache in ToriiDB (db_0) covers fetch_page, search_web, and http_request GET calls only. Pass 3 writes it for http_request alone; since v1.3.1 fetch_page and search_web write their own unfiltered result from the handler and apply the decision-model filters on every return, cached or fresh. fetch_page entries are shared across sessions.
中文