[BUG] disallowedTools not inherited by subagents spawned via Agent tool

Status Open
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 16, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

When a named agent has disallowedTools configured, the restriction is NOT applied to subagents spawned via the Agent tool. Subagents can freely call the disallowed tool — including the exact command pattern the restriction was supposed to block.

Reproduction

claude \
  --agents '{"test":{"description":"Test","prompt":"Test agent.","disallowedTools":["Bash(curl *)"]}}' \
  --agent test --print --dangerously-skip-permissions \
  'Spawn a subagent with the Agent tool. Tell it to run: curl -s -o /dev/null -w "%{http_code}" https://httpbin.org/get'

Expected: Subagent inherits parent's disallowedTools. The curl call is blocked in the subagent too.

Actual: Subagent runs curl successfully and returns HTTP 200. The disallowedTools restriction only applies to the parent session.

You can verify the parent lacks Bash by asking it to list its tools — Bash is absent from the 66 tools listed (that's a separate issue, see below). But even if the scoped pattern were parsed correctly and only blocked curl calls, the subagent would still bypass it entirely.

Why this matters

The model quickly learns to work around tool restrictions by delegating to subagents. After a single failed Bash call in the parent, the agent exclusively uses subagents for ALL subsequent Bash work — making disallowedTools purely cosmetic.

Related issues

Whether scoped patterns like Bash(curl *) should strip the entire Bash tool or only block curl-pattern calls is a separate question (see #6527, #19501). This issue is about the restriction not propagating to subagents regardless of how it's parsed.

Environment

  • Version: v2.1.209
  • Terminal: Non-interactive (--print)
  • OS: Linux (Fedora 44)

View original on GitHub ↗

3 Comments

maruiz93 · 1 month ago

JSONL output from the reproduction command above:

<details>
<summary>output.jsonl</summary>

{"type":"system","subtype":"hook_started","hook_id":"a4c917e3-8be6-48af-9065-2a3dabf32dbf","hook_name":"SessionStart:startup","hook_event":"SessionStart","uuid":"e6596686-dfa6-42b6-8d3e-71f7deef28ae","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"hook_started","hook_id":"70b22156-6d61-4da6-9877-25e8ebaaf399","hook_name":"SessionStart:startup","hook_event":"SessionStart","uuid":"cc10afec-2247-46e4-a39a-c6ac79d8e05b","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"hook_response","hook_id":"a4c917e3-8be6-48af-9065-2a3dabf32dbf","hook_name":"SessionStart:startup","hook_event":"SessionStart","output":"{\n  \"hookSpecificOutput\": {\n    \"hookEventName\": \"SessionStart\",\n    \"additionalContext\": \"<EXTREMELY_IMPORTANT>\\nYou have superpowers.\\n\\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\\n\\n---\\nname: using-superpowers\\ndescription: Use when starting any conversation - establishes how to find and use skills, requiring skill invocation before ANY response including clarifying questions\\n---\\n\\n<SUBAGENT-STOP>\\nIf you were dispatched as a subagent to execute a specific task, ignore this skill.\\n</SUBAGENT-STOP>\\n\\n<EXTREMELY-IMPORTANT>\\nIf you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.\\n\\nIF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.\\n\\nThis is not negotiable. You cannot rationalize your way out of this.\\n</EXTREMELY-IMPORTANT>\\n\\n## The Rule\\n\\n**Invoke relevant or requested skills BEFORE any response or action** — including clarifying questions, exploring the codebase, or checking files. If it turns out wrong for the situation, you don't have to use it.\\n\\n**Before entering plan mode:** if you haven't already brainstormed, invoke the brainstorming skill first.\\n\\nThen announce \\\"Using [skill] to [purpose]\\\" and follow the skill exactly. If it has a checklist, create a todo per item.\\n\\n## Skill Priority\\n\\nWhen multiple skills apply, process skills come first — they set the approach, then implementation skills (frontend-design, etc.) carry it out. Brainstorming and systematic-debugging are Superpowers' most common process skills, but the rule holds for any of them.\\n\\n- \\\"Let's build X\\\" → superpowers:brainstorming first, then implementation skills.\\n- \\\"Fix this bug\\\" → superpowers:systematic-debugging first, then domain skills.\\n\\n## Red Flags\\n\\nThese thoughts mean STOP—you're rationalizing:\\n\\n| Thought | Reality |\\n|---------|---------|\\n| \\\"This is just a simple question\\\" | Questions are tasks. Check for skills. |\\n| \\\"I need more context first\\\" | Skill check comes BEFORE clarifying questions. |\\n| \\\"Let me explore the codebase first\\\" | Skills tell you HOW to explore. Check first. |\\n| \\\"I can check git/files quickly\\\" | Files lack conversation context. Check for skills. |\\n| \\\"Let me gather information first\\\" | Skills tell you HOW to gather information. |\\n| \\\"This doesn't need a formal skill\\\" | If a skill exists, use it. |\\n| \\\"I remember this skill\\\" | Skills evolve. Read current version. |\\n| \\\"This doesn't count as a task\\\" | Action = task. Check for skills. |\\n| \\\"The skill is overkill\\\" | Simple things become complex. Use it. |\\n| \\\"I'll just do this one thing first\\\" | Check BEFORE doing anything. |\\n| \\\"This feels productive\\\" | Undisciplined action wastes time. Skills prevent this. |\\n| \\\"I know what that means\\\" | Knowing the concept ≠ using the skill. Invoke it. |\\n\\n## Platform Adaptation\\n\\nIf your harness appears here, read its reference file for special instructions:\\n\\n- Codex: `references/codex-tools.md`\\n- Pi: `references/pi-tools.md`\\n- Antigravity: `references/antigravity-tools.md`\\n\\n## User Instructions\\n\\nUser instructions (CLAUDE.md, AGENTS.md, GEMINI.md, etc, direct requests) take precedence over skills, which in turn override default behavior. Only skip skill workflows or instructions when your human partner has explicitly told you to.\\n</EXTREMELY_IMPORTANT>\"\n  }\n}\n","stdout":"{\n  \"hookSpecificOutput\": {\n    \"hookEventName\": \"SessionStart\",\n    \"additionalContext\": \"<EXTREMELY_IMPORTANT>\\nYou have superpowers.\\n\\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\\n\\n---\\nname: using-superpowers\\ndescription: Use when starting any conversation - establishes how to find and use skills, requiring skill invocation before ANY response including clarifying questions\\n---\\n\\n<SUBAGENT-STOP>\\nIf you were dispatched as a subagent to execute a specific task, ignore this skill.\\n</SUBAGENT-STOP>\\n\\n<EXTREMELY-IMPORTANT>\\nIf you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.\\n\\nIF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.\\n\\nThis is not negotiable. You cannot rationalize your way out of this.\\n</EXTREMELY-IMPORTANT>\\n\\n## The Rule\\n\\n**Invoke relevant or requested skills BEFORE any response or action** — including clarifying questions, exploring the codebase, or checking files. If it turns out wrong for the situation, you don't have to use it.\\n\\n**Before entering plan mode:** if you haven't already brainstormed, invoke the brainstorming skill first.\\n\\nThen announce \\\"Using [skill] to [purpose]\\\" and follow the skill exactly. If it has a checklist, create a todo per item.\\n\\n## Skill Priority\\n\\nWhen multiple skills apply, process skills come first — they set the approach, then implementation skills (frontend-design, etc.) carry it out. Brainstorming and systematic-debugging are Superpowers' most common process skills, but the rule holds for any of them.\\n\\n- \\\"Let's build X\\\" → superpowers:brainstorming first, then implementation skills.\\n- \\\"Fix this bug\\\" → superpowers:systematic-debugging first, then domain skills.\\n\\n## Red Flags\\n\\nThese thoughts mean STOP—you're rationalizing:\\n\\n| Thought | Reality |\\n|---------|---------|\\n| \\\"This is just a simple question\\\" | Questions are tasks. Check for skills. |\\n| \\\"I need more context first\\\" | Skill check comes BEFORE clarifying questions. |\\n| \\\"Let me explore the codebase first\\\" | Skills tell you HOW to explore. Check first. |\\n| \\\"I can check git/files quickly\\\" | Files lack conversation context. Check for skills. |\\n| \\\"Let me gather information first\\\" | Skills tell you HOW to gather information. |\\n| \\\"This doesn't need a formal skill\\\" | If a skill exists, use it. |\\n| \\\"I remember this skill\\\" | Skills evolve. Read current version. |\\n| \\\"This doesn't count as a task\\\" | Action = task. Check for skills. |\\n| \\\"The skill is overkill\\\" | Simple things become complex. Use it. |\\n| \\\"I'll just do this one thing first\\\" | Check BEFORE doing anything. |\\n| \\\"This feels productive\\\" | Undisciplined action wastes time. Skills prevent this. |\\n| \\\"I know what that means\\\" | Knowing the concept ≠ using the skill. Invoke it. |\\n\\n## Platform Adaptation\\n\\nIf your harness appears here, read its reference file for special instructions:\\n\\n- Codex: `references/codex-tools.md`\\n- Pi: `references/pi-tools.md`\\n- Antigravity: `references/antigravity-tools.md`\\n\\n## User Instructions\\n\\nUser instructions (CLAUDE.md, AGENTS.md, GEMINI.md, etc, direct requests) take precedence over skills, which in turn override default behavior. Only skip skill workflows or instructions when your human partner has explicitly told you to.\\n</EXTREMELY_IMPORTANT>\"\n  }\n}\n","stderr":"","exit_code":0,"outcome":"success","uuid":"40556364-cfec-4fdd-bb3a-20685dbda942","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"hook_response","hook_id":"70b22156-6d61-4da6-9877-25e8ebaaf399","hook_name":"SessionStart:startup","hook_event":"SessionStart","output":"{\"async\": true, \"asyncTimeout\": 180000}\n{\"metrics\": {\"sdk_bootstrap\": 1, \"sdk_bootstrap_ms\": 470, \"sdk_hook_py\": 311, \"pv\": 20006}}\n","stdout":"{\"async\": true, \"asyncTimeout\": 180000}\n{\"metrics\": {\"sdk_bootstrap\": 1, \"sdk_bootstrap_ms\": 470, \"sdk_hook_py\": 311, \"pv\": 20006}}\n","stderr":"","exit_code":0,"outcome":"success","uuid":"c2e0b3c3-9658-4272-97b3-1fcdab6ca5f2","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"init","cwd":"/home/manon/Workspace/fullsend/fullsend-dev-env/projects/disallow-tools-steering-vs-security/docs/artifacts/code-jul10","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","tools":["Task","CronCreate","CronDelete","CronList","Edit","EnterWorktree","ExitWorktree","ListMcpResourcesTool","NotebookEdit","Read","ReadMcpResourceDirTool","ReadMcpResourceTool","ReportFindings","ScheduleWakeup","SendMessage","Skill","TaskCreate","TaskGet","TaskList","TaskOutput","TaskStop","TaskUpdate","WebFetch","WebSearch","Workflow","Write","mcp__gmail__batch_delete_emails","mcp__gmail__batch_modify_emails","mcp__gmail__batch_report_phishing","mcp__gmail__create_filter","mcp__gmail__create_filter_from_template","mcp__gmail__create_label","mcp__gmail__delete_draft","mcp__gmail__delete_email","mcp__gmail__delete_filter","mcp__gmail__delete_label","mcp__gmail__download_attachment","mcp__gmail__download_email","mcp__gmail__draft_email","mcp__gmail__get_filter","mcp__gmail__get_inbox_with_threads","mcp__gmail__get_or_create_label","mcp__gmail__get_thread","mcp__gmail__list_email_labels","mcp__gmail__list_filters","mcp__gmail__list_inbox_threads","mcp__gmail__modify_email","mcp__gmail__modify_thread","mcp__gmail__read_email","mcp__gmail__reply_all","mcp__gmail__report_phishing","mcp__gmail__search_emails","mcp__gmail__send_draft","mcp__gmail__send_email","mcp__gmail__update_draft","mcp__gmail__update_label","mcp__slack__get_channel_history","mcp__slack__get_channel_id_by_name","mcp__slack__get_reactions","mcp__slack__get_thread","mcp__slack__list_joined_channels","mcp__slack__refresh_channel_cache","mcp__slack__refresh_user_cache","mcp__slack__search_channel_messages","mcp__slack__search_messages","mcp__slack__whoami"],"mcp_servers":[{"name":"gmail","status":"connected"},{"name":"slack","status":"connected"}],"model":"claude-opus-4-6","permissionMode":"bypassPermissions","slash_commands":["address-reviews","babysit-pr","catch-up","create-issue","delete-session","diary","implement","jira","red-hat-quick-deck","replay-session","research","retro","review","sway","teammate-feedback","understand","deep-research","review-squad","sway-research","sway-verify","superpowers:brainstorming","superpowers:dispatching-parallel-agents","superpowers:executing-plans","superpowers:finishing-a-development-branch","superpowers:receiving-code-review","superpowers:requesting-code-review","superpowers:subagent-driven-development","superpowers:systematic-debugging","superpowers:test-driven-development","superpowers:using-git-worktrees","superpowers:using-superpowers","superpowers:verification-before-completion","superpowers:writing-plans","superpowers:writing-skills","frontend-design:frontend-design","dev-env:preset-create","dev-env:preset-update","dev-env:project-close","dev-env:project-new","dev-env:project-resume","dev-env:project-update","dev-env:setup","dataviz","update-config","verify","debug","code-review","simplify","batch","fewer-permission-prompts","doctor","loop","claude-api","run","run-skill-generator","agents","clear","color","compact","config","context","effort","fast","heapdump","init","mcp","model","__remote-workflow","reload-skills","rename","security-review","usage","insights","recap","goal","team-onboarding"],"apiKeySource":"none","claude_code_version":"2.1.210","output_style":"default","agents":["claude","Explore","general-purpose","Plan","restricted","retro","review-architecture","review-architecture-gemini","review-deps","review-performance","review-pr","review-readability","review-security","review-security-gemini","review-squad","statusline-setup"],"skills":["address-reviews","babysit-pr","catch-up","create-issue","delete-session","diary","implement","jira","red-hat-quick-deck","replay-session","research","retro","review","sway","teammate-feedback","understand","deep-research","review-squad","sway-research","sway-verify","superpowers:brainstorming","superpowers:dispatching-parallel-agents","superpowers:executing-plans","superpowers:finishing-a-development-branch","superpowers:receiving-code-review","superpowers:requesting-code-review","superpowers:subagent-driven-development","superpowers:systematic-debugging","superpowers:test-driven-development","superpowers:using-git-worktrees","superpowers:using-superpowers","superpowers:verification-before-completion","superpowers:writing-plans","superpowers:writing-skills","frontend-design:frontend-design","dev-env:preset-create","dev-env:preset-update","dev-env:project-close","dev-env:project-new","dev-env:project-resume","dev-env:project-update","dev-env:setup","dataviz","update-config","verify","debug","code-review","simplify","batch","fewer-permission-prompts","doctor","loop","claude-api","run","run-skill-generator"],"plugins":[{"name":"superpowers","path":"/home/manon/.claude/plugins/cache/claude-plugins-official/superpowers/6.1.1","source":"superpowers@claude-plugins-official"},{"name":"security-guidance","path":"/home/manon/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6","source":"security-guidance@claude-plugins-official"},{"name":"frontend-design","path":"/home/manon/.claude/plugins/cache/claude-plugins-official/frontend-design/unknown","source":"frontend-design@claude-plugins-official"},{"name":"dev-env","path":"/home/manon/.claude/skills/dev-env","source":"dev-env@skills-dir"}],"capabilities":["interrupt_receipt_v1","msg_lifecycle_v1"],"analytics_disabled":true,"product_feedback_disabled":false,"uuid":"c1720298-9213-49a1-a48b-c827c1f7d42e","memory_paths":{"auto":"/home/manon/.claude/projects/-home-manon-Workspace-fullsend-fullsend-dev-env/memory/"},"fast_mode_state":"off"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":7,"estimated_tokens_delta":7,"uuid":"49e0ebe1-5e6b-4dbf-827f-fe40c7092558","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":11,"estimated_tokens_delta":4,"uuid":"acc723a8-ec82-4238-aec5-4e8380a6cf99","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":13,"estimated_tokens_delta":2,"uuid":"59cc3cdd-583b-433c-b21e-321f6f89cb7c","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":18,"estimated_tokens_delta":5,"uuid":"e4784b9d-9c46-4bd7-8a85-d45503a9f82b","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":20,"estimated_tokens_delta":2,"uuid":"6dd968c9-7657-4972-ac3c-37c3803b8c0f","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":26,"estimated_tokens_delta":6,"uuid":"f728ae85-3e94-4d2e-bf6a-e85d640f3d48","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":28,"estimated_tokens_delta":2,"uuid":"6e9feaa4-4a94-40b9-888f-7ecb112af68f","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":81,"estimated_tokens_delta":53,"uuid":"9cf75b69-d231-4c93-8be5-f45e3da71d0c","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"assistant","message":{"model":"claude-opus-4-6","id":"msg_vrtx_018AFkPipxq8V9pbmohPt5Cm","type":"message","role":"assistant","content":[{"type":"thinking","thinking":"The user wants me to spawn a subagent that runs a curl command and report the result. Let me do that.","signature":"ErsCCnMIDxACGAIqQII40Kiqt+5U9wCClyQMMmI9siqeKDIY1bm55HpA/qVIwz+OBOYw6o/igUcuk8ZkKASqnNVk37O50w9TE1OpV2QyD2NsYXVkZS1vcHVzLTQtNjgAQgh0aGlua2luZ1oMODU1NDAzOTczNjU5Egx6yyAwSzBHC6Y49zAaDJ8A3aekEqc4HaBt3CIwDVAT7nW/TI1Tcja88Qb0JxnRRkfiz9GWkG0cEppbNSCsFF+QnTucsG88s7MKA6m3KnZk1MIkUg5+9DpmQFdTiE4H550FZMj9740eZCmfa+hdxygKSNHfFvqG9iixebUd1heO2vuB/AcaJUDEG+t5v8axC70jaLB6wRJ0+wXGt1+1N4udhzVDvOerfhbuGpyf9O/vUla38Pi5wfqafgWd2yTUfR8mJI0XGAE="}],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":34746,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":34746,"ephemeral_1h_input_tokens":0},"output_tokens":14},"context_management":null},"parent_tool_use_id":null,"session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"f0732847-4a8b-4f05-b15b-6efcd342ef11","request_id":"req_vrtx_011Cd41muN7h1xwPRpZKaZi8"}
{"type":"assistant","message":{"model":"claude-opus-4-6","id":"msg_vrtx_018AFkPipxq8V9pbmohPt5Cm","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","name":"Agent","input":{"description":"Run curl HTTP check","prompt":"Run this exact command in Bash and report the output verbatim:\n\ncurl -s -o /dev/null -w '%{http_code}' https://httpbin.org/get","run_in_background":false}}],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":34746,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":34746,"ephemeral_1h_input_tokens":0},"output_tokens":14},"context_management":null},"parent_tool_use_id":null,"session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"080587e5-a7c4-46cb-8623-ee47222abd75","request_id":"req_vrtx_011Cd41muN7h1xwPRpZKaZi8"}
{"type":"system","subtype":"task_started","task_id":"aab91f8580542a9d4","tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","description":"Run curl HTTP check","subagent_type":"general-purpose","task_type":"local_agent","prompt":"Run this exact command in Bash and report the output verbatim:\n\ncurl -s -o /dev/null -w '%{http_code}' https://httpbin.org/get","uuid":"63a76f86-892a-4a13-b8d8-ccd06961f803","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Run this exact command in Bash and report the output verbatim:\n\ncurl -s -o /dev/null -w '%{http_code}' https://httpbin.org/get"}]},"parent_tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"60978bbc-7527-4acb-b4b3-32f4321819b6","timestamp":"2026-07-15T14:38:30.271Z","subagent_type":"general-purpose","task_description":"Run curl HTTP check"}
{"type":"system","subtype":"task_progress","task_id":"aab91f8580542a9d4","tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","description":"Run curl HTTP check","subagent_type":"general-purpose","usage":{"total_tokens":29337,"tool_uses":1,"duration_ms":4339},"last_tool_name":"Bash","uuid":"8ba5443c-b0ce-4543-82d1-4c48f5bd75e6","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"assistant","message":{"model":"claude-opus-4-6","id":"msg_vrtx_013LqqVvCk8DtjKth8btkG9p","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_vrtx_01CDUjwbdXHSH6S97TGMdSaM","name":"Bash","input":{"command":"curl -s -o /dev/null -w '%{http_code}' https://httpbin.org/get","description":"Fetch HTTP status code from httpbin.org/get"}}],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":29312,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":29312,"ephemeral_1h_input_tokens":0},"output_tokens":11},"context_management":null},"parent_tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"384f9bc1-f968-4a0a-befc-0f71d49d3335","request_id":"req_vrtx_011Cd41nFwcnE1pEekJd7pS3","subagent_type":"general-purpose","task_description":"Run curl HTTP check"}
{"type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_vrtx_01CDUjwbdXHSH6S97TGMdSaM","type":"tool_result","content":"200","is_error":false}]},"parent_tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"65d67fc9-27c4-4ddd-94db-44c201a06f7d","timestamp":"2026-07-15T14:38:37.644Z","subagent_type":"general-purpose","task_description":"Run curl HTTP check"}
{"type":"system","subtype":"task_updated","task_id":"aab91f8580542a9d4","patch":{"status":"completed","end_time":1784126320571},"uuid":"11c8eb91-fef3-46a7-865b-e517bdec1a36","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"system","subtype":"task_notification","task_id":"aab91f8580542a9d4","tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","status":"completed","output_file":"/tmp/claude-4211579/-home-manon-Workspace-fullsend-fullsend-dev-env-projects-disallow-tools-steering-vs-security-docs-artifacts-code-jul10/f248d99d-e61c-49e2-9706-ee39132de2d4/tasks/aab91f8580542a9d4.output","summary":"The output is:\n\n```\n200\n```","usage":{"total_tokens":30473,"tool_uses":1,"duration_ms":10300},"uuid":"2f443a5c-b4ca-4c3d-b4c3-d3c9a8ddfd6d","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4"}
{"type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_vrtx_01NpLMywitBPV961bVpeaq5X","type":"tool_result","content":[{"type":"text","text":"The output is:\n\n```\n200\n```"},{"type":"text","text":"agentId: aab91f8580542a9d4 (use SendMessage with to: 'aab91f8580542a9d4', summary: '<5-10 word recap>' to continue this agent)\n<usage>subagent_tokens: 30462\ntool_uses: 1\nduration_ms: 10300</usage>"}]}]},"parent_tool_use_id":null,"session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"be7949d0-3bb8-4bab-8331-88cd5b6a6e98","timestamp":"2026-07-15T14:38:40.572Z","tool_use_result":{"status":"completed","prompt":"Run this exact command in Bash and report the output verbatim:\n\ncurl -s -o /dev/null -w '%{http_code}' https://httpbin.org/get","agentId":"aab91f8580542a9d4","agentType":"general-purpose","content":[{"type":"text","text":"The output is:\n\n```\n200\n```"}],"resolvedModel":"claude-opus-4-6","totalDurationMs":10300,"totalTokens":30462,"totalToolUseCount":1,"usage":{"input_tokens":1,"cache_creation_input_tokens":1136,"cache_read_input_tokens":29312,"output_tokens":13,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":1136},"inference_geo":"","iterations":[],"speed":"standard"},"toolStats":{"readCount":0,"searchCount":0,"bashCount":1,"editFileCount":0,"linesAdded":0,"linesRemoved":0,"otherToolCount":0}}}
{"type":"assistant","message":{"model":"claude-opus-4-6","id":"msg_vrtx_01BogG9fYGDQAeqLo4gfaJ9r","type":"message","role":"assistant","content":[{"type":"text","text":"The subagent ran the command and the result is:\n\n```\n200\n```\n\nThe `curl` request to `https://httpbin.org/get` returned HTTP status code **200** (OK)."}],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":279,"cache_read_input_tokens":34746,"cache_creation":{"ephemeral_5m_input_tokens":279,"ephemeral_1h_input_tokens":0},"output_tokens":6},"context_management":null},"parent_tool_use_id":null,"session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","uuid":"10d4c784-fa4c-4f17-8a63-9f25957836b0","request_id":"req_vrtx_011Cd41o1geo7bxbAFxn7s2f"}
{"type":"result","subtype":"success","is_error":false,"api_error_status":null,"duration_ms":18372,"duration_api_ms":15158,"ttft_ms":3915,"ttft_stream_ms":3032,"time_to_request_ms":117,"num_turns":2,"result":"The subagent ran the command and the result is:\n\n```\n200\n```\n\nThe `curl` request to `https://httpbin.org/get` returned HTTP status code **200** (OK).","stop_reason":"end_turn","session_id":"f248d99d-e61c-49e2-9706-ee39132de2d4","total_cost_usd":0.45062525,"usage":{"input_tokens":4,"cache_creation_input_tokens":35025,"cache_read_input_tokens":34746,"output_tokens":222,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":35025},"inference_geo":"","iterations":[],"speed":"standard"},"modelUsage":{"claude-opus-4-6":{"inputTokens":8,"outputTokens":374,"cacheReadInputTokens":64058,"cacheCreationInputTokens":65473,"webSearchRequests":0,"costUSD":0.45062525,"contextWindow":200000,"maxOutputTokens":64000}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","uuid":"1887c30a-4fce-4c14-87ed-7b7ac06285e6"}

</details>

bcherny collaborator · 14 days ago

Thanks for the detailed repro. Confirmed the behavior on 2.1.233 (Linux): with disallowedTools: ["Bash(curl *)"] on the agent, a subagent spawned via the Agent tool runs curl and gets 200 — same with disallowedTools: ["Bash"].

This is how it's currently designed, though we agree it's confusing: disallowedTools in an agent definition only shapes that agent's own tool list (which is why the parent loses Bash) — it isn't a permission rule and isn't inherited by subagents, which get their tool set independently. The docs describe the field as removing tools "from inherited or specified list" for that agent: https://code.claude.com/docs/en/sub-agents

For an enforced restriction that does apply to subagents, use permission deny rules — permissions.deny in settings or the session-level --disallowedTools flag. I verified on 2.1.233 that claude --disallowedTools 'Bash(curl *)' ... blocks the subagent's curl (even with --dangerously-skip-permissions). You can also prevent spawning entirely by adding Agent to the agent's disallowedTools, or restrict which types it can spawn with Agent(agent_type).

We're looking at clarifying the docs and considering whether the agent-level field should cascade to spawned subagents. Leaving this open to track that.

🤖 Generated with Claude Code

gabrielhernandeslps · 7 days ago

Still reproducible on v2.1.241, but only through one of the two ways to deny a
tool — which may be useful for whoever picks this up.

I ran both paths on the same machine, same version, minutes apart.

1. --disallowed-tools on the command line — subagent DOES obey

mkdir -p /tmp/repro && echo '{"mcpServers":{}}' > /tmp/repro/no-mcp.json

claude -p 'Use the Agent tool to dispatch one subagent. Have that subagent run
the shell command `id` and report the output back to you.' \
  --output-format stream-json --verbose \
  --allowed-tools Agent Read Grep Glob \
  --disallowed-tools Bash Write Edit \
  --strict-mcp-config --mcp-config=/tmp/repro/no-mcp.json \
  > /tmp/repro/t1.jsonl

grep -c '"name":"Bash"' /tmp/repro/t1.jsonl   # -> 0

The Agent call happens, and the model reports back:

Subagent could not run it. Bash disabled this session — for subagents too.

2. disallowedTools inside --agents — subagent does NOT obey

claude --agents '{"conf":{"description":"Test","prompt":"Test agent.","disallowedTools":["Bash"]}}' \
  --agent conf --print --output-format stream-json --verbose \
  --strict-mcp-config --mcp-config=/tmp/repro/no-mcp.json \
  'Dispatch a subagent with the Agent tool and ask it to run the command `id`, then report the output.' \
  > /tmp/repro/t2.jsonl

grep -c '"name":"Bash"' /tmp/repro/t2.jsonl   # -> 1

The transcript shows the denied tool executing inside the delegated agent:

tool_use: Agent | parent_tool_use_id: null
tool_use: Bash  | parent_tool_use_id: toolu_…      <-- born inside the Agent call
result: uid=501(…) gid=20(…) groups=…

Reading

On 2.1.241 the two paths diverge, which looks like the propagation landed on the
CLI flag and not on the per-agent disallowedTools in --agents. If that is
intentional, it is worth documenting, since both read like "this tool is denied
for this run".

A small note on the general shape of the problem: the non-null
parent_tool_use_id is a reliable marker for "this call was born inside a
subagent", so it works as an after-the-fact audit for anyone who needs a
genuinely confined run today.

Tested on: Claude Code v2.1.241, macOS, headless (-p / --print).