Skip to content

feat(cron): add per-job reasoning effort overrides - #69911

Open
dbc-hbin wants to merge 1 commit into
NousResearch:mainfrom
dbc-hbin:feat/cron-reasoning-effort-consolidation
Open

feat(cron): add per-job reasoning effort overrides#69911
dbc-hbin wants to merge 1 commit into
NousResearch:mainfrom
dbc-hbin:feat/cron-reasoning-effort-consolidation

Conversation

@dbc-hbin

Copy link
Copy Markdown

Closes #23524.

Summary

Add a first-class optional reasoning_effort override to each cron job and carry it through storage, runtime resolution, the unified cronjob tool, CLI, authenticated APIs, web/desktop editors, automation blueprints, tests, and docs.

This is a current-main consolidation of the overlapping work and design discussion in #7382, #14617, #26214, #30929, #62623, #63327, #64565, and #65679. In particular:

Thanks to @MikelCalvo, @Alex-giao, @evaclawdbot, @PavelTajdus, @dschnurbusch, @the3asic, and the authors/reviewers of the related attempts for establishing the behavior and edge cases this consolidation covers.

Semantics

Canonical stored values are:

none | minimal | low | medium | high | xhigh | max | ultra

Resolution happens only after provider authentication/fallback has selected the model actually used:

job.reasoning_effort
→ agent.reasoning_overrides[effective_model]
→ agent.reasoning_effort
→ provider/model default

Behavior at write boundaries:

  • create omission or null: inherit; store no key;
  • update omission: keep the existing override;
  • update null, or CLI --reasoning-effort inherit: remove the key and restore inheritance;
  • none: explicitly disable reasoning for this job;
  • compatibility input false: canonicalize to none;
  • true, empty/unknown values, containers, and numbers: reject;
  • malformed legacy/hand-edited values: remain readable and are not rewritten on read; execution warns and falls through to model/global/provider policy.

Script-only no_agent jobs retain the configured value for editing/audit and for switching back to agent mode, but never apply it at runtime.

Surface coverage

  • cron storage and scheduler runtime
  • final-model/provider-auth fallback ordering
  • unified cronjob create/update/list
  • hermes cron create, edit, and list
  • authenticated gateway and dashboard APIs
  • web dashboard editor/list UI
  • desktop editor/detail UI and translations
  • automation blueprint parse/create/suggestion/export round trips
  • user and developer documentation

Verification

Rebased onto current main (de5ece994) before submission.

  • Relevant Python/cron/API/CLI suite: 1,445 passed, 0 failed
  • Web cron Vitest: 11 passed
  • Web production build: passed
  • Desktop cron Vitest: 19 passed
  • Desktop TypeScript typecheck: passed
  • Ruff on all changed Python production/test files: passed
  • git diff --check: passed
  • Independent core, boundary, web, and desktop reviews completed; findings were fixed and reverified.

A broader local project run discovered 42,046 tests and reported 25 failures in 14 unrelated platform/environment tests on macOS (for example missing Linux systemctl utilities and /tmp vs /private/tmp assumptions). The complete cron suite remained green.

Compatibility

Existing jobs.json records require no migration and are not rewritten merely by being read or listed. Jobs without the field continue to inherit the existing per-model/global reasoning policy.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cron Cron scheduler and job management comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery comp/tools Tool registry, model_tools, toolsets comp/desktop Electron desktop app (apps/desktop/*) comp/dashboard Web dashboard / control panel UI (dashboard/, landing) area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades duplicate This issue or pull request already exists labels Jul 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #7382: the current diff implements the same per-job reasoning_effort persistence and scheduler-precedence mechanism across the cron surfaces. The additional validation and UI/API coverage are consolidation, not a distinct implementation.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for consolidating the per-job reasoning work. Current main still lacks this capability: cron/jobs.py:1246 has no per-job reasoning_effort input and cron/scheduler.py:3364 resolves only model/global reasoning.

Problems

  • web/src/lib/cron-job.ts:100 converts a malformed legacy value to null; buildCronJobPayload then always emits that null at line 71. An unrelated dashboard edit therefore clears the stored value. This conflicts with the stated read/preserve compatibility contract, and the added test currently codifies the destructive result.

Suggested changes

  • Preserve an invalid legacy value as a distinct editor state and omit reasoning_effort from an update unless the selector was changed. Add a name-only edit test that proves the field is omitted.

This is an automated hermes-sweeper review.

Comment thread web/src/lib/cron-job.ts
@@ -88,6 +100,7 @@ export function cronJobFormFromJob(job: CronJob): CronJobFormState {
base_url: asString(job.base_url),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This collapses an invalid legacy value to null; since buildCronJobPayload always emits reasoning_effort (line 71), a name-only dashboard save clears the stored value. Preserve a distinct invalid/preserve state and omit the field until the user changes this selector.

@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Jul 30, 2026
@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Nine PRs address or reference #23524. #7382, #26214, #30929, #62623, #63327, #64565, #65679, and #69911 implement the same per-job cron reasoning override at varying surface breadth, while #14617 combines that mechanism with broader /reasoning --global session work; the strongest diffs preserve job override → effective-model override → global fallback and distinguish explicit none from inheritance.

Related pull requests

  • feat(cron): add per-job reasoning effort overrides #7382 best fix — (+318/-29) — n/a: Focused storage, scheduler, CLI, tool, tests, and documentation coverage for per-job overrides; the current diff validates at the storage boundary, derives choices from VALID_REASONING_EFFORTS, preserves none, and falls back through resolve_reasoning_config. The recorded best-fix designation and the fixes reported in 5895e1085 support retaining this as the canonical salvage base after the contributor's keep-open review.
  • fix: support /reasoning --global and cron reasoning overrides #14617 partial — (+529/-43) — n/a: Combines cron persistence and precedence with shared /reasoning --global parsing and session-scoped CLI, gateway, and TUI behavior. The contributor's keep-open review identifies obsolete handler locations and incomplete cron CLI/API/web coverage, so its distinct interactive reasoning work should be split and rebased rather than used as the cron consolidation base.
  • feat: add per-job cron reasoning effort #26214 partial — (+201/-6) — n/a: Adds core storage and scheduler behavior plus tool, gateway API, web-server, tests, and docs, but its visible scheduler uses an or expression and its interfaces omit current canonical levels and standalone CLI set/clear paths. Despite the keep-open review, the diff shows a narrower duplicate of feat(cron): add per-job reasoning effort overrides #7382 that still needs the review's listed repairs.
  • feat(cron): add per-job reasoning effort #30929 fixes — (+482/-3) — n/a: Adds storage, scheduler fallback, tool and CLI UX, tests, and docs, including explicit none, clear behavior, and malformed-value fallback. Despite the keep-open review, its visible CLI parser edit targets obsolete hermes_cli/main.py ownership and hard-codes an outdated effort subset, so it remains a duplicate of feat(cron): add per-job reasoning effort overrides #7382 rather than a separate consolidation lane.
  • feat(cron): support per-job reasoning effort #62623 [closed] partial — (+545/-10) — n/a: Closed as a duplicate of feat(cron): add per-job reasoning effort overrides #7382; it remains relevant as tested reference coverage for max, legacy false, malformed stored values, active CLI parser wiring, and safe global fallback.
  • feat(cron): add per-job reasoning effort across all surfaces #63327 fixes — (+1125/-17) — n/a: Broadly covers storage, CLI, APIs, web/desktop UI, tests, and docs, but its scheduler diff replaces the shared per-model resolver with direct global parsing. Despite the maintainer-bot keep-open verdict, salvage requires preserving its cross-surface additions while restoring resolve_reasoning_config for the fallback chain.
  • feat(cron): per-job reasoning_effort override #64565 [closed] fixes — (+218/-7) — n/a: Closed after a contributor documented the decision to pursue per-auxiliary-task reasoning instead; the diff remains a useful reference because it preserves job → per-model → global precedence through the shared resolver. It is also recorded as a duplicate of feat(cron): add per-job reasoning effort overrides #7382 and should remain closed.
  • feat(cron): configure reasoning per job #65679 [closed] best fix — (+732/-20) — n/a: Closed in favor of feat(cron): add per-job reasoning effort overrides #7382; its comprehensive storage, final-model-aware scheduler, CLI, tool, API, web/desktop UI, tests, and docs remain a strong reference implementation. Although it has a recorded best-fix designation, the author explicitly closed it for the same mechanism covered by the still-open canonical PR, so reopening is not recommended.
  • feat(cron): add per-job reasoning effort overrides #69911 fixes — (+1530/-23) — n/a: Current-main consolidation covering storage, final-model-aware precedence, CLI, authenticated APIs, web/desktop editors, blueprints, tests, and docs. Despite the contributor keep-open review, the visible web diff still maps malformed legacy values to null and always emits that field, so an unrelated dashboard edit can destructively clear stored data; this blocker must be fixed or the unique cross-surface work split onto feat(cron): add per-job reasoning effort overrides #7382.

Duplicates

#7382, #26214, #30929, #62623, #63327, #64565, #65679, and #69911 implement substantially the same per-job cron reasoning_effort mechanism; the cron portion of #14617 overlaps that chain, while its /reasoning --global session work is separable. The explicit duplicate chain is #26214/#30929/#62623/#63327/#64565/#65679/#69911#7382.

Suggested consolidation

Keep #7382 open with a salvage path as the canonical focused implementation: retain its validated storage boundary, current CLI parser wiring, canonical effort vocabulary, and shared resolver fallback. Author action: rebase #14617 and split out its distinct /reasoning --global work; split any still-useful API/UI/blueprint coverage from #63327 and #69911 onto #7382, while addressing #63327's per-model-resolution regression and #69911's blocking legacy-value preservation review, then close #26214, #30929, #63327, and #69911 as duplicates of #7382; keep #62623, #64565, and #65679 closed.

Complex graph

flowchart TD
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I23524(["issue #23524 (open)"])
    subgraph Dup7382 ["PRs duplicating each other"]
        P7382["PR #7382 (open)"]
        P26214["PR #26214 (open)"]
        P30929["PR #30929 (open)"]
        P62623["PR #62623 (closed)"]
        P63327["PR #63327 (open)"]
        P64565["PR #64565 (closed)"]
        P65679["PR #65679 (closed)"]
        P69911["PR #69911 (open)"]
    end
    P69911 -->|fixes| I23524
    class I23524 open
    class P7382 open
    class P26214 open
    class P30929 open
    class P62623 closed
    class P63327 open
    class P64565 closed
    class P65679 closed
    class P69911 open
    class P7382 best
    class P65679 best
    class P69911 target
    click I23524 "https://github.com/NousResearch/hermes-agent/issues/23524"
    click P7382 "https://github.com/NousResearch/hermes-agent/pull/7382"
    click P26214 "https://github.com/NousResearch/hermes-agent/pull/26214"
    click P30929 "https://github.com/NousResearch/hermes-agent/pull/30929"
    click P62623 "https://github.com/NousResearch/hermes-agent/pull/62623"
    click P63327 "https://github.com/NousResearch/hermes-agent/pull/63327"
    click P64565 "https://github.com/NousResearch/hermes-agent/pull/64565"
    click P65679 "https://github.com/NousResearch/hermes-agent/pull/65679"
    click P69911 "https://github.com/NousResearch/hermes-agent/pull/69911"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 9 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 423 kB of PR diffs, 27 kB of issue/PR text, 20 kB of discussion (29 comments), 17 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

@teknium1

Copy link
Copy Markdown
Contributor

Heads-up: the core cron half of this (store validation, scheduler precedence, CLI flags, docs) landed on main via #91244 (43c6dac, salvaged from #91038; first-submitter credit to @PavelTajdus in #30929). What #91244 did NOT land is your desktop/dashboard/web surfacing — that half is still open ground. Two notes for a rebase: (1) the merged store uses cron/jobs.py::_normalize_reasoning_effort + cron/scheduler.py::_resolve_job_reasoning_config — please build on those rather than a parallel path; (2) standing policy from the #91244 review: the field must NOT be exposed on the model-facing cronjob tool schema (there's a policy-pinning test), but dashboard/web UI is a user surface and is welcome. If you rebase this down to just the UI half (or continue via #79486 which includes your fix), we'd be glad to review.

@alt-glitch alt-glitch removed the duplicate This issue or pull request already exists label Aug 21, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to merged #91244: the core cron implementation landed there, while the desktop/dashboard/web user surface remains a valid follow-up if rebased onto that implementation and kept out of the model-facing cronjob tool schema.

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

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/desktop Electron desktop app (apps/desktop/*) comp/gateway Gateway runner, session dispatch, delivery comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: support per-cron reasoning effort overrides

4 participants