Skip to content

[EPIC-Y][LOU-Y4] Background sub-agents: task background:true with agent_status, agent_await and agent_cancel - #91

Merged
LinuxDevil merged 2 commits into
mainfrom
lou-y4-background-subagents
Oct 1, 2026
Merged

LinuxDevil merged 2 commits into
mainfrom
lou-y4-background-subagents

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

What

  • task gains background?: boolean (default false). With true it starts the sub-agent and returns { taskId, status: 'running', agent } right away. If the concurrency limit is full it returns status: 'queued' instead.
  • When subagents is set, three tools are registered alongside task:
    • agent_status({ taskId? }) returns { tasks: [{ taskId, agent, status, elapsedMs, approvalId?, toolName?, error? }] }. status is one of queued | running | done | failed | cancelled | awaiting-approval.
    • agent_await({ taskId | taskIds, timeoutMs? }) returns the same result text the synchronous task path returns (in result), or an error. A task still running when the timeout passes reports status: 'timeout'.
    • agent_cancel({ taskId }).
  • withSubagentOptions(subagents, { maxConcurrent }) sets the per-lead-run concurrency (default 3, validated). It is a new export in src/subagents and the package root. Calls beyond the limit queue and start as slots free.
  • Background children use the same delegation core (runSubagent), so they inherit hooks, tracing, onEvent/stream, usage roll-up and the depth budget. Each child gets its own AbortController, bound to the same parent tool-call scope. Aborting the lead's signal cancels every queued or running background child.
  • A background child that pauses for approval ends as awaiting-approval, with the child's approvalId and toolName. agent_await returns that state immediately.
  • A user tool named agent_status, agent_await or agent_cancel now conflicts with subagents, the same way a tool named task already did.
  • The system-prompt block tells the lead to collect background tasks with agent_await before it finishes.
  • Docs: a "Background sub-agents" section in docs/sub-agents.md, regenerated llms files, and a CHANGELOG entry under Added.

Why

Parity gap with eve (background tasks) and open-harness (background sub-agents with agent_await/status/cancel and maxConcurrent). Today task blocks the lead until the child finishes.

Acceptance criteria

  • task takes background?: boolean. With true it returns { taskId, status: 'running', agent } immediately. The child inherits the parent runtime, and aborting the parent cancels background children.
  • agent_status, agent_await (result summary or timeout) and agent_cancel are registered alongside task.
  • maxConcurrent (default 3) bounds running background children. Further calls get queued and start as slots free. maxSubagentDepth still applies.
  • A child that pauses for approval shows awaiting-approval in agent_status. It cannot be resumed in this PR, so agent_await returns awaiting-approval with the approvalId (fallback described in the ticket; limitation documented).
  • Tests with mockModel cover: results flow back through agent_status/agent_await, maxConcurrent queues, agent_await timeout, cancel, parent abort cancels children, approval pause, depth limit, unknown ids and bad options.
  • Docs section "Background sub-agents", regenerated llms files, CHANGELOG (Added).

Deferred to LOU-Y4.2 (needs an executor change, which this ticket does not allow): when the lead run finishes, still-running background children are not yet cancelled, awaited (awaitBackgroundOnFinish), or reported (result.backgroundTasks / subagent.cancelled). withSubagents() and the tools never see the run end: AgentExecutor.withExtensions passes only (agent, toolRegistry, subagents, depth), and finishRun/abortRun/savePause call nothing in src/subagents or in the allowed src/execution files. Proposed Y4.2 change, about 10 lines in AgentExecutor: let withSubagents return an onRunEnd(result), call it in a finally around runAgentLoop, and have it cancel children (or await them when awaitBackgroundOnFinish is set) and attach backgroundTasks to the result. Until then, the docs tell users to have the lead agent_await its tasks or to abort the signal they passed.

How verified

  • npx tsc --noEmit: no errors
  • npm run lint: 0 errors, 420 warnings (same count as main)
  • npm run test:types: no type errors
  • npx vitest run (after build): 147 files passed; 2104 tests passed, 3 skipped
  • npm run build && npm run build --workspace=packages/create-loushy-agent: both succeed
  • npm run docs:verify-snippets -- --skip-build: all 103 snippets type-check, 6 also run cleanly
  • npm run docs:llms:check: up to date
  • npm run test:coverage: 2104 passed, 3 skipped. The first run had one failing test that I could not identify. The next 3 full runs passed, and the sub-agent suites passed 5 times in a row.
  • npm run fallow: exit 0, "No issues found" (dead code). The one reported clone group is the existing AnthropicProvider/OpenAIProvider duplication, unchanged by this PR.

Scope: only src/subagents/*, docs/sub-agents.md, CHANGELOG.md and llms-full.txt. No changes to src/execution/*, AgentExecutor.ts, createAgent.ts or package.json.

🤖 Generated with Claude Code

https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR


Generated by Claude Code

claude added 2 commits October 1, 2026 14:37
…nt_status, agent_await and agent_cancel

The task tool takes background: true, which starts the sub-agent and
returns { taskId, status: 'running', agent } at once. Agents with
subagents also get agent_status, agent_await and agent_cancel.
withSubagentOptions(subagents, { maxConcurrent }) bounds running
background children per lead run (default 3); the rest queue. Background
children inherit the lead run's runtime and depth budget, and aborting the
lead cancels them. A child that pauses for approval reports
awaiting-approval with its approvalId.

Cancelling or awaiting background children when the lead run finishes
needs a run-end hook in AgentExecutor (out of scope here): left to
LOU-Y4.2 and documented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants