Skip to content

Codex multi-agent workflows: parallel lanes, subagents and cloud fan-out

A Codex multi-agent workflow splits one body of work into lanes that share no files, runs one Codex agent per lane in its own Git worktree or cloud container, and merges the lanes in dependency order after each passes its own gate. Parallel lanes pay off only when shared contracts land first and every lane is verified independently.

Your epic has five subtasks: a migration, an API, a service change, a settings page and end-to-end tests. You can run five Codex sessions at once, but the last time you tried, two of them rewrote the same barrel file, a third invented its own response shape, and you spent the afternoon untangling merges. This page is for the developer who runs the agents and the tech lead who decides how many run at once and what “done” means for each.

What you get from a Codex multi-agent setup

Section titled “What you get from a Codex multi-agent setup”
  • A rule for what runs in parallel, what runs first and what must stay serial.
  • Four copy-paste prompts: decomposition, foundation, lane worker and cross-lane conflict resolution.
  • A fan-out script that starts one codex exec agent per Git worktree, and a lane gate that rejects work outside its lane before you read it.
  • config.toml settings that cap subagent concurrency and cost.
  • A merge order and an integration check that prove the combined result works.

Commands and config keys on this page were checked against codex 0.157.1 (--help and the rust-v0.157.1 source) on 2026-09-26.

Which Codex surface runs which kind of parallel work?

Section titled “Which Codex surface runs which kind of parallel work?”

Codex gives you four ways to run agents side by side. They differ in what they isolate, and isolation decides what can safely run in parallel.

SurfaceStart it withIsolationUse it for
Subagents in one sessionAsk for them in the prompt; switch with /subagentsOne session; you control concurrency with [agents] in config.tomlRead-heavy fan-out: exploring a codebase, reviewing a diff from several angles
Managed worktree sessionscodex --worktree, or /worktree inside a sessionA new managed Git worktree per sessionInteractive lanes you want to watch and steer
Scripted codex execgit worktree add, then codex exec -C <dir>A worktree and branch you name yourselfRepeatable fan-out from a script, with logs you keep
Cloud taskscodex cloud exec --env ENV_IDA cloud container per task; up to four attempts eachLong lanes, heavy builds, and best-of-N on a hard lane

The Codex desktop app (codex app, macOS and Windows) runs the same worktree pattern with one thread per lane. Neowin reported (secondary, 2026-07-09) that it now ships as a Codex mode of the ChatGPT desktop app. For worktree setup and cleanup on every surface, see isolated Codex tasks with Git worktrees.

When should you run Codex agents in parallel, and when serially?

Section titled “When should you run Codex agents in parallel, and when serially?”

Parallelize a piece of work only when all three conditions hold:

  • It owns its files. No other lane creates or edits the same paths.
  • It depends on nothing another lane is still writing. Its inputs are already on the base branch.
  • It can prove itself alone. It has its own tests, and type check and lint pass on its branch without the other lanes.

Serialize everything else: database migrations, shared types and interfaces, route or schema registration in barrel files, and any step where you need to make a judgment call before the next one starts.

Most feature sets have the same shape. A thin foundation (migration, shared interfaces, registration lines) blocks everything, then three to five lanes run in parallel, then an integration phase runs once after every merge. Conflicts almost always come from skipping the foundation: two agents each add “one line” to src/routes/index.ts, or each invent their own EventPayload.

The walk-through uses a notification-preferences feature: users choose email, SMS or push per notification type. The same steps work for a quarter’s worth of independent features; only the lane list gets longer.

  1. Decompose the work and write the plan to a file. Run the planning prompt below in a normal Codex session on your base branch. Review the plan, not the code: the file-ownership table and the contracts are where parallel work succeeds or fails. Commit docs/plan/notification-prefs.md, because every lane prompt points to it.

  2. Land the foundation serially. Run the foundation prompt in one session on a feature branch, for example feature/notification-prefs. When its tests pass, commit it. Every lane now starts from a branch that already has the table, the shared types and the registration lines, so no lane needs to touch a shared file.

  3. Launch one agent per lane. For two or three lanes you want to watch, open a terminal per lane and run codex --worktree from the feature branch, then paste the lane prompt. For more lanes, or a run you want to repeat, use the fan-out script in the next section.

  4. Monitor and steer without joining every conversation. codex agents (or /agents in a session) opens the agent command center, where you can search, open, rename and stop sessions. Rename each session after its lane there. To redirect a lane without switching to it, queue a message by session name: codex queue --thread prefs-api --message "Use the NotificationPreference type from src/types/notifications.ts; do not define a new one." When one lane needs to know what another decided, @-mention that task in the prompt instead of pasting its output. Check /usage before you launch another batch.

  5. Gate each lane on its own. Run the lane gate below on every branch as it finishes. A managed codex --worktree session leaves its changes uncommitted in a worktree that Codex names, so commit the lane’s work there first and pass that worktree’s path (from git worktree list) as the gate’s fourth argument. A lane that fails its gate goes back to its agent with the gate output; you do not read its diff yet.

  6. Merge in dependency order, then run integration. Merge the lane with the fewest shared touch points first, and the end-to-end tests lane last. After the last merge, run the full suite once on the feature branch. Only then open the pull request and request @codex review on it, alongside your team’s reviewers.

Fan out lanes from a script with codex exec

Section titled “Fan out lanes from a script with codex exec”

The script creates one worktree and branch per lane from the current branch, installs dependencies outside the sandbox, runs one non-interactive agent per lane in parallel, and commits each lane’s result so the gate has a clean branch to check. Run it from the repository root on the branch that holds the foundation commit, with one prompt file per lane in prompts/. The script stops if a lane’s branch or worktree already exists, so before a rerun remove the previous ones (the “Old worktrees pile up” row in When parallel Codex agents break); that discards any lane work you have not merged.

#!/usr/bin/env bash
# fan-out.sh: one codex exec agent per lane, each in its own worktree
set -euo pipefail
BASE=$(git rev-parse --abbrev-ref HEAD)
RUNS="$PWD/.codex-runs"
mkdir -p "$RUNS"
pids=(); lanes=()
for lane in api service ui; do
wt="../wt-prefs-$lane"
git worktree add -b "feat/prefs-$lane" "$wt" "$BASE"
(cd "$wt" && npm ci --silent) # installs need the network the sandbox withholds
codex exec -C "$wt" \
-c default_permissions=":workspace" \
--json -o "$RUNS/$lane.md" \
"$(cat "prompts/prefs-$lane.md")" < /dev/null > "$RUNS/$lane.jsonl" &
pids+=("$!"); lanes+=("$lane")
done
failed=0
for i in "${!pids[@]}"; do
wait "${pids[$i]}" || { echo "FAIL ${lanes[$i]}: codex exec exited non-zero"; failed=1; }
done
[ "$failed" -eq 0 ] || exit 1
for lane in api service ui; do
git -C "../wt-prefs-$lane" add -A
git -C "../wt-prefs-$lane" commit -m "prefs: $lane lane (codex exec)" || echo "$lane: nothing to commit"
done

Three choices in the script are deliberate. -c default_permissions=":workspace" selects the built-in workspace permission profile, which OpenAI prefers over the legacy --sandbox flag; profiles are beta (Codex CLI 0.138.0 and later), so pin your CLI version in scripts. npm ci installs from the lockfile, so five lanes cannot resolve five different dependency trees. The script, not the agent, commits, so the result does not depend on whether the agent’s sandbox can write to the repository’s shared .git directory. .codex-runs/ holds each lane’s final message and JSONL event log; add it to .gitignore. Two guards keep a bad lane from reaching a commit: the script waits on each lane’s process ID and stops if any codex exec exited non-zero (a bare wait returns 0 regardless), and < /dev/null matters because codex exec appends piped stdin to the prompt, so a script run from CI or bash < file would otherwise feed stray input to every agent.

Write the service and UI lane prompts the same way: the lane’s name, its editable files, the contract it imports, and a definition of done with commands. A lane prompt that omits “edit only” invites the agent to fix whatever it notices on the way, and that is where cross-lane conflicts come from.

How do you prove each lane without reading every diff?

Section titled “How do you prove each lane without reading every diff?”

Put machine checks in front of your attention, in this order. Each layer is cheaper than the one after it, so a lane reaches a human only after the cheap checks pass.

LayerWhat it catchesHow
Lane boundaryThe agent edited files outside its lanegit diff --name-only against the lane’s allowed paths
Lane tests and static checksBroken behaviour inside the laneThe lane’s own tests, type check and lint on its branch
Reviewer agentContract drift, missing tests, logic errorsA codex exec run under the :read-only permission profile, with the plan as the rubric
Contract tests at the seamsLanes that each pass but disagreeTests that import the shared types from both sides, written in the foundation
Integration runInteractions: shared test state, ports, orderingThe full suite once, after the last merge
Human sign-offWrong plan, wrong contract, risky filesYou approve the plan and contracts before launch, and read diffs only in files your plan marks as risky (auth, payments, migrations)

The lane gate automates the first three layers. Run it from the repository root once per finished lane:

#!/usr/bin/env bash
# lane-gate.sh LANE ALLOWED_PATHS_REGEX [BASE] [WORKTREE]
# example: ./lane-gate.sh api '^(src/routes/notifications/|src/services/notifications/api|tests/.*notification)'
set -euo pipefail
lane="$1"; allowed="$2"; base="${3:-feature/notification-prefs}"; wt="${4:-../wt-prefs-$lane}"
runs="$PWD/.codex-runs"
cd "$wt"
test -z "$(git status --porcelain)" || { echo "FAIL $lane: uncommitted changes"; exit 1; }
stray=$(git diff --name-only "$base"...HEAD | grep -v -E "$allowed" || true)
if [ -n "$stray" ]; then echo "FAIL $lane: files outside the lane:"; echo "$stray"; exit 1; fi
npm run typecheck
npm run lint
npm test
codex exec -c default_permissions=":read-only" -o "$runs/$lane-review.md" \
"Review git diff $base...HEAD against docs/plan/notification-prefs.md. Report only correctness bugs, contract drift from src/types/notifications.ts, and behaviour without a test. Give file and line for each finding. If there are none, reply with exactly NO FINDINGS on its own line." < /dev/null
[ "$(tr -d '[:space:]' < "$runs/$lane-review.md")" = 'NOFINDINGS' ] || { echo "FAIL $lane: review findings in $runs/$lane-review.md"; exit 1; }
echo "PASS $lane"

The review step is a plain codex exec run rather than codex exec review, because codex exec review --base rejects a custom prompt: --base and a custom prompt are mutually exclusive (checked in codex 0.157.1), so it cannot take the plan as its rubric. If you prefer codex exec review --base "$base", run it without a prompt and put the rubric in the review guidelines of AGENTS.md. The gate fails unless the review file holds nothing but NO FINDINGS (whitespace aside), so a review that lists findings and also writes that line still fails; when it fails, read the findings and send them back to the lane’s agent, or overrule a false positive yourself. Each check sits on its own line because under set -e a failure in any command before the last && of a chain does not stop the script, so a failing type check would still print PASS.

A lane that fails the boundary check goes back to its agent, or you move the stray file into the foundation and re-plan. Do not merge the lane and fix the overlap by hand: that is how the next lane’s conflict starts. For the review side of this at team scale, see Codex review strategies and running the review queue when agents open the pull requests.

Fan out inside one session with Codex subagents

Section titled “Fan out inside one session with Codex subagents”

Subagents are on by default (multi_agent is stable in 0.157.1). The session’s agent spawns them when your prompt asks for parallel work, and /subagents switches between them. They suit questions more than edits: several readers covering one codebase, or several reviewers covering one diff. Keep lanes that write files in separate worktrees, where Git isolates them.

Cap them in ~/.codex/config.toml. Every key below is in the 0.157.1 config schema:

[agents]
max_threads = 4 # alias of max_concurrent_threads_per_session
default_subagent_reasoning_effort = "medium" # used when the spawn call sets none
# default_subagent_model = "gpt-6-sol" # only after your own evals favour it
[agents.reviewer]
description = "Read-only reviewer. Reports findings with file and line; never edits files."
config_file = "./agents/reviewer.toml" # a config layer, relative to this file
[goals]
max_goal_token_budget = 2000000 # nested subagent tokens count toward it

Leave default_subagent_model unset until you have a reason. Codex runs GPT-6 Astra by default, and the site’s rule is to tune effort before switching model; the models hub lists the current Codex models and prices. Since 0.151.0, tokens spent by nested subagents count toward a /goal budget, so a goal budget also caps a fan-out.

A lane that needs a heavy build, runs for a long time, or has several plausible designs fits a cloud task better than a laptop worktree. Push the foundation branch first: codex cloud exec runs on your current branch unless you pass --branch (checked in codex cloud exec --help, 0.157.1), and the container clones from your remote.

Terminal window
# run in your terminal, inside the repository
git push -u origin feature/notification-prefs
codex cloud exec --env ENV_ID --branch feature/notification-prefs --attempts 2 - < prompts/prefs-service.md
codex cloud list --env ENV_ID # watch progress
codex cloud diff TASK_ID --attempt 2 # compare attempts
# apply the chosen attempt inside the lane's own worktree, commit it, then gate it
git worktree add -b feat/prefs-service ../wt-prefs-service feature/notification-prefs
(cd ../wt-prefs-service && codex cloud apply TASK_ID --attempt 2 \
&& git add -A && git commit -m "prefs: service lane (cloud)")
./lane-gate.sh service "$SERVICE_PATHS" # the service lane's allowed-paths regex

ENV_ID is your cloud environment’s ID or label, and TASK_ID is the ID or URL that codex cloud exec prints. codex cloud apply writes the diff into the checkout you run it in, so run it inside the lane’s worktree and commit before the gate, which refuses uncommitted changes. That way a cloud lane goes through the same lane gate as a local one. Drop a lane you send to the cloud from the for lane in list in fan-out.sh, or the two would claim the same worktree. Environment setup, internet access and when best-of-N is worth paying for are covered in Codex cloud environments.

How many Codex agents should you run at once?

Section titled “How many Codex agents should you run at once?”

Set the number by review capacity, not by what your machine or plan allows. Faros AI’s “AI Engineering Report 2026” (April 2026, telemetry from 22,000 developers) reported task throughput per developer up 33.7%, while median time in review rose 441.5% and incidents per pull request rose 242.7%. More generation without more verification moves the queue to review and the cost to production.

Practical limits that follow from that:

  • Start with three lanes. Add a fourth only when the lane gates of the first three pass without rework. Treat five lanes per developer as a ceiling you have to justify, not a target.
  • One owner per merge. Whoever wrote the plan merges the lanes, because merge order depends on the plan.
  • Budget before launch. Check /usage in a session before starting a batch, set max_threads for subagents, and set a /goal budget on long lanes. Plan allowances and their five-hour and weekly windows are covered in Codex cost management.
SymptomCauseRecovery
Conflicts in src/routes/index.ts or another barrel fileSeveral lanes registered themselvesMove registration into the foundation with stubs, as in the foundation prompt. For a merge already in conflict, use the prompt below
Lanes pass alone and fail togetherShared test state, fixed ports, or two lanes seeding the same tableAdd the missing contract test to the foundation, isolate test data per suite, then rerun integration
Two lanes disagree on a response shapeThe contract was left to the agentsPut the shape in src/types/notifications.ts in the foundation; queue a message to both lanes pointing at it
The lane gate reports files outside the laneThe prompt lacked “edit only”, or the plan missed a shared fileSend the gate output back to the agent, or move the file into the foundation and re-plan
A cloud lane is missing the foundationThe branch was not pushed, or --branch pointed elsewherePush the foundation branch and resubmit with --branch
npm ci or builds exhaust the laptopFive worktrees installing and testing at onceStagger launches, or move the heaviest lanes to cloud tasks
A lane stalls or loopsUnclear definition of done, or a full context windowStop it from codex agents, tighten the definition of done in the lane prompt, and start a fresh session in the same worktree
Old worktrees pile upEvery lane leaves a worktree and a branchAfter merging, git worktree remove ../wt-prefs-api, git branch -d feat/prefs-api, then git worktree prune

Where to go next with multi-agent Codex work

Section titled “Where to go next with multi-agent Codex work”