Skip to content

idea: per-peer write-tool allowlist narrowing for do-mode — inspired by Claude Code's parameterized subagent permission rules #845

Description

@github-actions

Research brief

Source: Analyst landscape survey 2026-07-24 — agent_mesh roadmap vs. comparable OSS agent frameworks (OpenHands, SWE-agent, Aider, MetaGPT/ChatDev, Renovate, claude-code-action).

Claude Code's own June 2026 release added Tool(param:value) permission-rule syntax so a rule can match a tool's input parameters with * wildcards — e.g. Agent(model:opus) to block Opus subagents (v2.1.178, 2026-06-15) — a first-party move toward finer-grained, parameterized restriction of what a spawned subagent may do, beyond a flat allow/deny per tool name. [Source: Claude Code changelog]

SWE-agent's Agent-Computer Interface (ACI) design principles argue a tool surface should be no larger than the task needs — the ACI should "help the agent recover from mistakes" and "remove unnecessary context from prior observations," i.e. a smaller, task-appropriate tool surface reduces mistake surface. [Source: arXiv:2405.15793, docs/background/aci.md]

The gap, confirmed against this repo (not just landscape-inspired)

src/config.js:49 defines WRITE_TOOLS = ['Edit', 'Write', 'MultiEdit', 'NotebookEdit'] as a single global constant. src/delegate-invocation.js:191 applies it uniformly to every do-mode spawn:

const tools = mode === 'ask' ? [...READ_TOOLS] : [...READ_TOOLS, ...WRITE_TOOLS];

There is no way for an individual peer to receive a narrower write-tool set than the full four. Contrast with WEB_TOOLS: agentWantsWebTools (delegate-invocation.js:159-188) already threads a per-agent additive grant from the operator-owned mesh.json manifest (webTools: true, ask-only, "operator-owned... so a tampered third-folder card cannot expand egress"). There is no analogous subtractive per-peer scoping for do-mode's write tools.

Concretely: a peer whose entire job is prose/doc editing gets the identical NotebookEdit/MultiEdit/Write grant as a peer that legitimately creates new files — needless blast radius. Every ACI mistake-surface argument applies to the unused tools just as much as the used ones.

Proposed direction

Add an optional writeTools array under a peer's own agent.json x-agentmesh block (the same established namespace already used for modes/meshVersion — see test/structure-conformance.test.js), e.g. "x-agentmesh": { "writeTools": ["Edit"] }. At spawn time, the tool-list builder intersects the declared list with the global WRITE_TOOLS constant — a peer can only ever narrow its own write surface, never widen it (a tampered/compromised agent.json cannot grant itself Bash or anything outside the fixed global set). Omitting the field preserves today's behavior exactly (full WRITE_TOOLS) — fully backward compatible, opt-in hardening.

This is a distinct axis from two already-open ideas, so it doesn't overlap:

Non-goals

  • No change to ask mode (already read-tool-only).
  • No per-task-call scoping via delegate_task tool args — that would violate the anti-spoof invariant (model-facing surface stays exactly { mode, task }). Scoping is declared once, out-of-band, in the peer's own agent.json — same trust boundary as idea: post-do validation gate — declarative validators in agent.json run after do-mode tasks #509's proposed validators.
  • No dynamic/runtime tool negotiation — the allowlist is static per peer, read once (like description.js reads AGENT.md once at server start).

Invariants preserved

  • Single writable root / path-guard unaffected — this narrows which write tools exist, not where they may write.
  • No Bash in do: the intersection is always a subset of WRITE_TOOLS, so Bash can never enter regardless of what a peer declares.
  • Anti-spoof: no new field is read from tool-call args, only from the peer's own manifest at spawn setup.

Considered and rejected

MetaGPT's global publish-subscribe message pool (agents broadcast to a shared bus; others subscribe by role) was also surveyed as a landscape idea for cross-peer coordination, but it directly conflicts with this project's governing "no central registry, broker, or dispatcher by design" principle (PROJECT.md) and was not carried forward as a proposal.

Sources


Draft spec location: docs/superpowers/specs/2026-07-24-per-peer-write-tool-allowlist-design.md (Goal/Non-goals/design above; invariants above; risk: a peer misconfiguring its own allowlist too narrowly just fails a do-mode task with a clear tool-not-allowed error, no security risk either direction). Spec-push to the repo is currently blocked pending #771 (DEV_MESH_PAT not configured); this issue carries the full draft in the body in the meantime, matching current practice for #818/#824/#831/etc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    blockedBlocked on a dependencygenerated:analystAnalyst agent–generated improvement idea (analyst-daily-review)needs-humansecurityspec:draftSpec being drafted

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions