Skip to content

Allow PostToolUse hooks to request active-turn reasoning-effort updates #47395

Open

Description

@hekmon8

Motivation

Codex already has all the machinery for updating reasoning effort during an active turn:

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:

  1. Hook input: expose the issuing step's effective reasoning_effort on PostToolUse stdin (optional field, sourced from the captured StepContext, so it reflects mid-turn updates rather than turn-initial settings).
  2. Hook output: accept an optional
    { "hookSpecificOutput": { "hookEventName": "PostToolUse", "turnSettings": { "effort": "high" } } }
    turnSettings is modeled after the existing turn-settings abstraction so future fields can extend the same object; only effort is opened up now.
  3. Semantics:
    • only synchronous hooks can apply it (same can_apply_control_effects gating as other control effects);
    • the request is routed through the existing TurnSettingsUpdate validation/publication path, so step_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).

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

  1. SipengXie2024 commented on Oct 12, 2026

    @SipengXie2024

    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:

    1. The first generation: the router needs to set the initial effort before any tools have run. This connects to Feature request: Pre-turn routing hook for plugins to select model and reasoning effort #40599.
    2. Subsequent generations: when a generation produces several tool calls, the router needs an opportunity to evaluate their collected results before the next generation. A hook on each individual tool result is useful for collecting evidence, but the policy should also be able to make one decision from the completed batch.

    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.

  2. robertn702 commented on Oct 13, 2026

    @robertn702

    +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_providers entry, because none of the current hooks run before a model request. It works, but the proxy route has costs this proposal would remove:

    • Custom providers don't get reasoning_effort_override, so the proxy has to pin the request-level effort and insert and replay its own configuration_update items, including after a restart.
    • Users lose the built-in provider behaviors like WebSocket transport and the remote model catalog, and ChatGPT logins need a second proxy (CLIProxyAPI) in the chain.
    • The proxy keeps its own list of each model's supported efforts in sync with the bundled catalog.

    Agree with @SipengXie2024 on the first generation. The proxy decides on every request, including the one before any tools run, and a PostToolUse effect 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthooksIssues related to event hooks

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions