Skip to content

[FEATURE]: Ephemeral Sub-Agent Teams (parallel multi-agent orchestration) #19999

Closed as not planned

Description

@lleontor705

[FEATURE]: Ephemeral Sub-Agent Teams (parallel multi-agent orchestration)

Feature hasn't been suggested before

This builds on the ideas in #12711 and #19215 but proposes a different approach: ephemeral, scoped teams that are created for a task and destroyed when done — no persistent team state, no new DB tables, no file-based coordination.

Describe the enhancement you want to request

Problem

The task tool spawns sub-agents sequentially — each runs in its own session, returns a result, and that's it. There's no way for sub-agents to:

  1. Run in parallel on independent subtasks
  2. Communicate with each other during execution
  3. Coordinate via a lead agent that assigns work, monitors progress, and merges results

Claude Code's "agent-teams" capability solves this. OpenCode should too.

What's different from #12711 and #19215

Both proposals add persistent team infrastructure (file-based or DB-backed). That's a large surface area with recovery logic, TUI integration, and ongoing state management.

This proposal takes a lighter approach:

Aspect #12711 / #19215 This proposal
Lifecycle Persistent teams that survive restarts Ephemeral — created per-task, auto-cleaned
Storage JSON files / new SQLite tables Existing sessions + in-memory coordination
Recovery Complex reconciliation None needed — if parent dies, children abort
Scope 9+ new tools 1 new tool (team) + 1 coordination module
Communication Cross-session message injection Shared message bus scoped to team lifetime

Proposed design

One new tool: team

z.object({
  description: z.string(),
  tasks: z.array(z.object({
    agent: z.string(),
    prompt: z.string(),
    id: z.string().optional(),    // for dependency references
    depends: z.array(z.string()).optional(),
  })),
  concurrency: z.number().optional(),  // default: all parallel
})

The LLM calls team with a batch of tasks. The tool:

  1. Creates child sessions (like task does today)
  2. Runs them in parallel via Promise.all (respecting depends for ordering)
  3. Pipes results back as a combined output
  4. Cleans up — child sessions remain browsable but the coordination state is gone

Optional: inter-agent messaging

A lightweight Bus-based channel scoped to the team's lifetime. Agents can post messages visible to siblings. This enables patterns like "agent A produces a schema, agent B consumes it" without round-tripping through the lead.

Why ephemeral

  • No new persistence — uses existing Session infrastructure
  • No recovery logic — parent abort signal cascades to children (already works in task.ts)
  • No new TUI — child sessions already show in the session hierarchy
  • Minimal blast radius — opt-in via experimental.team_tool, same pattern as batch_tool

Use cases

  • Parallel file analysis (explore agent per directory)
  • Concurrent implementation + test writing
  • Multi-model review (run same prompt through different providers)
  • Research fan-out (multiple search queries simultaneously)

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 30, 2026
  2. github-actions commented on Mar 30, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    The issue notes differences from #12711 and #19215 specifically, but there is significant overlap with this broader set of issues around parallel/multi-agent orchestration. Please check these to see if your proposal can be consolidated or if it is truly distinct enough to warrant a separate issue.

  3. AndresCdo commented on Mar 31, 2026

    @AndresCdo

    Following up with a non-duplicate Phase 2 proposal that builds directly on #20152 (experimental team tool) while intentionally avoiding the persistent/team-platform scope in #12711 and #19215.

    Current baseline (already in #20152)

    • Ephemeral parallel fan-out/fan-in (team tool)
    • Bounded concurrency + collect-all semantics
    • No shared child state/channel

    Proposed Phase 2: ephemeral mailbox (runtime-only)

    Goal: add in-run inter-agent communication for team children without introducing persistent team entities, new DB tables, or TUI team infrastructure.

    Scope (what this adds)

    1. team gains optional channel id in metadata and creates an in-memory mailbox hub for that invocation.
    2. Add two narrow tools available only to children spawned by team:
      • team_send({ to, message })
      • team_recv({ from?, timeout_ms? })
    3. Child identity is deterministic within one run (task_1, task_2, ... or caller-provided ids) and used for addressing.
    4. Lead/aggregator keeps collect-all behavior unchanged.

    Non-goals (what this does NOT add)

    • No persistent team records
    • No cross-run/cross-session replay
    • No TUI team sidebar/dialog
    • No plan-approval/delegate mode/state machine
    • No hierarchical/nested team platform

    Why this should not duplicate #12711 / #19215

    Behavioral contract

    • Mailbox exists only for the parent team execution lifetime.
    • Messages are best-effort in-memory; parent cancellation destroys mailbox.
    • team_recv can block up to timeout and returns empty if none available.
    • Invalid target ids are explicit tool errors.
    • Permission model remains aligned with existing task/tool permissions; team_send/recv are only exposed in team-child context.

    Safety + verification matrix for implementation

    • Routing: A→B delivery by id
    • Broadcast (optional in phase 2a or 2b)
    • Timeout behavior for team_recv
    • Parent abort cleanup (no leaks)
    • Isolation between concurrent team invocations
    • Collect-all unaffected by messaging failures

    If maintainers agree, I’ll open a focused implementation PR as Phase 2 only (small diff, tests-first), and keep persistent/team-platform concerns out of scope.

  4. m13v commented on Apr 9, 2026

    @m13v

    the ephemeral approach is exactly right. we tried persistent team state early on and the recovery logic alone was more code than the actual orchestration.

    one thing worth adding to the team tool spec: a timeout per task. different tasks have wildly different completion times, and without per-task timeouts, a single stuck agent blocks the entire Promise.all. we use a watchdog that checks for tool activity (not just process liveness) since an agent can be alive but spinning in circles.

    for the inter-agent messaging bus, keep it strictly unidirectional (producer posts, consumers poll). we tried bidirectional agent-to-agent messaging and it immediately degenerated into ACK loops where agents just kept acknowledging each other instead of doing work. the parent collects results, the children never talk to siblings directly.

    the depends array for ordering is clean. one edge case: circular dependencies in the DAG. worth adding a cycle check before dispatch rather than discovering it at runtime when two tasks deadlock waiting on each other.

  5. m13v commented on Apr 9, 2026

    @m13v

    our agent orchestration workflow that handles the ephemeral team pattern with per-task timeouts and context injection between handoffs: https://github.com/m13v/tmux-background-agents/blob/main/SKILL.md

  6. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  7. mguttmann commented on Jun 13, 2026

    @mguttmann

    We built something close to this: a deterministic multi-agent workflow layer (fan-out / pipeline / synthesize across ephemeral sub-agent sessions, with per-agent worktree isolation and an abort cascade) on top of nested sub-agent spawning. Reference implementation in PR #32167, design-review proposal in #32166 — curious whether it overlaps with the ephemeral-teams approach you had in mind.

  8. prassanna-ravishankar commented on Jun 21, 2026

    @prassanna-ravishankar

    @m13v's point about persistent team state being more recovery code than orchestration is the right lesson, and it generalises. the durable bit you actually want isnt a team table, its liveness reconciliation, so a crashed member gets evicted instead of leaving the team wedged.

    i went ephemeral-by-default in repowire for the same reason. peers register on start, and a lazy-repair pass evicts ghosts when a request next needs the registry, so theres no team state to recover and nothing runs on a timer. spawn a peer, it does the task, it falls off the mesh when it dies.

    not native opencode, but the teardown model youre describing (created per-task, destroyed when done, no DB tables) is exactly what fell out of building it, happy to share what worked if useful.

  9. github-actions commented on Aug 20, 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

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