Repository navigation
[BUG] System prompt advertises tools that are unavailable in the active mode #1240
Description
Describe the bug
The generated system prompt contains instructions for tools that are not available to the model after mode and tool filtering.
For example, execute_command is only part of the command tool group, so it is available in the built-in Code and Debug modes but not in Architect, Ask, or Orchestrator. Despite that, the common capabilities and rules sections tell every mode that it can use execute_command and include command-execution guidance.
This is not limited to execute_command. Other examples include:
- Orchestrator has no tool groups, but the prompt recommends
list_filesand refers toread_file. - Ask does not have the
editgroup, but the common capabilities text claims general file-writing and editing capabilities. - Architect restricts edits to Markdown files, but the common capabilities text describes unrestricted writing and editing.
- MCP guidance can be included when no MCP tool or resource is effectively available.
- Instructions can require
skill,ask_followup_question,attempt_completion,new_task, or other control tools even when the corresponding tool has been removed throughdisabledToolsor model-specific exclusions.
As a result, the model can receive instructions that it cannot follow. This can cause invalid tool attempts, retries, unnecessary token usage, and an increased mistake count. Runtime validation generally prevents a disallowed tool from executing, so this report is about prompt/tool-policy consistency rather than a confirmed permission bypass.
To Reproduce
Steps to reproduce the behavior:
- Select the built-in Architect, Ask, or Orchestrator mode, or create a custom mode without the
commandgroup. - Start a task so that the system prompt and native tool definitions are generated.
- Inspect the effective native tools sent for the active mode and confirm that
execute_commandis not logically allowed. - Inspect the generated system prompt.
- Observe that the capabilities and rules sections still say that commands can be executed with
execute_commandand include terminal-specific instructions.
Additional variants:
- Use Orchestrator mode and observe that the prompt recommends
list_fileseven though the mode has noreadgroup. - Use Ask mode and observe that the common capabilities section claims file-writing/editing capability even though the mode has no
editgroup. - In Code or Debug mode, disable
execute_commandthroughdisabledToolsand observe that command instructions remain in the prompt. - Disable an otherwise always-available tool such as
skillorattempt_completionand observe that the prompt can still require its use. - Connect an MCP server for which no tool is enabled for the prompt and no accessible resource exists; MCP guidance can still be generated based on server presence rather than effective tool availability.
Expected behavior
System-owned prompt text should only advertise or require a tool when that tool is present in the final logical tool-availability set for the request.
The same effective tool policy should be shared by:
- system prompt generation;
- API tool-definition construction;
- runtime tool-use validation; and
- system-prompt preview generation.
The effective set should account for mode groups, custom modes, disabledTools, model-specific included/excluded tools, feature flags, experiment state, MCP allowlists, enabled MCP tools, and accessible MCP resources.
Screenshots
Not applicable. The mismatch is visible by comparing the generated system prompt with the effective tool definitions for the same request.
Video
Not applicable.
What version of zoo are you running
3.76.0
Additional context
Relevant implementation paths
- Tool groups and always-available tools are defined in
src/shared/tools.ts. - Built-in mode groups are defined in
packages/types/src/mode.ts. - Effective native-tool filtering is performed in
src/core/prompts/tools/filter-tools-for-mode.ts. - Native and dynamic MCP tool definitions are assembled in
src/core/task/build-tools.ts. - The common prompt sections are assembled unconditionally in
src/core/prompts/system.ts. - Static capability claims are in
src/core/prompts/sections/capabilities.ts. - Static command, list, read, MCP, and control-tool instructions are spread across
src/core/prompts/sections/rules.ts,tool-use-guidelines.ts,system-info.ts,objective.ts, andskills.ts. - Runtime system-prompt generation and API tool construction occur at different points in
src/core/task/Task.ts. - Preview generation follows a separate path in
src/core/webview/generateSystemPrompt.ts.
Existing Architect and Ask prompt snapshots include the stale execute_command text, so the snapshots currently approve the inconsistent output instead of detecting it.
Root cause
Tool availability and prompt generation use separate sources of truth. The API tool path computes a filtered set, but prompt sections do not receive that final set and instead emit mostly static capability and rule text.
Checking only whether the mode has a particular group would fix the simplest built-in-mode cases but would remain incorrect when a tool is removed by disabledTools, model customization, feature flags, or MCP availability rules.
Suggested direction
Resolve one request-scoped effective tool policy before generating the system prompt. Pass its normalized logical tool-name set to prompt generation, API metadata construction, preview generation, and runtime validation.
The logical allowed set must remain separate from the tool definitions physically sent to a provider. This is particularly important for Gemini, where all tool declarations may be sent for conversation-history compatibility even though only a subset is logically permitted.
Prompt sections should then be composed from tool-specific fragments. For example:
- Include terminal and command guidance only when
execute_commandis logically available. - Recommend directory listing only when
list_filesis available. - Describe read, search, and edit capabilities using the specific available tools and active file restrictions.
- Include MCP guidance only when at least one MCP operation is effectively available.
- Include mandatory
skill, follow-up, completion, delegation, mode-switching, or todo instructions only when the respective control tool is available.
Protocol-critical tools need an explicit product decision. With the current task loop, attempt_completion is part of the completion protocol rather than an ordinary optional capability. A low-risk approach would be to make such lifecycle tools non-disableable and to prevent mode-essential tools such as Orchestrator's new_task from being disabled while that mode is active. Fully supporting their removal would require plain-text completion/question fallbacks in the task state machine, not only prompt changes.
User-authored custom instructions should not be silently rewritten. If they reference unavailable tools, a preview-time diagnostic would be safer than altering their content. Built-in instructions, however, should always follow the effective policy.
Suggested acceptance criteria
- Code and Debug include command guidance when
execute_commandis available. - Architect, Ask, and Orchestrator do not mention
execute_commandby default. - Orchestrator does not advertise read, list, or edit capabilities it does not have.
- Ask does not advertise editing capabilities.
- Architect's prompt reflects its Markdown-only edit restriction.
- Disabling or model-excluding an individual tool removes system-owned instructions that advertise or require it.
- MCP text depends on effective MCP operations, not merely on the presence of a connected server.
- No prompt requires a tool when the effective allowed-tool set is empty.
- Gemini may receive compatibility tool declarations, but its prompt and runtime validator use the logical allowed set.
- Runtime and preview generation produce the same effective-tool-dependent prompt sections.
- Focused mode-by-tool and disabled-tool assertions cover the behavior; snapshots are supplementary rather than the only verification.
Activity
[-][BUG][/-][+][BUG] System prompt advertises tools that are unavailable in the active mode[/+]JunyongParkDev commentedon Aug 13, 2026
Claiming
DaubnerF commentedon Aug 31, 2026
I'm interested in this as well, I stumbled upon this just recently. I would be willing to contribute a fix, although I have to admit I have never contributed to this project so I am not familiar with how this works, so I am grateful for any guidance :)
DaubnerF commentedon Aug 31, 2026
I finally read contributing.md :)
Are you still interested in providing a fix? If not, I hereby volunteer to take over (claiming)
edelauna commentedon Aug 31, 2026
@DaubnerF feel free to submit a pr
JunyongParkDev commentedon Sep 7, 2026
@DaubnerF
Sorry for the late reply - I just saw your comment. Please fell free to take over, and thanks for taking this on! :)
Narrow the change set to the tool-policy work and its regression tests
fix(task): restore caller-layer cancellation for model-metadata fetches
[Fix] Prevent unavailable tools from appearing in system prompts (Zoo…
Blanket auto-deny for unapproved commands (hands-free mode) (Zoo-Code…