-
Notifications
You must be signed in to change notification settings - Fork 985
Description
Summary
A custom agent spawned as a sub-agent via task() sees task in its tool list, recognizes its own description among available agents, and recursively delegates to itself instead of using its tools directly.
CustomAgentConfig.tools does not prevent this — even an explicit allowlist without task is ignored at runtime.
Environment
@github/copilot-sdk0.1.33-preview.0- Copilot CLI 1.0.5
- Node.js / TypeScript, macOS
Repro
const research: CustomAgentConfig = {
name: 'research',
description: 'Searches repos via Sourcebot MCP',
prompt: 'You ARE the research agent. Use your tools directly. Do NOT call task.',
tools: ['sourcebot-*', 'context7-*', 'web_search', 'web_fetch', 'report_intent'], // no "task"
infer: true,
}
const session = await client.createSession({
model: 'claude-sonnet-4.6',
mcpServers: {
sourcebot: { type: 'http', url: '...', tools: ['*'] },
context7: { type: 'local', command: 'npx', args: ['...'], tools: ['*'] },
},
customAgents: [research],
onPermissionRequest: approveAll,
})MCP servers are at session level because CustomAgentConfig.mcpServers was not functional in earlier versions (#553, since closed for .NET SDK — untested on Node.js).
What happens
Parent agent calls task(research) → spawned sub-agent calls task(research) → repeat.
Sub-agent reasoning from traces:
"Let me use the research agent which has access to Sourcebot tools."
It doesn't realize it is the research agent.
Measured impact (two live sessions)
| Session | task recursions |
MCP tool calls | Cost | Duration |
|---|---|---|---|---|
AIT-46 (tools: null) |
3 | 3 | $0.44 | 82s |
AIT-47 (tools: [explicit list without task]) |
13 | 0 | $0.56 | 102s |
Setting tools made it worse — more recursions, zero actual work.
Key finding
CustomAgentConfig.tools is not enforced for sub-agents spawned via the task() inference path. This is similar to #859 (not enforced via SessionConfig.Agent) but affects a different code path — runtime-inferred sub-agent selection.
Additional finding: hooks break sub-agents
When SessionConfig.hooks.onPreToolUse is set (even returning undefined), all sub-agents become non-functional — spawned but make zero LLM calls. Removing hooks restores sub-agent functionality. This may warrant a separate issue.
Related issues
- MCP servers in CustomAgentConfig are not exposed to the agent during execution #553 —
CustomAgentConfig.mcpServersnot exposed at runtime - AI: CustomAgentConfig.Tools not enforced when agent pre-selected via SessionConfig.Agent #859 —
CustomAgentConfig.toolsnot enforced viaSessionConfig.Agent - AI: Agent Tools with bare MCP server name not expanded — agent sees zero MCP tools #860 — bare MCP server names in agent
toolsnot expanded
Request
- Enforce
CustomAgentConfig.toolsfor sub-agents spawned viatask() - Prevent sub-agents from recursively spawning themselves via
task() - Or provide a way to exclude
taskfrom a sub-agent's tool universe