Repository navigation
feat(subagent): let the model choose foreground or background lanes - #282
Merged
Merged
Conversation
The subagent tool now exposes run_in_background and timeout_seconds. A
background call returns a lane id at once; the lane sends one terminal
<agent-notification> with a summary, usage, child session paths, and the
output (oversized output goes through the tool-output retention boundary).
agent_send takes {lane_id, action: reply|stop|status}. Reply only applies to
single-agent lanes and no longer re-runs a parallel or chain batch. Status
reads in-memory state without waiting. Aliases, groups, and fan-out
addressing are removed, and the model-facing schemas reject unknown fields.
Every rejecting check (discovery, mode, batch size, unknown agents, project
agent confirmation) runs before a lane exists. Each background turn has a
wall-clock limit, idle keep-alive children stop after 10 minutes, a session
holds at most 8 running lanes and keeps the 16 most recent finished ones.
session_shutdown stops the runtime's own lanes, waits up to 3 seconds, and
forces the rest down; rpc children join the process-exit sweep.
Print and JSON modes, STEP_DISABLE_SUBAGENT_BACKGROUND=1, and
[subagent] background = false run background requests in the foreground with
a notice. [subagent] background_timeout_seconds sets the default limit and is
validated in both config.toml and the StepCode JSON config.
liuedcson
requested review from
MelodyVAR,
Uking-xxx and
ZouR-Ma
as code owners
October 21, 2026 09:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The model could not choose between running a subagent in the foreground and in the background. Background lanes existed only as internal plumbing, and their control surface had several defects:
agent_sendreply rebuilt the call from the lane's original params, so replying to a parallel or chain lane re-ran the whole batch.to.allmade a single command fan out to unrelated lanes./new,/resume,/fork, reload) and quit did not stop a session's lanes or their rpc children, so late results could reach a replaced session.Changes
subagentgainsrun_in_background(defaultfalse) andtimeout_seconds(60–7,200, background only). The model-facing schemas forsubagent, its task and chain items, andagent_sendsetadditionalProperties: false.lane_followed by eight hex digits. When the lane finishes, fails, or is stopped, it sends one<agent-notification lane="…" tasks="N">. The notification opens with a summary such asLane lane_1a2b3c4d finished: 2 completed, 1 failed., followed by duration, usage, child session ids and JSONL paths, auto-cancelled dialogs, failure reasons, and output. Oversized output goes through the existing tool-output retention boundary.agent_sendis now{lane_id?, action: "reply" | "stop" | "status", prompt?, interrupt?}. Reply works only for single-agent lanes and runs only the follow-up task. Status is non-blocking: it reads in-memory state and returns the tail of the last output, or lists lanes whenlane_idis omitted.session_shutdownstops only the current runtime's lanes. It waits up to 3 seconds, then kills the remaining children and removes their temp directories. It clears the widget and drops late callbacks through an epoch check.tuiorrpcallow background lanes. Print and JSON modes,STEP_DISABLE_SUBAGENT_BACKGROUND=1, and[subagent] background = falserun the call in the foreground. The result then starts with a notice explaining why.[subagent] background_timeout_secondssets the default limit. Out-of-range values are reported as settings warnings and ignored. The StepCode JSON config (STEPCODE_CONFIG_PATH) reads and writes the same settings undersubagent.executionis now"background"for lane runs and"blocking"otherwise. Previously a foreground parallel call reported"background".Behavior and compatibility
subagentandagent_sendtool descriptions and in the system prompt's Delegation section. The new text says to use the foreground when the next step needs the result, and not to sleep or poll after starting a lane. It also documents the threeagent_sendactions and removes alias, group, and all addressing. Every Step session with thesubagenttool receives this text.alias,group,subscribe: "none", andagent_send'stoobject. Extra fields in model calls now fail validation instead of being ignored.agentId,alias,event, andstatustolaneandtasks. The renderer still readsdetails.agentId, so older transcripts render as before.[subagent] backgroundand[subagent] background_timeout_seconds. New environment variable:STEP_DISABLE_SUBAGENT_BACKGROUND.Validation
pnpm run check: passed.packages/coding-agent:pnpm exec vitest --run test/step-subagent-events.test.ts test/subagent-*.test.ts test/step-capabilities-extension.test.ts test/step-system-prompt.test.ts test/stepcode-config.test.ts test/step-settings-manager.test.ts test/step-tool-profile.test.ts test/workflow-*.test.ts test/session-index: 22 files and 390 tests passed.Limitations
./test.shwas not used as evidence. On the author's machine it fails in unrelated git-dependent suites because the isolated HOME breaks a local git wrapper; those suites also fail onmain.