Repository navigation
[FEATURE]: Nested sub-agent spawning (up to 5 levels) + multi-agent workflow orchestration — reference implementation, requesting design review #32166
Description
What this is
We've been running a fork that adds nested sub-agent spawning (a session tree up to 5 levels deep) plus a multi-agent workflow/orchestration layer on top of it, and a round of hardening. It's implemented, tested, and we use it daily.
Per CONTRIBUTING.md ("any core product feature must go through a design review with the core team before implementation"), I'm opening this before sending a PR: I'd like to know whether the team wants any of this upstream, and in what shape (one PR, or split per area). The branch is ready and I'm happy to adapt, split, or drop pieces.
Open issues this addresses
Bugs it fixes:
- Nested Subagent Fails Silently in 3-Layer Deep Chain (Works Fine in 2-Layer) #23091 — nested subagent fails silently at depth 3 (works at depth 2)
- Permission asks from nested subagent sessions silently hang #13715 — permission asks from nested subagent sessions silently hang
Feature requests it covers:
- Sub-agent nesting enabled #30899 — knowing the progress of nested sub-agents
- [FEATURE]: Ephemeral Sub-Agent Teams (parallel multi-agent orchestration) #19999 — ephemeral sub-agent teams / parallel multi-agent orchestration
- [FEATURE]:Support for multi-agent orchestration in isolated workspaces #17994 — multi-agent orchestration in isolated workspaces
- [FEATURE]: Display subagent status in TUI prompt footer #23784 — display subagent status in the TUI footer
- [FEATURE]: Task tool should support
modelparameter for cost-optimized multi-agent orchestration #26925 —tasktoolmodelparameter
What it adds
1. Nested sub-agent spawning (depth ≤ 5)
A subagent can spawn its own subagents. Depth is derived from the parentID chain (Session.lineage) — no schema change required. Guardrails:
- Four independent limits: permission-deny at the limit, a resolve-time tool filter (
task/workflowremoved on the last level), a runtime guard in the task tool beforectx.ask, and a config-free hard cap (depth 10) inSession.createNext. task_idresume restricted to direct children (this closes the silent-hang/deadlock class), per-tree lifetime cap, permission asks routed to the root session of the tree with origin metadata (fixes Permission asks from nested subagent sessions silently hang #13715), abort/cancel cascade across the whole tree, TurnBudget shared by reference across levels.- One config knob:
experimental.subagent_max_depth(default 5;2= previous behavior,1= kill switch).
2. Multi-agent workflow orchestration
A deterministic workflow layer (the larger, more opinionated piece) that lets an agent fan out, pipeline, and synthesize work across many sub-agents, with ctx.question / ctx.shell / nested ctx.workflow, event streaming, a run dashboard in TUI/desktop, headless (opencode run --workflow), worktree isolation, an approval gate, and a save endpoint. This is what answers #19999 / #17994.
3. Hardening & UX follow-ups
Per-session fail-fast concurrency cap (no tree-wide semaphore, so no deadlock), experimental.subagent_tree_limit, optional depth/rootID wire fields, a TUI tree view with depth badges and "asked by @agent (depth N)" (#30899 / #23784), per-task timeout, and a display-only subtree cost rollup.
Status
Implemented on a branch off current dev. bun turbo typecheck 23/23; the nested/workflow/server suites pass (≈280 focused, full suite green earlier); docs updated. It's a large branch (~55k LoC, the workflow subsystem being most of it), so I fully expect you may want it split into focused PRs — e.g. nested spawning alone first, workflow layer separately — or may not want the workflow piece at all. Happy to do whatever fits your roadmap.
Question: is nested spawning (and optionally the orchestration layer) something you'd accept, and how would you like it scoped? I'll open the PR(s) accordingly.
Activity
dzianisv commentedon Jun 14, 2026
Did a focused review of this against the other in-flight workflows effort (#29059 / PR #29789) since they overlap heavily.
Finding: these two PRs are not independent — #32167 is a genealogical superset of #29789.
git merge-base --is-ancestorconfirms VasyaYovbak's PR #29789 is fully in the history of this branch; the identical migration timestamps (20260531160000_workflow-runs,…directory,…paused_resume) are the giveaway. So the 80-file overlap isn't two teams duplicating work — it's the workflow subsystem from #29789 plus this PR's nested-spawning + p2 hardening layered on top. Of the shared files, 28 are byte-identical and 52 are this branch's evolution of them.Net: there is no 3-way reconciliation to do. The orchestration core is one lineage; the only real question is scope of what lands upstream, which is exactly what you asked.
Design-review take:
ctx.agent/parallel/pipeline/setPhaseshape matches Claude Code's dynamic-workflows runtime closely, and routingctx.agentthrough real opencode sessions/subagents (so each step is inspectable in the existing tool-call UI) is the right call — better than CC's opaque runtime. The per-stepschema(structured output),isolation: "worktree",onError, per-steptools/skills/model/variantare all genuinely useful and have no equivalent yet.types.gen.tsalone is ~12k of the diff) makes review hard — separating generated artifacts from hand-written code in the split would help a lot.Consolidation branch: I rebased this onto current
dev(tipde9aa9c8) to confirm it still applies — merges clean, zero conflicts: https://github.com/dzianisv/opencode/tree/feat/workflows-consolidated . Since #32167 already contains #29789, that branch is effectively the unified work refreshed on latestdev. (I couldn't runbun turbo typechecklocally — disk-space limit on my box, not a code issue — but the merge is conflict-free and you reported 23/23 + ~280 tests green.)Happy to help with the nested-spawning-first split if that's the direction.
mguttmann commentedon Jun 14, 2026
Thanks @dzianisv — that's a really helpful review, and your read of the lineage is exactly right: this branch is #29789 plus the nested-spawning + p2 hardening on top, one history, no 3-way merge.
Fully agree with the split, and it's already in motion:
dev, independent of whether the orchestration layer lands. Agreed this is the high-value, reviewable piece and the bugfixes are wanted regardless.Good call on the generated churn too — I'll keep
types.gen.ts/openapi.json/ sdk regen out of the hand-written diff (separate commit, or regenerated on request) so the reviewable surface is just the engine + session changes.Thanks for the offer to help with the nested-first split — I'll scope it down and ping you here when the focused branch is up. Appreciate you taking the time to trace it.
mguttmann commentedon Jun 14, 2026
The focused nested-spawning branch is up: #32301. Split exactly as you suggested, @dzianisv — workflow subsystem excluded (zero
packages/opencode/src/workflow/**in the diff), generated artifacts isolated in their own commit, and it carries the #23091 / #13715 fixes. The orchestration layer stays on its own track via #29789. Would appreciate your eyes when you have a moment.mguttmann commentedon Jun 15, 2026
@dzianisv thanks for the thorough review — and agreed on all of it. I've acted on both of your recommendations:
(1) Nested-spawning first is up as #32301 — the #23091/#13715 fixes (ask-routing-to-root) plus the four guardrails, small and reviewable on its own, green CI, mergeable. Exactly the "land this first, it's wanted regardless" piece.
(2) The workflow subsystem is now a stacked split into focused, independently-reviewable PRs:
workflow.tsmodularized into schema/errors/types + barrel)ctx.tool(...)+ plugin registrationPer your note about generated churn, the regenerated SDK/openapi is isolated in #32392 rather than spread across the diff; each PR is workflow-only (unrelated drift dropped). They stack 1→6, so reviewing/merging in order gives clean increments (each description links the per-layer compare for the incremental view).
I'd gladly take you up on the offer to help land the nested-first split — what's the best path from here? Happy to adjust the slicing or the base ordering to whatever's easiest for you to review/merge.
dzianisv commentedon Jun 19, 2026
For anyone tracking this: we shipped a working implementation of Claude Code-style dynamic workflows in our fork.
Commit: dzianisv@2073487
What works (end-to-end, against a real provider):
/workflow <path-to-file.js>slash command runs project-local JS workflows.agent(),parallel(),pipeline(),phase(),log(),args) with no boilerplate, alongside the nativeworkflow({...})form. Files written for Claude Code's hidden workflows feature run unmodified.schemaoption (model is forced to return validated JSON).parallel()fan-out, andpipeline()(per-item staging, no barrier).claude-sonnet-4→ the provider's versionedclaude-sonnet-4.6), and the resolved model is threaded through to the sub-agent call.SKILL.mdcontent + a per-dir catalog so the manager agent can plan over locally-discovered skills.13 files, includes test coverage (
bare-globals.test.ts,workflow-command.test.ts, plus tool/schema tests). Verified E2E: a 6-phase research workflow and isolation tests run to completion against GitHub Copilot-served Claude models.Happy to open a PR upstream or split it into reviewable chunks if there's interest.
mguttmann commentedon Jun 23, 2026
Update: the reference implementation is now in reviewable shape.
@VasyaYovbak's full version (#29789) came in as one ~40k-line PR, so I rebased it onto current dev and split it into six PRs that each do one thing:
They're a stack, but each one is small enough to read on its own, and all six are green and mergeable against current dev right now. I'll keep them rebased.
#32301 is the standalone nested-sub-agent piece (fixes #23091 and #13715) and doesn't depend on the workflow stack.
@dzianisv also has a workflow implementation in his fork — if you'd rather have one upstream version, I can reconcile the two.
@thdxr / @kitlangton — is this something you'd want upstream? If so, it's ready to review and I'll keep it current; if the design should change first, let me know.
github-actions commentedon Aug 23, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.