openai / openai/codex

First-class bounded batch fan-out for heterogeneous subagents

Open
#39,129 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app enhancement subagent
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What variant of Codex are you using?

Codex App primarily. The orchestration primitive would ideally be shared with CLI/tool-backed Codex surfaces.

What feature would you like to see?

Summary

Codex now has most of the pieces needed for heterogeneous multi-agent work: subagents, per-agent model configuration, async orchestration, and configurable concurrency.

The missing primitive is bounded batch fan-out.

A coordinator should be able to submit a large set of independent tasks in one operation, have Codex schedule them across cheaper/faster worker agents with explicit limits, then collect bounded results for synthesis.

The motivating shape is:

                strong coordinator
                       |
             decompose / schedule
                       |
         +-------------+-------------+
         |             |             |
      fast worker   fast worker   fast worker
         |             |             |
         +-------------+-------------+
                       |
                  coordinator
                     reduce

For example: a Sol coordinator analyzing a large multi-repository system could dispatch 80 independent repository audits to Spark workers, run at most 32 concurrently, then synthesize their findings.

This should not require the coordinator to make 80 individual spawn_agent calls and manually manage 80 wait_agent lifecycles.

Problem

spawn_agent is a good primitive for small, adaptive teams where the parent decides what to delegate one task at a time.

It is a poor primitive for workloads where the complete work set is already known:

  • inspect every package in a monorepo;
  • review 100 independent files/modules;
  • run the same migration audit across many services;
  • investigate one question independently against many repositories;
  • generate bounded implementation/review tasks from an already-computed plan.

In these cases, repeated parent-side spawn/wait decisions add orchestration turns and context churn without adding useful reasoning.

Simply increasing agents.max_threads does not solve that. Batch size and concurrency are different things.

I may want to submit 200 tasks while allowing only 16 or 32 workers to execute concurrently.

Proposed shape

The exact API is not important, but conceptually something like:

batch = spawn_batch(
    worker_profile = "fast_worker",
    tasks = [...],
    concurrency = 32,
    max_tokens_per_worker = 20000,
    total_budget = ...,
    max_result_size = ...,
    recursive_spawn = false,
)

results = wait_batch(batch)

tasks could contain independent prompts plus optional scoped context/path information.

spawn_batch should create one schedulable batch, not require the model to emit N individual spawn calls.

Important semantics

Batch size != concurrency

A batch may contain 200 tasks while the scheduler runs only 16 concurrently.

Excess work should queue rather than requiring the parent model to manage free slots.

Heterogeneous workers

The worker model/profile should be selectable independently from the coordinator.

A common configuration would be:

coordinator: expensive/high-reasoning model
workers:     fast/cheap model
reviewer:    optional stronger model

This is where models such as Spark are particularly useful: not necessarily as the coordinator, but as high-throughput bounded workers.

Explicit budgets

Large fan-out needs guardrails, not just a higher thread limit.

Useful controls would include:

  • maximum batch size;
  • maximum active workers;
  • model/profile allowlist;
  • per-worker token or credit budget;
  • aggregate batch budget;
  • timeout;
  • sandbox/tool permissions;
  • maximum result size;
  • maximum subagent depth;
  • queue vs fail behavior when capacity is exhausted.

A parent should be able to say “up to 32 Spark workers, 20k tokens each, read-only, depth 1” rather than implicitly creating an uncontrolled swarm.

Bounded result aggregation

The coordinator usually does not need the complete transcript of every worker.

By default, batch completion should return something closer to:

task id
status
final worker result
usage
optional artifact references

rather than injecting every worker's full interaction history into the parent context.

This matters once fan-out becomes large.

Partial failure

wait_batch should preserve successful results when some tasks fail, time out, or are cancelled.

It should be possible to retry selected task IDs without rerunning the whole batch.

Cancellation and observability

A batch should have an ID and expose:

queued
running
succeeded
failed
cancelled
token/credit usage

The user should be able to cancel the batch or individual tasks.

Why make this a first-class primitive?

A sufficiently capable coordinator can approximate this today with repeated spawn_agent calls.

But that pushes deterministic scheduler work back into model reasoning:

find free slot
spawn worker
remember worker id
wait
inspect completion
spawn next
repeat

None of those steps requires a frontier reasoning model.

A runtime-level batch primitive could handle queueing, limits, cancellation and result collection deterministically while leaving the coordinator responsible for the parts that actually require reasoning:

decomposition
task specification
dependency identification
final synthesis

This also makes very large fan-out safer. The runtime can enforce hard budgets even if the coordinator attempts to over-spawn.

Concrete example

Consider an architecture audit over 80 repositories.

The coordinator first determines that each repository can be inspected independently.

Desired execution:

Sol:
  build 80 bounded audit tasks
       |
       v
spawn_batch:
  worker = Spark
  tasks = 80
  concurrency = 24
  read-only
  depth = 1
       |
       v
scheduler:
  24 running
  56 queued
       |
       v
80 bounded reports
       |
       v
Sol:
  cross-repo synthesis
  contradictions
  architecture decision

The expensive coordinator is used where its reasoning matters. The fast workers provide breadth.

Acceptance criteria

  • A coordinator can submit N independent subagent tasks in one tool/runtime operation.
  • Batch size may exceed active concurrency.
  • Queued work starts automatically as worker capacity becomes available.
  • Worker model/profile may differ from the coordinator.
  • Per-worker and aggregate budgets are enforceable by the runtime.
  • Worker recursion/depth can be disabled or bounded.
  • Batch status, usage, cancellation and partial failures are observable.
  • Results can be collected without importing full worker transcripts into parent context by default.
  • Individual failed tasks can be retried without rerunning successful tasks.
  • Existing spawn_agent remains available for adaptive one-off delegation.

This is intended to complement, not replace, normal subagents and agent teams.

Additional information

Related requests

I searched the existing Codex issues before filing this.

  • https://github.com/openai/codex/issues/14039 — per-subagent model/provider/profile selection. This covers which model a worker uses; it does not provide batch dispatch/scheduling.
  • https://github.com/openai/codex/issues/11701 — subagent configuration and orchestration, including strong planner + Spark/execution workers. This establishes the heterogeneous-agent use case; it does not provide a first-class large fan-out primitive.
  • https://github.com/openai/codex/issues/16183 — higher/configurable subagent spawning limits and queueing. Raising the ceiling helps, but still leaves N individual spawn/wait operations to the coordinator.
  • https://github.com/openai/codex/issues/33437 — project-scoped agent/model concurrency quotas. This would compose very well with batch fan-out: the policy defines what may run, while the batch primitive defines how a known work set is submitted and collected.
  • https://github.com/openai/codex/issues/12047 — teams, hierarchical orchestration and async agent messaging. Teams are useful for persistent/adaptive collaboration; this request is specifically for data-parallel bounded work with a known task set.

Two current reports also show why explicit runtime scheduling and budgets matter:

I am not asking for an unlimited subagent count.

I am asking for a bounded map/fan-out primitive where the runtime, rather than the coordinator model, handles queueing, concurrency, budgets and result collection.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No implementation files, tests, or entry points are named. Start by locating the existing subagent spawn/wait runtime and its concurrency and configuration paths, then compare them with the acceptance criteria for queueing, budgets, status, cancellation, partial failure, and bounded results.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
ai, devtools, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.