microsoft / microsoft/conductor

claude-agent-sdk: honoring the per-agent tools: allowlist needs a permission-mode redesign, not a name mapping

Open
#347 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
451
Forks
65
Avg merge
1d 18h
Merged PRs (30d)
39

Description

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:

  1. 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.

  2. 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.

  3. 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

  • #335 / #346 — MCP server support (left this carve-out explicitly out of scope)
  • docs/providers/experimental.md — promotion criterion 1 requires no carve-outs in active use

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with config/validator.py, the ClaudeAgentSdkProvider implementation, mcp/manager.py, and the SDK semantics in types.py:1581-1600; compare them with AGENTS.md and the provider promotion criteria in docs/providers/experimental.md. Done means a decided permission model that enforces per-agent tools safely, defines behavior for non-MCP names, and accurately represents support in the provider descriptor.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.