Auto-review guardian turns fire UserPromptSubmit without matching subagent lifecycle hooks

Open 💬 0 comments Opened Aug 26, 2026 by bob-zebedy

What version of Codex CLI is running?

codex-cli 0.149.1

The same behavior first appears in local rollout data produced by 0.147.0.

What subscription do you have?

Pro

Which model were you using?

  • Parent turn: gpt-5.6-sol
  • Internal reviewer turn: codex-auto-review

What platform is your computer?

Darwin 25.6.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

iTerm2 3.6.11

Codex doctor report

Redacted relevant excerpt. The full report contains unrelated local paths and sandbox-only network diagnostics.

{
  "schemaVersion": 1,
  "codexVersion": "0.149.1",
  "runtime": {
    "platform": "macos-aarch64",
    "installMethod": "standalone"
  },
  "config": {
    "hooks": true,
    "guardianApproval": true,
    "approvalPolicy": "OnRequest"
  }
}

What issue are you seeing?

With approvals_reviewer = "auto_review", every permission review starts an internal guardian turn. User-configured hooks receive a UserPromptSubmit event for that hidden reviewer turn, but receive no matching SubagentStart, SubagentStop, or Stop event.

The observed start event has this shape, with identifiers redacted:

{
  "hook_event_name": "UserPromptSubmit",
  "model": "codex-auto-review",
  "session_id": "<parent-session-id>",
  "turn_id": "<guardian-turn-id>",
  "agent_id": null
}

The guardian's separate rollout confirms that the turn is a subagent and completes normally:

{"type":"session_meta","payload":{"session_id":"<parent-session-id>","source":{"subagent":{"other":"guardian"}},"thread_source":"subagent"}}
{"type":"event_msg","payload":{"type":"task_started","turn_id":"<guardian-turn-id>"}}
{"type":"event_msg","payload":{"type":"task_complete","turn_id":"<guardian-turn-id>"}}

No terminal hook is emitted for <guardian-turn-id>, even though task_complete is present in the rollout. This occurs in the interactive TUI (originator = "codex-tui"), not in codex exec.

The imbalance is large because one reviewer turn is created per permission request. In a sanitized local sample from August 17 through August 26:

  • 520 unique codex-auto-review UserPromptSubmit turns were emitted
  • 0 of those turns had a matching Stop or SubagentStop
  • In an August 26 snapshot, 59 reviewer turns had no terminal hook, while all 3 completed user-facing turns had matching Stop events; the fourth user-facing turn was still active

There was exactly one configured handler for each event, so this was not caused by duplicate hook configuration.

This leaves hook-based task status and analytics integrations with hundreds of phantom running tasks. Filtering on the internal model slug is possible, but it relies on an undocumented implementation detail and can break when the reviewer model changes.

What steps can reproduce the bug?

  1. Configure Auto Review:
approval_policy = "on-request"
approvals_reviewer = "auto_review"
sandbox_mode = "workspace-write"
  1. Configure the same append-only logger for PermissionRequest, UserPromptSubmit, SubagentStart, SubagentStop, and Stop:
{
  "hooks": {
    "PermissionRequest": [{"hooks":[{"type":"command","command":"tee -a /tmp/codex-hook-events.jsonl >/dev/null"}]}],
    "UserPromptSubmit": [{"hooks":[{"type":"command","command":"tee -a /tmp/codex-hook-events.jsonl >/dev/null"}]}],
    "SubagentStart": [{"hooks":[{"type":"command","command":"tee -a /tmp/codex-hook-events.jsonl >/dev/null"}]}],
    "SubagentStop": [{"hooks":[{"type":"command","command":"tee -a /tmp/codex-hook-events.jsonl >/dev/null"}]}],
    "Stop": [{"hooks":[{"type":"command","command":"tee -a /tmp/codex-hook-events.jsonl >/dev/null"}]}]
  }
}
  1. Start the interactive codex TUI and ask it to perform an operation that produces a PermissionRequest.
  2. Let Auto Review approve or deny the request.
  3. Inspect /tmp/codex-hook-events.jsonl and the guardian rollout under ~/.codex/sessions/.
  4. Observe a UserPromptSubmit for model = "codex-auto-review" and a completed guardian rollout, but no matching subagent or stop lifecycle hook.

What is the expected behavior?

Internal Auto Review turns should either:

  1. Not fire user-facing UserPromptSubmit hooks; or
  2. Emit balanced SubagentStart and SubagentStop events with stable agent_id / agent_type fields; or
  3. Include a documented, stable internal-task discriminator and a corresponding terminal event.

The documented hook lifecycle says subagents use SubagentStart and SubagentStop, while Stop represents a main turn. Hook consumers should not need to infer internal reviewer identity from model = "codex-auto-review".

Documentation: https://developers.openai.com/codex/hooks

Additional information

Related but distinct reports:

  • #33229 reports internal ChatGPT Desktop background tasks triggering user hooks. In this report, the internal task is specifically the Auto Review guardian, it has a persisted subagent rollout, and that rollout contains task_complete.
  • #18607 reports missing terminal hooks in codex exec. This report reproduces in the interactive TUI.

Guardian rollouts existed locally before this imbalance began. The first unbalanced guardian UserPromptSubmit was observed on August 17, while samples before and after that point both report CLI 0.147.0, so the local evidence does not establish a CLI-version transition as the trigger.

View original on GitHub ↗