Repository navigation
Allow PostToolUse hooks to request active-turn reasoning-effort updates #47395
Description
Motivation
Codex already has all the machinery for updating reasoning effort during an active turn:
TurnSettingsUpdate/Op::TurnSettingspublishes sparse settings updates for subsequent steps of a live turnstep_model_switchinggates those updates and existing managed-policy/model validation stays authoritative- supported models switch effort cache-preservingly through the reasoning-effort override path (Record reasoning effort changes in conversation history behind a flag #43110, GPT-6 Astra reasoning-effort changes do not use configuration_update, defeating cache preservation #42996)
PostToolUsehooks already receive the activesession_id/turn_id, tool input/output, and run against the capturedStepContext(Use captured step settings for request metadata and tool hooks #45248)
What's missing: a PostToolUse hook cannot request an effort change for the remaining steps of the turn it is observing. A hook can see that a tool result was huge, trivial, or failed, but has no sanctioned way to say "escalate/de-escalate effort from here on". That blocks extensions from implementing policies like adaptive reasoning (#38487) without coupling to Codex internals.
Proposal
A minimal, general control effect — not an adaptive-reasoning policy:
- Hook input: expose the issuing step's effective
reasoning_effortonPostToolUsestdin (optional field, sourced from the capturedStepContext, so it reflects mid-turn updates rather than turn-initial settings). - Hook output: accept an optional
{ "hookSpecificOutput": { "hookEventName": "PostToolUse", "turnSettings": { "effort": "high" } } }turnSettingsis modeled after the existing turn-settings abstraction so future fields can extend the same object; onlyeffortis opened up now. - Semantics:
- only synchronous hooks can apply it (same
can_apply_control_effectsgating as other control effects); - the request is routed through the existing
TurnSettingsUpdatevalidation/publication path, sostep_model_switching, managed policy, and model support remain authoritative — no new validation logic, no Responses/cache changes; - rejections surface the existing reason as a warning instead of failing the turn;
- multiple hooks requesting the same effort apply it once; conflicting requests apply nothing and emit a diagnostic (no silent last-write-wins).
- only synchronous hooks can apply it (same
Non-goals
- No auto/adaptive-reasoning policy, escalation rules, TTL, or bounds — those are consumers of this primitive.
- No changes to the Responses API,
configuration_update, request construction, or prompt-cache behavior.
Implementation
I have a working branch prepared (parser + schema + aggregation, session plumbing through apply_turn_settings, and unit/integration tests incl. sync/async gating, feature-gate rejection, and multi-hook conflicts):
main...hekmon8:codex:post-tool-use-turn-settings-effort
Happy to open the PR if this direction sounds right.
Refs: #38487 (adaptive reasoning use case), #42996 (effort switching/cache context), #43110 (cache-preserving reasoning-effort infrastructure), #45248 (captured step settings for tool hooks).
Activity
SipengXie2024 commentedon Oct 12, 2026
I would like to add a concrete use case for this interface: a Jev-based effort router that keeps the selected model fixed and adjusts effort within the same user turn.
In my local Claude Code integration, the router chooses an initial effort from the task, collects tool outcomes, and updates effort before each model generation. Failed checks can raise effort; successful recovery allows it to step down. I would like to run this policy as a Codex plugin without maintaining a patched Codex binary.
The proposed PostToolUse control effect would help. Two execution boundaries matter for this use case:
A supported pre-generation hook, or equivalent semantics built on the existing hooks, would cover both. The useful contract would expose the current effective effort, the model's supported effort values, and stable turn/step identifiers; accept an optional effort override; and apply it before capturing the settings used for the next generation. Codex should retain validation and user-control responsibilities: respect manual overrides, preserve the current setting on hook failure or timeout, and distinguish requested settings from settings that actually took effect.
Astra-Ares documents a native checkpoint and a patched Codex build for this purpose. A supported plugin interface would let implementations share the official runtime while keeping their routing policies independent.
My environment is Codex CLI 0.162.1. This is a request for an extension point; Jev, escalation rules, and any built-in Auto policy can remain separate choices. I have not benchmarked this policy on Codex and am not claiming a cost or quality improvement.
robertn702 commentedon Oct 13, 2026
+1 from someone running an effort router on Codex today without this hook. I maintain reasoning-router, which does it as a local Responses proxy behind a custom
model_providersentry, because none of the current hooks run before a model request. It works, but the proxy route has costs this proposal would remove:reasoning_effort_override, so the proxy has to pin the request-level effort and insert and replay its ownconfiguration_updateitems, including after a restart.Agree with @SipengXie2024 on the first generation. The proxy decides on every request, including the one before any tools run, and a
PostToolUseeffect alone couldn't cover that one. Exposing the model's supported effort values in hook input would also replace the catalog copy.https://github.com/robertn702/reasoning-router