Summary
ClaudeAgentSdkProvider declares workflow_tools_passthrough=False, so config/validator.py rejects any non-empty per-agent tools: list and _resolve_tool_config refuses one at execute time. #335 wired up MCP servers but deliberately left this carve-out in place, because closing it is not the name-mapping exercise it first appears to be.
Why it isn't just a name mapping
The obvious idea is to translate Conductor's <server>__<tool> names (mcp/manager.py:197, documented at docs/mcp-tools.md:150) into the CLI's mcp__<server>__<tool> and pass them as allowed_tools. Three things break that:
-
allowed_tools is not an availability filter. Per the SDK's own docstrings (types.py:1581-1600), tools selects the built-in tool set, allowed_tools is a permission auto-approve list, and disallowed_tools is the only field that removes a tool from the model's context. Putting an allowlist in allowed_tools does not prevent anything from being called.
-
permission_mode="bypassPermissions" makes it a no-op anyway. That is what the provider sets today on the default path (granting the claude_code preset without prompting). Under bypassPermissions every tool is auto-approved regardless of allowed_tools, so an allowlist would be silently ignored — exactly the "silently granting different tools than declared is a security regression" failure the current refusal exists to prevent.
-
Only MCP-shaped names are translatable at all. A workflow-level tools: entry can be an arbitrary name (e.g. web_search in examples/research-assistant.yaml:54) with no corresponding CLI tool ID. So even a correct mapping would only ever cover part of the allowlist, making workflow_tools_passthrough=True a partial truth in a boolean descriptor — which AGENTS.md explicitly forbids ("lying in the descriptor undermines the framework").
Possible directions
permission_mode="dontAsk" + allowed_tools — non-approved tools are denied, but they stay visible in the model's context, so the model can waste turns attempting them. Also changes default behavior for existing users.
- A
can_use_tool callback (ClaudeAgentOptions.can_use_tool) — the most precise enforcement point, and the only one that can deny per call with a reason.
disallowed_tools — needs the full tool list up front, which requires an MCP handshake Conductor does not perform for this provider.
Any of these needs a decision about what happens to non-MCP-shaped names, and whether the descriptor needs to become finer-grained than a single boolean.
Related
Summary
ClaudeAgentSdkProviderdeclaresworkflow_tools_passthrough=False, soconfig/validator.pyrejects any non-empty per-agenttools:list and_resolve_tool_configrefuses one at execute time. #335 wired up MCP servers but deliberately left this carve-out in place, because closing it is not the name-mapping exercise it first appears to be.Why it isn't just a name mapping
The obvious idea is to translate Conductor's
<server>__<tool>names (mcp/manager.py:197, documented atdocs/mcp-tools.md:150) into the CLI'smcp__<server>__<tool>and pass them asallowed_tools. Three things break that:allowed_toolsis not an availability filter. Per the SDK's own docstrings (types.py:1581-1600),toolsselects the built-in tool set,allowed_toolsis a permission auto-approve list, anddisallowed_toolsis the only field that removes a tool from the model's context. Putting an allowlist inallowed_toolsdoes not prevent anything from being called.permission_mode="bypassPermissions"makes it a no-op anyway. That is what the provider sets today on the default path (granting theclaude_codepreset without prompting). UnderbypassPermissionsevery tool is auto-approved regardless ofallowed_tools, so an allowlist would be silently ignored — exactly the "silently granting different tools than declared is a security regression" failure the current refusal exists to prevent.Only MCP-shaped names are translatable at all. A workflow-level
tools:entry can be an arbitrary name (e.g.web_searchinexamples/research-assistant.yaml:54) with no corresponding CLI tool ID. So even a correct mapping would only ever cover part of the allowlist, makingworkflow_tools_passthrough=Truea partial truth in a boolean descriptor — which AGENTS.md explicitly forbids ("lying in the descriptor undermines the framework").Possible directions
permission_mode="dontAsk"+allowed_tools— non-approved tools are denied, but they stay visible in the model's context, so the model can waste turns attempting them. Also changes default behavior for existing users.can_use_toolcallback (ClaudeAgentOptions.can_use_tool) — the most precise enforcement point, and the only one that can deny per call with a reason.disallowed_tools— needs the full tool list up front, which requires an MCP handshake Conductor does not perform for this provider.Any of these needs a decision about what happens to non-MCP-shaped names, and whether the descriptor needs to become finer-grained than a single boolean.
Related
docs/providers/experimental.md— promotion criterion 1 requires no carve-outs in active use