All articles
agentic systems · intermediate ·

A field guide to multi-agent code review with custom subagents

How to split code review across parallel subagents in Codex — defining TOML-based custom agents, wiring sandbox policies, and composing a review pipeline that catches what a single agent misses.

code-reviewcodexcoding-agentspatternssubagents

A single agent reviewing code it helped write is a known weakness. The agent carries the history of how the code was built — every tradeoff, every assumption, every “good enough for now” decision. It reviews with the same blind spots it had during implementation.

Codex’s subagent system offers a way out: split review across multiple agents, each with a narrow brief, a clean context window, and no memory of how the code came to be. One agent maps the codebase. Another finds risks. A third verifies external APIs. They run in parallel, return structured results, and the main thread synthesizes.

This post walks through standing up that pipeline from scratch.

The architecture

The pattern uses three custom agents, each defined as a standalone TOML file under .codex/agents/:

Three-agent review pipeline
AgentRoleModelSandbox
pr_explorerMaps affected code paths, traces executiongpt-5.3-codex-sparkread-only
reviewerFinds correctness, security, and test gapsgpt-5.4read-only
docs_researcherVerifies framework APIs via MCPgpt-5.4-miniread-only

Each agent gets a clean context window. None of them know what the others are doing. None of them participated in writing the code. That isolation is the point.

Step 1: Project-level configuration

Start with the global subagent settings in .codex/config.toml:

.codex/config.toml toml
[agents]
max_threads = 6
max_depth = 1

max_threads = 6 lets all three review agents run concurrently with room for follow-up work. max_depth = 1 keeps the topology flat — review agents can spawn one level deep but no further. This prevents accidental fan-out when an agent decides to delegate sub-tasks on its own.

Step 2: The explorer agent

The explorer’s job is narrow: read the codebase, trace execution paths, and report findings. It never proposes fixes. It never edits files.

.codex/agents/pr-explorer.toml toml
name = "pr_explorer"
description = "Read-only codebase explorer for gathering evidence before changes are proposed."
model = "gpt-5.3-codex-spark"
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
developer_instructions = """
Stay in exploration mode.
Trace the real execution path, cite files and symbols, and avoid proposing fixes
unless the parent agent asks for them.
Prefer fast search and targeted file reads over broad scans.
"""

The key choices here:

  • gpt-5.3-codex-spark — fast enough for exploration, cheaper than the reviewer’s model. Exploration is high-volume, low-judgment work.
  • read-only sandbox — the explorer cannot modify files even if it wanted to. This is defense in depth: even if the model hallucinates an edit instruction, the sandbox blocks it.
  • Instructions that create a stopping point — “cite files and symbols” forces concrete output. Without it, explorers tend to keep reading files indefinitely.

Step 3: The reviewer agent

The reviewer is where judgment lives. It gets the most capable model and the most specific instructions:

.codex/agents/reviewer.toml toml
name = "reviewer"
description = "PR reviewer focused on correctness, security, and missing tests."
model = "gpt-5.4"
model_reasoning_effort = "high"
sandbox_mode = "read-only"
developer_instructions = """
Review code like an owner.
Prioritize correctness, security, behavior regressions, and missing test coverage.
Lead with concrete findings, include reproduction steps when possible, and avoid
style-only comments unless they hide a real bug.
"""

The reviewer gets model_reasoning_effort = "high" because review is the highest-stakes step. A false negative here (missing a real bug) is worse than a false positive from the explorer. The sandbox stays read-only because review should never edit — it produces findings, not patches.

Step 4: The docs researcher

This agent is optional but high-leverage. It checks whether the code’s assumptions about external APIs are actually correct:

.codex/agents/docs-researcher.toml toml
name = "docs_researcher"
description = "Documentation specialist that uses the docs MCP server to verify APIs and framework behavior."
model = "gpt-5.4-mini"
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
developer_instructions = """
Use the docs MCP server to confirm APIs, options, and version-specific behavior.
Return concise answers with links or exact references when available.
Do not make code changes.
"""

[mcp_servers.openaiDeveloperDocs]
url = "https://developers.openai.com/mcp"

This is where subagents compose with MCP. The docs researcher doesn’t read your codebase — it reads external documentation through a dedicated MCP server. This separation of concerns means the reviewer doesn’t need to context-switch between “reading the diff” and “looking up API signatures.”

Step 5: Wiring it together

With all three agents defined, the prompt that triggers the pipeline is straightforward:

Review this branch against main. Have pr_explorer map the affected code paths,
reviewer find real risks, and docs_researcher verify the framework APIs that the
patch relies on.

Codex handles the orchestration: spawning agents, routing their instructions, waiting for all results, and returning a consolidated response. You don’t manage thread lifecycles manually.

How approvals and sandbox work across agents

Subagents inherit the parent session’s sandbox policy by default. If you’re running with --yolo or have changed approval settings with /approvals, those overrides propagate to children.

You can also hardcode sandbox policy per agent with sandbox_mode. An agent with sandbox_mode = "read-only" stays read-only regardless of what the parent session allows. This is the right call for all three review agents — they produce findings, not changes.

In interactive CLI sessions, approval requests can surface from inactive agent threads even while you’re looking at the main thread. The approval overlay shows the source thread label, and you can press o to open that thread before approving or rejecting.

In non-interactive flows, actions that need fresh approval fail and surface the error back to the parent. The review doesn’t silently skip a check — it reports what it couldn’t do.

When this pattern works

The three-agent split works because the tasks are genuinely independent. The explorer doesn’t need the reviewer’s output. The reviewer doesn’t need the docs researcher’s findings. Each agent works from the same input (the diff) and produces independent output. That’s the test for whether parallel subagents help: if agents can work without seeing each other’s intermediate results, fan out. If each step depends on the previous one’s discoveries, keep it in the main thread.

Getting started in 5 minutes

  1. Create .codex/agents/ in your project root
  2. Add the three TOML files above (or start with just pr_explorer and reviewer)
  3. Set max_threads = 6 and max_depth = 1 in .codex/config.toml
  4. Make a change on a branch, then run the review prompt
  5. Iterate on the agent instructions based on what the review misses

Start with well-scoped changes where you already know what a good review looks like. That gives you a baseline for judging whether the agents are catching the right things.

Split review across agents with clean contexts

An agent that wrote the code reviews it poorly. Three agents with independent context windows — explorer, reviewer, docs researcher — catch what a single agent misses.

TOML files are the agent definition format

Each custom agent lives in its own file under .codex/agents/ with name, description, developer_instructions, model, and sandbox_mode.

Read-only sandbox for all review agents

Review produces findings, not changes. Hardcoding sandbox_mode = "read-only" per agent is defense in depth regardless of parent session policy.

Parallel works; sequential doesn't

Fan out when agents work from the same input independently. Keep dependent multi-step workflows in the main thread to avoid context loss at handoff boundaries.

Descriptions program the parent agent

A custom agent's description field shapes what instructions the main thread writes when delegating. Write them as meta-prompts, not labels.