Skip to content

[FEATURE]: Nested sub-agent spawning (up to 5 levels) + multi-agent workflow orchestration — reference implementation, requesting design review #32166

Closed as not planned

Description

@mguttmann

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:

Feature requests it covers:

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/workflow removed on the last level), a runtime guard in the task tool before ctx.ask, and a config-free hard cap (depth 10) in Session.createNext.
  • task_id resume 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

  1. dzianisv commented on Jun 14, 2026

    @dzianisv

    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-ancestor confirms 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:

    • The ctx.agent / parallel / pipeline / setPhase shape matches Claude Code's dynamic-workflows runtime closely, and routing ctx.agent through 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-step schema (structured output), isolation: "worktree", onError, per-step tools/skills/model/variant are all genuinely useful and have no equivalent yet.
    • Strongly agree with your own instinct to split: (1) nested spawning + the four guardrails + ask-routing-to-root (Nested Subagent Fails Silently in 3-Layer Deep Chain (Works Fine in 2-Layer) #23091/Permission asks from nested subagent sessions silently hang #13715 fixes) is small, high-value, and reviewable on its own; (2) the workflow subsystem (~most of the 55k LoC) as a separate PR. Landing (1) first de-risks the whole thing and the bugfixes are wanted regardless of whether the orchestration layer is accepted.
    • One concern worth flagging for review: 55k LoC with generated SDK/openapi churn (types.gen.ts alone 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 (tip de9aa9c8) 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 latest dev. (I couldn't run bun turbo typecheck locally — 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.

  2. mguttmann commented on Jun 14, 2026

    @mguttmann
    Author

    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:

    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.

  3. mguttmann commented on Jun 14, 2026

    @mguttmann
    Author

    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.

  4. mguttmann commented on Jun 15, 2026

    @mguttmann
    Author

    @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:

    Per 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.

  5. dzianisv commented on Jun 19, 2026

    @dzianisv

    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.
    • Claude Code "bare-globals" format is supported directly — workflow files use injected globals (agent(), parallel(), pipeline(), phase(), log(), args) with no boilerplate, alongside the native workflow({...}) form. Files written for Claude Code's hidden workflows feature run unmodified.
    • Sub-agents run in isolated sessions (clean main chat), with structured output via a JSON schema option (model is forced to return validated JSON).
    • Deterministic orchestration in plain JS: loops, branching, parallel() fan-out, and pipeline() (per-item staging, no barrier).
    • Bare model IDs resolve across providers (e.g. claude-sonnet-4 → the provider's versioned claude-sonnet-4.6), and the resolved model is threaded through to the sub-agent call.
    • Skill-catalog pre-injection: when a prompt references a skills directory, the runner injects SKILL.md content + 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.

  6. mguttmann commented on Jun 23, 2026

    @mguttmann
    Author

    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.

  7. github-actions commented on Aug 23, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions