feat(subagents): add disallowedTools field to agent definitions#3064
Conversation
Add a `disallowedTools` blocklist to agent frontmatter, letting agents specify tools they should not have access to. Supports exact tool names, MCP server-level patterns (e.g., `mcp__slack`), and display name aliases. Applied as a post-filter in AgentCore.prepareTools() after the existing `tools` allowlist. Persisted through serialize/parse roundtrips.
E2E Test ReportBinary:
All 7 tests PASS. Full test plan: |
Add Tool Configuration section to sub-agents docs explaining: - tools allowlist and disallowedTools blocklist - How MCP tools follow the same allowlist/blocklist rules - MCP server-level patterns in disallowedTools
📋 Review SummaryThis PR adds a 🔍 General Feedback
🎯 Specific Feedback🟡 High
🟢 Medium
🔵 Low
✅ Highlights
|
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
wenshao
left a comment
There was a problem hiding this comment.
packages/core/src/subagents/validation.ts:23
[Suggestion] SubagentValidator.validateConfig() still validates tools, model, and runConfig, but the new disallowedTools field is never validated. Malformed programmatic or session subagent configs can therefore carry non-string entries into runtime and fail later during execution instead of being rejected as invalid config.
Suggested fix: validate disallowedTools with the same helper/path used for tools, and add matching validator coverage.
— gpt-5.4 via Qwen Code /review
Reuse the existing validateTools() method to validate disallowedTools entries at config validation time, catching non-string and empty entries before they reach runtime.
|
Good catch @wenshao — Fixed in 422a54e: reuses the existing |
Merge origin/main into feat/disallowed-tools, keeping both the disallowedTools feature (this branch) and the approvalMode feature (from main). Also address review comment: guard disallowedTools validation with `.length > 0` to avoid misleading "inherit all tools" warning on empty arrays.
…LM#3064) * feat(subagents): add disallowedTools field to agent definitions Add a `disallowedTools` blocklist to agent frontmatter, letting agents specify tools they should not have access to. Supports exact tool names, MCP server-level patterns (e.g., `mcp__slack`), and display name aliases. Applied as a post-filter in AgentCore.prepareTools() after the existing `tools` allowlist. Persisted through serialize/parse roundtrips. * docs: document disallowedTools and MCP tool behavior for subagents Add Tool Configuration section to sub-agents docs explaining: - tools allowlist and disallowedTools blocklist - How MCP tools follow the same allowlist/blocklist rules - MCP server-level patterns in disallowedTools * fix(subagents): validate disallowedTools in SubagentValidator Reuse the existing validateTools() method to validate disallowedTools entries at config validation time, catching non-string and empty entries before they reach runtime. * test: remove flaky BaseSelectionList scroll test on Windows
TLDR
Add
disallowedToolsfield to agent definitions, allowing agents to specify a blocklist of tools they should not have access to. Supports exact tool names, MCP server-level patterns (e.g.,mcp__slackblocks all tools from that server), and display name aliases.Screenshots / Video Demo
N/A — no user-facing change in the CLI UI. This adds a new optional field to agent definition frontmatter:
Dive Deeper
Motivation: Users configuring sub-agents need a way to restrict tool access beyond the existing
toolsallowlist. The allowlist requires listing every permitted tool, which is impractical when you want "everything except X." ThedisallowedToolsblocklist solves this — agents inherit all tools by default, minus the blocked ones.How it works:
disallowedTools: write_file→["write_file"])transformToToolNames()(e.g.,WriteFile→write_file)AgentCore.prepareTools()after the allowlistmatchesMcpPattern()function (now exported)serializeSubagent()for create/update roundtripsInteraction with
toolsallowlist: If both are set,toolsis applied first (what's on the menu), thendisallowedToolsremoves from that set. If onlydisallowedToolsis set, the agent gets everything minus the blocklist.Reviewer Test Plan
disallowedTools: ["mcp__test-server__get_secret_number"]— should not be able to call that tooldisallowedTools: ["mcp__test-server"]— should block all tools from that serverdisallowedTools: ["write_file"]and notools— should have MCP access but not write_fileFull E2E test plan:
.claude/e2e-tests/pr1-mcp-bypass-disallowed-tools.mdTesting Matrix
Linked issues / bugs
Related to user question about sub-agent MCP tool access and permission scoping.