Skip to content

disallowedTools denylist and Task(agent_type) spawn restrictions #970

@bug-ops

Description

@bug-ops

Part of #974

Background

Claude Code's agent frontmatter supports a disallowedTools list (denylist) as a complement to the existing tools allowlist. Additionally, the Task tool (which spawns sub-agents) can be restricted to specific agent types — e.g. Task(explore) means the agent can only spawn the explore sub-agent. These features give fine-grained control over what agents can do and what they can delegate.

Current state in Zeph

FilteredToolExecutor in zeph-core/src/subagent/ implements a ToolPolicy with an allowlist. There is no denylist complement. SubAgentManager::spawn() can be called with any agent name — there is no per-agent restriction on which sub-agents it may spawn.

Implementation

disallowedTools denylist

  1. Add deny: Vec<String> to the existing ToolPolicy (alongside allow).
  2. Evaluation order in FilteredToolExecutor: if tool is in deny → block, else if allow is non-empty and tool not in allow → block, else allow.
  3. Wildcard support: deny: ["*"] blocks all tools (useful for plan-only agents).
  4. Update AgentFileSpec:
    tools:
      allow: [shell, web_scrape]
      deny:  [delete_file, write_file]

Task(agent_type) spawn restrictions

  1. Add allowed_spawns: Option<Vec<String>> to SubAgentDef / AgentFileSpec.
  2. In SubAgentManager::spawn(parent_id, target_name): if the parent agent has allowed_spawns: Some(list) and target_name is not in list, return Err(SpawnDenied).
  3. allowed_spawns: null (default) means unrestricted spawning.
  4. allowed_spawns: [] means the agent cannot spawn any sub-agents at all.
  5. Frontmatter syntax:
    allowed_spawns:
      - explore
      - summarizer

Acceptance criteria

  • deny: [shell] in tool policy prevents shell tool execution even if allow: [shell] is also set (deny wins).
  • deny: ["*"] blocks all tool calls.
  • allowed_spawns: [explore] prevents the agent from spawning any agent other than explore.
  • SpawnDenied error is returned (not a panic) and includes the denied agent name.
  • Unit tests: deny overrides allow, wildcard deny, spawn restriction allow, spawn restriction deny.
  • cargo nextest run -p zeph-core passes with zero warnings.

Technical notes

  • Deny evaluation must happen before allow to prevent allow-then-deny confusion.
  • SpawnDenied should be a variant in the existing SubAgentError enum.
  • Document the deny/allow interaction in code comments on ToolPolicy.
  • allowed_spawns is stored in SubAgentDef, not in SubAgentPermissions, since it is a capability constraint not a resource limit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions