feat: add sub-agent spawning via delegate_task tool#451
feat: add sub-agent spawning via delegate_task tool#451shivammittal274 wants to merge 3 commits intomainfrom
Conversation
Add a `delegate_task` tool that spawns ephemeral sub-agents with isolated context windows. The sub-agent is an exact replica of the parent — same model, instructions, tools, and compaction — following the AI SDK agent-as-tool pattern (ai-sdk.dev/docs/agents/subagents). - New `sub-agent.ts` with `createDelegateTaskTool` factory - Sub-agent reuses parent's model, full prompt (soul, memory, skills, user prefs, workspace, external integrations), and all tools - 15-step limit (SUB_AGENT_MAX_TURNS), own compaction, no recursion - Skipped in chat mode - New prompt section guiding delegation behavior
Greptile SummaryThis PR introduces sub-agent delegation to BrowserOS: a new Key findings:
Confidence Score: 2/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant PA as Parent Agent (AiSdkAgent)
participant DT as delegate_task tool
participant SA as Sub-Agent (ToolLoopAgent)
participant T as Tools (browser/fs/mcp/memory)
U->>PA: Task prompt
PA->>PA: Decides to delegate subtask
PA->>DT: call delegate_task({ task })
DT->>SA: subAgent.generate({ prompt: task, abortSignal })
loop Up to SUB_AGENT_MAX_TURNS (15)
SA->>T: Tool call
T-->>SA: Tool result
end
SA-->>DT: result.text (summary)
DT-->>PA: text summary as tool result
PA->>U: Final response incorporating summary
Last reviewed commit: ff8acb0 |
| // Create the sub-agent once — reused across invocations | ||
| const subAgent = new ToolLoopAgent({ | ||
| model: deps.model, | ||
| instructions, | ||
| tools: subAgentTools, | ||
| stopWhen: [stepCountIs(AGENT_LIMITS.SUB_AGENT_MAX_TURNS)], | ||
| prepareStep, | ||
| }) |
There was a problem hiding this comment.
Sub-agent instance reused across invocations
The ToolLoopAgent is constructed once at factory-creation time and then reused for every delegate_task call. If ToolLoopAgent maintains any per-instance state — particularly if stepCountIs tracks steps cumulatively across generate() calls rather than resetting per call — the second delegation will inherit leftover step count and may terminate sooner than the intended 15-step limit.
It would be safer to construct the ToolLoopAgent inside execute so each invocation starts from a guaranteed clean state:
execute: async ({ task }, { abortSignal }) => {
const subAgent = new ToolLoopAgent({
model: deps.model,
instructions,
tools: subAgentTools,
stopWhen: [stepCountIs(AGENT_LIMITS.SUB_AGENT_MAX_TURNS)],
prepareStep,
})
// ...
}If the AI SDK guarantees that generate() always resets the step counter, add a brief comment referencing the SDK docs so future readers don't have to investigate this.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/server/src/agent/sub-agent.ts
Line: 40-47
Comment:
**Sub-agent instance reused across invocations**
The `ToolLoopAgent` is constructed once at factory-creation time and then reused for every `delegate_task` call. If `ToolLoopAgent` maintains any per-instance state — particularly if `stepCountIs` tracks steps cumulatively across `generate()` calls rather than resetting per call — the second delegation will inherit leftover step count and may terminate sooner than the intended 15-step limit.
It would be safer to construct the `ToolLoopAgent` inside `execute` so each invocation starts from a guaranteed clean state:
```typescript
execute: async ({ task }, { abortSignal }) => {
const subAgent = new ToolLoopAgent({
model: deps.model,
instructions,
tools: subAgentTools,
stopWhen: [stepCountIs(AGENT_LIMITS.SUB_AGENT_MAX_TURNS)],
prepareStep,
})
// ...
}
```
If the AI SDK guarantees that `generate()` always resets the step counter, add a brief comment referencing the SDK docs so future readers don't have to investigate this.
How can I resolve this? If you propose a fix, please make it concise.Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Summary
delegate_tasktool that lets the parent agent spawn sub-agents with isolated context windowsToolLoopAgent.generate())delegate_taskfrom sub-agent toolsChanges
apps/server/src/agent/sub-agent.tsdelegate_tasktoolapps/server/src/agent/ai-sdk-agent.tsdelegate_taskinto parent toolsetapps/server/src/agent/prompt.tssub-agentsprompt section guiding delegationpackages/shared/src/constants/limits.tsSUB_AGENT_MAX_TURNS: 15Test plan
delegate_taskbun run typecheck)