Repository navigation
Support dynamic tool discovery to prevent prompt context bloat #64004
Replies: 3 comments 3 replies
|
The |
Real-world data point: 67 MCP tools = ~42k tokens per turn, and the only lever today is per-project booleansConfirming the magnitude in the post with a measured case, and answering @capitaharlock's question with a concrete argument for Zed. Setup. Zed 1.20.2 (native agent), macOS, one workspace with 7 local MCP servers (1C platform tooling: platform docs, code metadata, metadata graph, standard-subsystem search, syntax check, code templates, code review). Result: 67 tools, 163 KB of tool name + description + JSON schema ≈ 42k input tokens on every request, before any conversation history. One server with 11 tools accounts for 52.6 KB (~13.5k tokens) on its own — a third of the whole tax. Two consequences worth naming in the discussion:
Cross-harness evidence that deferred loading pays off (same prompt, measured): a Claude Code session with tool search disabled sent 26,280 input tokens at 70.7 s TTFT; with tool search enabled the identical request sent 6,537 input tokens at 11.5 s. Worth noting that Claude Code silently disables tool search when Other harnesses already treat this as a solved problem: Codex has On @capitaharlock's question — where a retrieved schema lives is the whole design, and for Zed specifically it should be conversation history, not the system prefix:
So:
|
|
+1 on this — filed a follow-up in #66626 (codemode), deferred schemas solve the tool-definition cost, but tool results still round-trip through the model; a codemode tool closes that too (pi and OpenCode 2.0 ship it today). I think they're one roadmap — exposure: direct | deferred | codemode per server. @dvcrn |
Uh oh!
There was an error while loading. Please reload this page.
Problem
Zed sends full JSON schemas and descriptions for every enabled built-in and MCP tool on every turn.
Connecting tool-dense MCP servers (such as GitHub, GitLab, or browser automation servers) adds dozens of tool definitions directly into the request payload. For servers with 30 to 100 tools, schema definitions alone consume 20,000 to 60,000 tokens before conversation history is added. This limits usable context, increases API costs, and increases the rate of tool-selection errors by the model.
Currently, the only workaround is manually curating tool booleans in
agent.profilesinsidesettings.json, which does not scale across projects or workflows.Proposed solution
Implement on-demand tool loading with a configuration setting similar to the tool-access controls found in Claude Code, Codex, OpenCode, and Grok:
when_needed(on-demand): Zed loads only core tools with full schemas. Other tools appear only by name in a lightweight registry list. The model fetches full tool schemas via a built-intool_searchprimitive when it needs them.always(current behavior): All enabled tools are loaded upfront with their full JSON schemas.Tool workflow in
when_neededmoderead_file,edit_file,write_file,grep,terminal,spawn_agent,tool_search).tool_search): When the model needs an unretrieved tool, it queries the registry either by keyword or by exact name:Handling direct calls to unloaded tools
Because the model can see deferred tool names, it may occasionally attempt to call a tool before loading its schema. When this occurs, Zed should reject the call with an explicit error directing the model to fetch the schema first:
{ "error": "Tool 'mcp:github:create_issue' is deferred and its schema is not loaded in this session. Call tool_search(query: \"select:mcp:github:create_issue\", max_results: 1) to retrieve the parameter schema before calling this tool." }This prevents malformed arguments and allows the model to self-correct in the next turn.
Proposed
tool_searchschema{ "name": "tool_search", "description": "Find and load schemas for deferred tools into context. Use keywords to search descriptions, or 'select:<tool_name>' for direct lookup by name.", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "Query to find deferred tools. Supports keywords for search or 'select:name1,name2' for direct name matching." }, "max_results": { "type": "integer", "default": 5, "description": "Maximum number of results to return." } }, "required": ["query", "max_results"] } }Proposed configuration
Add a setting to
settings.jsonunderagent:{ "agent": { // "when_needed" | "always" "tool_access": "when_needed" } }This could also be exposed in the Agent Panel tool menu:
Impact
All reactions