Subagent capacity guardrail for Codex Desktop

Stop losing long prompts to invisible native subagent limits.

Has your Codex agent ever written a careful 900-word reviewer prompt, then failed because it did not know there were only six native subagent slots? This hook makes the pool visible before the agent wastes the turn.

before and after
agent: I will spawn reviewer, verifier, and critic...
runtime: unable to create 1 agent
runtime: native subagent pool is full
agent: closing six old agents, retrying long prompt...

advisor: occupied=5/6, remaining_spawn_budget=1
advisor: requested_spawns=2 would exceed cap
advisor: reuse an existing lane or close one first

What it prevents

The hook does not decide whether to delegate. It only keeps Codex from colliding with native pool reality.

Invisible cap hits

Reads per-parent native edge state and injects current budget before launch-heavy turns.

Batch spawn failures

Counts nested wrapper calls so two requested spawns consume two slots before approval.

Stale open rows

Excludes native open edges only when the child transcript has structured completion evidence.

Recursive delegation

Blocks child agents from spawning their own reviewers, verifiers, or explorers.

Wrong explorer model

Requires read-only explorer work to use a configured fast model lane instead of inheriting a frontier model.

Contract drift

Advises when a prompt asks a scout lane to own synthesis, edits, approval, or repeated compaction.

Destructive reset drift

Uses dry-run force tokens before clearing native edge state.

Install

Run tests first, install into your Codex home, then verify the live hook registration with doctor.

git clone https://github.com/fitz-s/codex-native-agent-pool-advisor.git
cd codex-native-agent-pool-advisor
npm test
node scripts/install.mjs
node scripts/doctor.mjs

Configure the non-universal parts

Model catalogs, state DB names, and fallback policies vary by Codex install. Keep them outside the hook logic.

Spark scan lane

gpt-5.3-codex-spark is treated as the near-instant scout lane for grep, file maps, symbol lookup, log filtering, file:line anchors, and fast hypothesis probes inside larger workflows.

Mini reasoning lane

gpt-5.4-mini is treated as the reasoning explorer / light executor lane for multi-hop traces, compact synthesis, small low-risk edits, and bounded verification.

Advisory contract

The hook does not block Spark because a task sounds complex. It asks the parent to cap scope/output, return anchors, or escalate synthesis to mini/frontier.

models.explorer Allowed read-only explorer models. Defaults to Spark plus mini fallback. If this is the only model setting, the first entry is preferred and the second is fallback.
defaults.agentCap Fallback cap when [agents].max_threads is absent.
defaults.warnRemaining How early advisory context appears near the native cap.
paths.stateDbName Codex native state DB filename when it is not state_5.sqlite.
{
  "models": {
    "explorer": ["gpt-5.3-codex-spark", "gpt-5.4-mini"],
    "explorerPreferred": "gpt-5.3-codex-spark",
    "explorerFallback": "gpt-5.4-mini"
  },
  "defaults": {
    "agentCap": 6,
    "warnRemaining": 1
  },
  "paths": {
    "stateDbName": "state_5.sqlite"
  }
}

Route by contract

OpenAI's agent guidance points to explicit model choice per specialist and mixed model sizes in the same workflow. This hook follows that shape: it blocks missing explicit explorer models, but it only advises on Spark/Mini contract fit.

Official basis

Codex subagents are useful for read-heavy exploration, triage, tests, and summarization; model and reasoning settings should differ by agent need.

Community pressure

Large repositories and compaction-heavy investigations need cheaper context-isolated exploration lanes before the leader spends frontier context.

Hook boundary

The hook enforces observable runtime safety. It does not decide whether Spark, mini, or frontier owns the next reasoning step.

Safety boundary

Normal hook execution writes advisor JSON state and logs. SQLite mutation is limited to successful close-agent evidence or the explicit reset script.

node scripts/reset-pool.mjs --parent <thread_id> --dry-run
node scripts/reset-pool.mjs --parent <thread_id> --force <token_from_dry_run>