Support PreToolUse permissionDecision: ask for native approval prompts
Summary
Please add native support for PreToolUse hooks returning permissionDecision: "ask", so a hook can escalate a specific tool call into a human approval prompt.
This was already explored in closed PR #20702: https://github.com/openai/codex/pull/20702
Current behavior
Codex currently parses permissionDecision: "ask", but treats it as unsupported. A PreToolUse hook that returns:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "ask",
"permissionDecisionReason": "This command needs explicit approval."
}
}
fails with:
PreToolUse hook returned unsupported permissionDecision:ask
The same applies to some Claude-compatible fields such as continue: false, stopReason, and suppressOutput: they are parsed, reported as unsupported, and the tool call continues depending on the hook failure behavior.
Desired behavior
PreToolUse permissionDecision: "ask" should route that specific tool call to the native Codex human approval flow.
Suggested precedence:
PreToolUse: askshould force a user approval prompt for that tool call.PreToolUse: denyshould continue to block the tool call.PreToolUse: allowshould not bypass core policy, sandbox checks, network checks, or later concrete approval boundaries.- Core policy should remain authoritative; a hook should be able to tighten approval requirements, not weaken them.
Why this matters
Hooks are useful as durable safety policy. Today a hook can deny a tool call, but it cannot say “this is allowed only after explicit user approval.” That forces users to either globally tighten approval policy, which is noisy, or deny commands that would be safe with per-call approval.
This is especially useful for Codex App/CLI setups where teams use PreToolUse hooks to guard high-risk commands, writes, network access, production operations, or organization-specific workflows.
Related work
PR #20702 already implemented a design in this direction and described the intended safety property: ask can tighten a decision into explicit approval, while allow must not waive core policy or later checks.
It was closed for inactivity, not because the feature was rejected. Reopening that PR or landing an equivalent focused implementation would solve this request.
6 Comments
I would support this, with one extra invariant: ask should create a pending approval record for the exact tool call, not just flip a hook-output flag.
The hook ask decision is a tightening decision. I would bind it to:
The precedence I would want:
Regression tests I would pin:
That gives teams a policy hook that can tighten authority for one call without creating an ambient bypass path.
The tightening-only rule is the key design constraint here, and it is worth making visible in the hook contract itself.
If ask is supported, the receipt back to the hook layer should say which approval boundary was escalated, whether core policy would already have blocked it, and whether the user approved or denied. That makes hook-driven approvals auditable instead of feeling like a silent second policy engine.
Yes. I would make that receipt part of the contract, not just an implementation log.
The hook layer needs to know whether it tightened an action into native approval and what happened afterward. Otherwise "ask" becomes hard to audit: the hook can request escalation, but it cannot distinguish "core policy would have blocked anyway", "native approval was shown and approved", "native approval was denied", or "the prompt expired/cancelled".
The receipt I would want back to the hook is small:
Two invariants follow from that:
That keeps the hook contract simple: the hook asks for a higher-authority decision, and the runtime returns a receipt proving which exact decision closed which exact pending call.
Another useful model for
PreToolUse: askis a two-stage review pipeline:askwith a semantic, rule-specific reason.This combines the strengths of both layers:
The result could improve safety without requiring a human prompt for every statically flagged operation.
For this use case, it would be valuable for
askto enter Codex's native approval pipeline and follow the effectiveapprovals_reviewer, rather than always bypassing Auto Review.A minimal additional acceptance case: a PreToolUse hook needs to add deterministic shell lifecycle instrumentation while preserving native command-aware approval. Today, updatedInput is ignored without permissionDecision allow; allow applies the rewrite but bypasses the ordinary approval decision; ask is unsupported; and PermissionRequest cannot rewrite input. A deny-then-retry wrapper preserves execution safety but native approval and reusable prefix rules evaluate the wrapper rather than the original command. Please support updatedInput together with ask so approval binds the effective input digest, retains the original input for audit, and still applies core policy, sandboxing, and normal approval rules.
Confirmed still present in codex-cli 0.149.0 on Linux.
Reproduction through a real downstream integration:
Observed result: the exact retry remains blocked even though the user approval is explicit. This makes conversational approval non-actionable for hook-gated outward-facing actions. Claude Code routes the same hook-level ask into a native prompt.
A safe fix needs permissionDecision ask to enter the native approval flow, or an unforgeable single-use approval grant bound to the exact retried tool call. Parsing conversation text or trusting an inherited environment variable would create a bypass.
Downstream impact: dev-baseline currently maps ask to deny on Codex and instructs the operator to run the approved command directly.