Cron/hook thinking-effort: downgrade only under OAuth proxy#153
Open
constkolesnyak wants to merge 1 commit into
Open
Cron/hook thinking-effort: downgrade only under OAuth proxy#153constkolesnyak wants to merge 1 commit into
constkolesnyak wants to merge 1 commit into
Conversation
Problem: every cron run on Claude OAuth (subscription) fails with
API Error: 400 level "max" not supported, valid levels: low, medium, high
because the global agent.thinking=max / agent.effort=max defaults are
applied to every session, including cron/hook sessions that run on
cron_model (Sonnet by default). Claude OAuth caps non-flagship models
at "high" and rejects "max".
The main interactive model (Opus) accepts "max", so lowering the global
default would degrade the interactive experience to fix cron. API users
(direct ANTHROPIC_API_KEY) accept "max" on every model and shouldn't
be downgraded at all.
Fix: detect OAuth via config.proxy.enabled — the local cli-proxy-api
that wraps Claude Code OAuth credentials. _select_thinking_effort()
caps thinking/effort to "high" only when source is cron/hook AND the
proxy is enabled. API users keep their configured value untouched
for every source, and interactive sessions keep it under OAuth too —
only the narrow OAuth+cron path is downgraded.
Composes with the existing model-aware _effective_effort() (which
already caps Sonnet's effort at "high"); this layer also handles the
thinking side (which the CLI otherwise rejects as a string-level
"max") and makes the OAuth trigger explicit.
Tests: tests/test_engine_options.py — 21 tests covering OAuth on/off
× cron/hook/interactive sources × max/lower values, plus from_dict
backwards-compat (legacy cron_thinking/cron_effort keys are silently
ignored — no schema break for users who had them in config.yaml).
History: supersedes ClickHouse#129. The previous version added cron_thinking
and cron_effort config knobs defaulting to "high", applied
unconditionally to every cron/hook session. @pufit's review there
asked to keep "max" by default and switch to "high" only under
OAuth — this PR does exactly that with no new config knobs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every cron run on Claude OAuth (subscription) fails with:
Root cause: the global
agent.thinking=max/agent.effort=maxdefaults are applied to every session, including cron and hook sessions that run oncron_model(Sonnet by default). Claude OAuth caps non-flagship models athighand rejectsmax. With a persistent cron session this also poisons every subsequent run on the samesdk_session_id.The main interactive model (Opus) accepts
max, so just lowering the global default would degrade the interactive experience to fix cron. API users (directANTHROPIC_API_KEY) acceptmaxon every model and shouldn't be downgraded at all.Fix
Detect OAuth via
config.proxy.enabled— the local cli-proxy-api that wraps Claude Code OAuth credentials is the single source of truth for "running under OAuth subscription" in nerve. Capthinkingandefforttohighonly when:source in ("cron", "hook"), ANDconfig.proxy.enabledis TrueAPI users (no proxy) keep their configured value untouched for every source, and interactive sessions keep it under OAuth too — only the narrow OAuth+cron path is downgraded.
Implementation lives in a small
_select_thinking_effort(config, source)helper at the session-start path innerve/agent/engine.py. It composes cleanly with the existing model-aware_effective_effort(value, model)(which already caps Sonnet's effort athigh) — this layer also handles thethinkingside (which the CLI otherwise rejects as a string-levelmax) and makes the OAuth trigger explicit.No new config knobs.
Tests
tests/test_engine_options.py(new, 21 tests, all passing):cron/hook+max,max→("high","high")(the exact bug being fixed).cron/hook+ lower values → unchanged (cap, not force).cron/hook+ mixed → each knob capped independently.web/telegram/discord/api/"") +max,max→ unchanged (Opus accepts max under OAuth).max,max→ unchanged (Artem's exact requirement).AgentConfig.from_dict({"cron_thinking": "high", "cron_effort": "high"})silently ignores those keys (backwards-compat for anyone whose config had them).Files
nerve/agent/engine.py—_select_thinking_efforthelper + single call site updatetests/test_engine_options.py— newHistory
Supersedes #129 — addresses @pufit's review feedback:
The previous PR introduced two config knobs (
agent.cron_thinking,agent.cron_effort) defaulting tohighand applied them unconditionally — silently downgrading API users. This version detects OAuth automatically viaconfig.proxy.enabledwith no new config surface.🤖 Generated with Claude Code