anthropics / anthropics/claude-agent-sdk-typescript

AgentDefinition.tools is intersected with Options.tools, making sub-agent tool sets dependent on session base

Ouverte
#163 1 commentaire 2 réactions 0 personnes assignées Voir sur GitHub
bug enhancement
Langage dominant
Shell
Étoiles
1.8k
Forks
226
Métriques de merge des PR
Aucune PR mergée en 30 j

Description

## Problem

`AgentDefinition.tools` is documented as: *"Array of allowed tool names. If omitted, inherits all tools from parent."* This implies that when set, the agent gets exactly those tools.

In practice, `AgentDefinition.tools` is **intersected** with `Options.tools` (the session-level base tool set). Sub-agents cannot have tools that aren't in the session base. This makes it impossible to restrict the main-thread agent's tools without also restricting all sub-agents.

## Observed Behavior

In `cli.js`, the tool resolution function (`Os` in minified source) works as follows:

```
1. Start with Options.tools (session base — shared across ALL agents)
2. Remove ALL_AGENT_DISALLOWED_TOOLS (Task, TaskOutput, AskUserQuestion, EnterPlanMode, TaskStop, etc.)
3. Remove AgentDefinition.disallowedTools
4. If AgentDefinition.tools is defined → INTERSECT with the result from step 3
5. If AgentDefinition.tools is undefined → use all remaining tools from step 3
```

The sub-agent spawning function (`tC` in minified source) passes the **parent's** `Options.tools` as the base:

```javascript
// In tC (sub-agent runner):
resolvedTools = Os(agentDefinition, toolUseContext.options.tools, isAsync).resolvedTools
```

This means every agent — main thread and sub-agents — shares the same base tool set.

## Concrete Failure Scenario

A coordinator pattern where the main-thread agent should only have orchestration tools, and sub-agents should have execution tools:

```typescript
const result = query({
prompt: "...",
options: {
tools: ['Task', 'TodoWrite', 'AskUserQuestion'], // Restrict coordinator
agent: 'Coordinator',
agents: {
Coordinator: {
description: 'Delegates work',
tools: ['Task', 'TodoWrite', 'AskUserQuestion'],
prompt: '...',
},
Coder: {
description: 'Writes code',
tools: ['Read', 'Edit', 'Write', 'Bash', 'Grep', 'Glob'],
prompt: '...',
},
},
},
});
```

**Expected:** Coordinator gets `[Task, TodoWrite, AskUserQuestion]`. Coder gets `[Read, Edit, Write, Bash, Grep, Glob]`.

**Actual:** After `ALL_AGENT_DISALLOWED_TOOLS` strips `Task/TodoWrite/AskUserQuestion` from the base, the intersection with `Options.tools` leaves the Coder with an **empty tool set** — none of `[Read, Edit, Write, Bash, Grep, Glob]` are in the base `[Task, TodoWrite, AskUserQuestion]`.

## Workaround

Leave `Options.tools` unrestricted (full tool set) so sub-agents work, then use `PreToolUse` hooks to block the coordinator from using direct tools. This results in a reject-and-retry pattern: the coordinator attempts a disallowed tool, the hook blocks it with an error, the model retries with delegation.

## Expected Behavior

`AgentDefinition.tools` should define each agent's tool set **independently**, not as a filter on the session base. When a sub-agent specifies `tools: ['Read', 'Edit', 'Write']`, it should get exactly those tools regardless of what `Options.tools` is set to.

Alternatively, provide a mechanism to restrict the main-thread agent's tools without affecting sub-agent tool resolution — e.g., an `Options.mainAgentTools` or `Options.mainAgentDisallowedTools` that only applies to the main thread.

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.