Support external approval reviewers via approvals_reviewer = "command"
What variant of Codex are you using?
CLI
What feature would you like to see?
I'd like to propose support for an external approval reviewer command in Codex.
Today, approval routing supports user and guardian_subagent, but there is no supported way to integrate approvals with local policy engines or custom approval tooling.
Proposed config
approvals_reviewer = "command"
approvals_reviewer_command = ["/abs/path/to/program", "arg1", "arg2"]
Notes:
- Spawn the program directly, not via a shell.
- If
approvals_reviewer = "command"is set butapprovals_reviewer_commandis missing or empty, config loading should fail clearly.
Suggested v1 behavior
Use the external reviewer only for approval flows that already go through the automated reviewer path today.
Behavior:
- write one JSON request to stdin
- read one JSON response from stdout
- support at least:
approvedapproved_for_sessiondeniedabort- on spawn failure, timeout, nonzero exit, or malformed JSON: fail closed to
ReviewDecision::Denied
Suggested request payload
{
"version": 1,
"review_id": "…",
"turn_id": "…",
"cwd": "/current/session/cwd",
"retry_reason": "…",
"request": {
"...": "existing approval request shape"
}
}
For shell / exec approvals, the nested request should include the actual command, for example:
{
"tool": "shell",
"command": ["git", "push", "origin", "branch"],
"cwd": "/repo/path",
"sandbox_permissions": "use_default",
"justification": "…"
}
Passing the command is the key requirement for local policy engines and custom approval daemons.
Why this seems low-risk
- existing
userbehavior stays unchanged - existing
guardian_subagentbehavior stays unchanged - this only affects flows already using automated review
- it fails closed
- direct argv spawning avoids shell-injection issues
Status
I already have a working local patch for this, including:
- config validation
- command reviewer stdin/stdout JSON exchange
- decision mapping onto existing
ReviewDecisionvalues - fail-closed behavior
- targeted tests for config parsing and one approval path
If this direction aligns with the intended roadmap, I'd be happy to submit it as an invited PR.
Additional information
I personally want this as I'm developing a system to have my agent approval gate in one location, instead of it being spread out through many different clis. So I simply wish to call my already working approval system. I am sure others will do the same, in their own ways. I tried to make the feature generic enough that it could serve anyone.
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
#16301 does indeed seem very similar. This would essentially be the equivalent of the permission hook in Claude Code. The one that left a comment also stated he wants it for observability, which this would also provide.
Working PR ready to go 👍
One related use case this could cover is approval-block observability.
If the external reviewer command receives the same approval request Codex is about to show to the user, local tooling can treat that as a stable machine-readable "Codex is blocked waiting for approval" event. That avoids scraping transcript text or internal artifacts.
For that to work cleanly, I think the response enum should include an explicit abstain value:
Semantics:
approved,approved_for_session,denied, andabortmake the approval decision.defer_to_usermeans the external reviewer observed the request but chose not to decide.denyas the safe default, with an opt-in mode that falls back to the user prompt.Example:
This would apply to spawn failure, timeout, nonzero exit, or malformed JSON.
That gives both workflows:
defer_to_userThis feature hasn't received enough upvotes, so closing.