You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[A2c] Remove createDelegateTool in favor of the subagents option #239
createDelegateTool() wraps one child agent as a tool. The subagents option (one task tool, a catalog in the prompt, parallel tasks, background tasks, depth limits, approvals inside sub-agents) does the same job on the same delegation core and works on both createAgent() and AgentExecutor.execute(). The docs already say "Prefer subagents for new code". Removing the older API before 1.0 leaves one way to delegate. Audit evidence: .agent-loop/audit2/our-report.md section 5, row "Delegation" (409 lines, 5 exports, "superseded by subagents").
Current state
Verified on main at cc5ddb8:
src/execution/DelegationTool.ts exports DelegationDepthExceededError (:22, extends PropagatingToolError), DelegateAgentOptions (:58), DelegateAgentResult (:81), createDelegateTool() (:102). It keeps its own AsyncLocalStorage depth counter (:53). Re-exported by src/execution/index.ts:7 (export * from './DelegationTool'), so 4 names are in the root.
The shared core stays: src/execution/delegation.ts (runSubagent, SubagentSpec, SubagentRequest) is used by src/subagents/withSubagents.ts:16,217 and src/createAgent.ts:47. It is not exported from the root.
AgentExecutor.execute() accepts subagents and maxSubagentDepth (docs/sub-agents.md:45, src/subagents/withSubagents.ts:414), so executor users have a replacement.
Tests that import createDelegateTool: src/execution/DelegationTool.test.ts (whole file), src/execution/cancellation.test.ts:14,342-345, src/execution/subagentInheritance.test.ts:8,273-281,464-484, src/execution/usage.test.ts:5,128,161,361, src/tools/defineTool.test.ts:8,159, src/flows/FlowExecutor.test.ts:700-725 (uses a delegate tool only as "a tool"); src/tools/noAiToolImport.test.ts:21 lists execution/DelegationTool.ts.
Example: examples/ops-pipeline/fixer.ts:25-28,155-185 (createFixerDelegateTool() wraps createDelegateTool() and adds a patch field), used by examples/ops-pipeline/index.ts:34,115, examples/ops-pipeline/pipeline.eval.ts:35,51, examples/ops-pipeline/fixer.test.ts:2,82-105; examples/ops-pipeline/README.md:9 describes "the monitor's delegation to the fixer agent".
Comments that name createDelegateTool(): src/execution/agentEvents.ts:63, src/execution/AgentExecutor.ts:180, src/execution/hooks.ts:72, src/execution/subagentRuntime.ts:3, src/models/usage.ts:36, src/execution/propagatingToolError.ts:7-19,49, src/execution/resume.ts:607, src/execution/toolCallExecution.ts:432.
Docs: docs/sub-agents.md:461-502 (section "## createDelegateTool()", the last section of the page), :368, :434; docs/streaming.md:304; docs/api-overview.md:55 (table row), :205, and the "Delegation" box in the diagram at :25.
Agent Forge: no use (grep of apps/agent-forge/{src,server,shared}).
Scope
In:
Delete src/execution/DelegationTool.ts and src/execution/DelegationTool.test.ts; remove src/execution/index.ts:7.
Keep PropagatingToolError (public, src/execution/propagatingToolError.ts): it is the general "rethrow, do not feed back to the model" signal. Rewrite its comments so they no longer use DelegationDepthExceededError as the example.
Tests: in cancellation.test.ts, subagentInheritance.test.ts and usage.test.ts, port each createDelegateTool case to the task tool (subagents on AgentExecutor.execute()), unless a task case with the same assertion already exists in the same file or in src/subagents/*.test.ts; then delete it and name the existing test in the pull request. In defineTool.test.ts:159 and FlowExecutor.test.ts:700-725, replace the delegate tool with a defineTool() tool (they only need "a tool"). Remove the line from noAiToolImport.test.ts.
Example: replace createFixerDelegateTool(opts) in examples/ops-pipeline/fixer.ts with createFixerTool({ agent, provider }): a defineTool() tool with input { task: string } whose execute(args, context) runs the fixer agent with AgentExecutor.execute({ agent, input: args.task, provider, signal: context.signal }), extracts the diff with extractDiffBlock(), throws EmptyPatchError when it is empty, and returns { text, patch }. Update index.ts, pipeline.eval.ts, fixer.test.ts and README.md of the example to the new name; the example's tests must keep passing.
Update the comments listed above to name only the task tool.
Docs: delete the "## createDelegateTool()" section of docs/sub-agents.md (it is the last heading, so no other heading moves); fix :368, :434; docs/streaming.md:304; docs/api-overview.md:55 row and :205; replace "Delegation" in the diagram with "Sub-agents".
Add the 4 names to src/publicSurface.test.ts / .test-d.ts (created by A1) as absent from the root.
CHANGELOG ### Breaking entry with the migration note below.
Out:
runSubagent and the delegation core in src/execution/delegation.ts: unchanged.
Root exports exactly 4 fewer names (both numbers in the pull request).
Every ported or deleted test is listed in the pull request with the task test that now covers it; the inheritance (hooks, usage roll-up), cancellation and approval-inside-child behaviors keep at least one test each through the task tool.
npx vitest run examples/ops-pipeline passes.
Full verification list in BRIEF-2.md passes, including the four Agent Forge checks.
Docs updated; npm run docs:llms re-run. The pull request notes for the docs site that sub-agents lost its last section (the Arabic page must drop it too).
CHANGELOG ### Breaking entry:
Removed createDelegateTool(), DelegateAgentOptions, DelegateAgentResult and DelegationDepthExceededError. Use the subagents option instead, on createAgent() or AgentExecutor.execute(): create the child with createAgent({ provider, instructions, description }) and pass subagents: { billing }. The model gets one task tool for every sub-agent, with the same inheritance (hooks, permissions, abort, usage roll-up) and a depth limit (maxSubagentDepth, default 1). A run at the depth limit is not offered the task tool, so a delegation cycle can no longer start; DelegationDepthExceededError is gone. See docs/sub-agents.md.
Live test
None: this ticket spends nothing.
Dependencies
A1 and A2b must merge first (A2b ports the same three test files away from ExecutionEvent; doing A2c second avoids rewriting them twice).
Owner decision required before starting (see Notes).
Conflicts: M4 and M10b edit sub-agent code and docs/sub-agents.md; rebase if they merged.
Notes for the implementer
Owner question (record the answer in the issue before starting): "May A2c remove createDelegateTool() (documented as superseded by subagents) in the next alpha?"
subagents takes agents built with createAgent({ ..., description }) (see docs/sub-agents.md:17-43), not inline specs; maxSubagentDepth defaults to 1 (docs/sub-agents.md:338). The migration note uses that shape.
The delegate tool's depth guard (AsyncLocalStorage) disappears. The task tool's guard is maxSubagentDepth (src/subagents/withSubagents.ts:72-80,406-417); a test that relied on an A -> B -> A cycle throwing should become "the task tool is not offered past the depth limit".
subagentInheritance.test.ts runs both paths through the same core; most delegate-tool cases there duplicate a task case. Delete duplicates instead of porting them.
Round 2 ticket A2c. Before starting, read the agent brief (worktree rules, verification list, live-test budget) and the plan. One ticket is one pull request; put Closes #<this issue> in it.
Goal
createDelegateTool()wraps one child agent as a tool. Thesubagentsoption (onetasktool, a catalog in the prompt, parallel tasks, background tasks, depth limits, approvals inside sub-agents) does the same job on the same delegation core and works on bothcreateAgent()andAgentExecutor.execute(). The docs already say "Prefersubagentsfor new code". Removing the older API before 1.0 leaves one way to delegate. Audit evidence:.agent-loop/audit2/our-report.mdsection 5, row "Delegation" (409 lines, 5 exports, "superseded bysubagents").Current state
Verified on
mainatcc5ddb8:src/execution/DelegationTool.tsexportsDelegationDepthExceededError(:22, extendsPropagatingToolError),DelegateAgentOptions(:58),DelegateAgentResult(:81),createDelegateTool()(:102). It keeps its ownAsyncLocalStoragedepth counter (:53). Re-exported bysrc/execution/index.ts:7(export * from './DelegationTool'), so 4 names are in the root.src/execution/delegation.ts(runSubagent,SubagentSpec,SubagentRequest) is used bysrc/subagents/withSubagents.ts:16,217andsrc/createAgent.ts:47. It is not exported from the root.AgentExecutor.execute()acceptssubagentsandmaxSubagentDepth(docs/sub-agents.md:45,src/subagents/withSubagents.ts:414), so executor users have a replacement.createDelegateTool:src/execution/DelegationTool.test.ts(whole file),src/execution/cancellation.test.ts:14,342-345,src/execution/subagentInheritance.test.ts:8,273-281,464-484,src/execution/usage.test.ts:5,128,161,361,src/tools/defineTool.test.ts:8,159,src/flows/FlowExecutor.test.ts:700-725(uses a delegate tool only as "a tool");src/tools/noAiToolImport.test.ts:21listsexecution/DelegationTool.ts.examples/ops-pipeline/fixer.ts:25-28,155-185(createFixerDelegateTool()wrapscreateDelegateTool()and adds apatchfield), used byexamples/ops-pipeline/index.ts:34,115,examples/ops-pipeline/pipeline.eval.ts:35,51,examples/ops-pipeline/fixer.test.ts:2,82-105;examples/ops-pipeline/README.md:9describes "the monitor's delegation to the fixer agent".createDelegateTool():src/execution/agentEvents.ts:63,src/execution/AgentExecutor.ts:180,src/execution/hooks.ts:72,src/execution/subagentRuntime.ts:3,src/models/usage.ts:36,src/execution/propagatingToolError.ts:7-19,49,src/execution/resume.ts:607,src/execution/toolCallExecution.ts:432.docs/sub-agents.md:461-502(section "##createDelegateTool()", the last section of the page),:368,:434;docs/streaming.md:304;docs/api-overview.md:55(table row),:205, and the "Delegation" box in the diagram at:25.apps/agent-forge/{src,server,shared}).Scope
In:
src/execution/DelegationTool.tsandsrc/execution/DelegationTool.test.ts; removesrc/execution/index.ts:7.PropagatingToolError(public,src/execution/propagatingToolError.ts): it is the general "rethrow, do not feed back to the model" signal. Rewrite its comments so they no longer useDelegationDepthExceededErroras the example.cancellation.test.ts,subagentInheritance.test.tsandusage.test.ts, port eachcreateDelegateToolcase to thetasktool (subagentsonAgentExecutor.execute()), unless ataskcase with the same assertion already exists in the same file or insrc/subagents/*.test.ts; then delete it and name the existing test in the pull request. IndefineTool.test.ts:159andFlowExecutor.test.ts:700-725, replace the delegate tool with adefineTool()tool (they only need "a tool"). Remove the line fromnoAiToolImport.test.ts.createFixerDelegateTool(opts)inexamples/ops-pipeline/fixer.tswithcreateFixerTool({ agent, provider }): adefineTool()tool with input{ task: string }whoseexecute(args, context)runs the fixer agent withAgentExecutor.execute({ agent, input: args.task, provider, signal: context.signal }), extracts the diff withextractDiffBlock(), throwsEmptyPatchErrorwhen it is empty, and returns{ text, patch }. Updateindex.ts,pipeline.eval.ts,fixer.test.tsandREADME.mdof the example to the new name; the example's tests must keep passing.tasktool.createDelegateTool()" section ofdocs/sub-agents.md(it is the last heading, so no other heading moves); fix:368,:434;docs/streaming.md:304;docs/api-overview.md:55row and:205; replace "Delegation" in the diagram with "Sub-agents".src/publicSurface.test.ts/.test-d.ts(created by A1) as absent from the root.### Breakingentry with the migration note below.Out:
runSubagentand the delegation core insrc/execution/delegation.ts: unchanged.Acceptance criteria
grep -rn "createDelegateTool\|DelegationDepthExceededError\|DelegateAgentOptions\|DelegationTool" src examples docs/*.md README.md apps/agent-forge --include=*.ts --include=*.mdfinds nothing (CHANGELOG excepted).tasktest that now covers it; the inheritance (hooks, usage roll-up), cancellation and approval-inside-child behaviors keep at least one test each through thetasktool.npx vitest run examples/ops-pipelinepasses.npm run docs:llmsre-run. The pull request notes for the docs site thatsub-agentslost its last section (the Arabic page must drop it too).### Breakingentry:Live test
None: this ticket spends nothing.
Dependencies
ExecutionEvent; doing A2c second avoids rewriting them twice).docs/sub-agents.md; rebase if they merged.Notes for the implementer
createDelegateTool()(documented as superseded bysubagents) in the next alpha?"subagentstakes agents built withcreateAgent({ ..., description })(seedocs/sub-agents.md:17-43), not inline specs;maxSubagentDepthdefaults to1(docs/sub-agents.md:338). The migration note uses that shape.AsyncLocalStorage) disappears. Thetasktool's guard ismaxSubagentDepth(src/subagents/withSubagents.ts:72-80,406-417); a test that relied on an A -> B -> A cycle throwing should become "thetasktool is not offered past the depth limit".subagentInheritance.test.tsruns both paths through the same core; most delegate-tool cases there duplicate ataskcase. Delete duplicates instead of porting them.Round 2 ticket
A2c. Before starting, read the agent brief (worktree rules, verification list, live-test budget) and the plan. One ticket is one pull request; putCloses #<this issue>in it.