Hermes Agent Lands Per-Task Reasoning Effort Controls - 3 PRs, 35 Files

Three related PRs landed on July 14-15, 2026, all from @teknium1, that together give Hermes Agent the ability to control reasoning depth at every level: per-model, per-auxiliary-task, and per-MoA-slot. The total: 2,103 additions across 35 files. Each PR is independently useful, but the combined surface is a complete cost-control layer.
Previously, if your main model was Claude Opus with reasoning at xhigh, every side task inherited that same expensive thinking - compression summaries, image descriptions, session titles - whether they needed it or not. The only alternative was routing those tasks to a cheaper model entirely, trading quality for cost. These three PRs add a third option: keep the side task on your main reasoning model, but dial the thinking down.
The three PRs
| PR | Additions | Files | What it does |
|---|---|---|---|
| #64458 | +1,391 | 19 | Per-model reasoning_effort overrides via unified resolution chokepoint |
| #64597 | +195 | 5 | Per-task reasoning_effort for all 16 auxiliary model tasks |
| #64631 | +517 | 11 | Per-slot reasoning_effort in MoA presets |
| Total | +2,103 | 35 | Full reasoning-effort control surface |
Level 1: Per-model overrides - PR #64458
The foundation. PR #64458 (salvaging @ScotterMonk's #51377) adds agent.reasoning_overrides - a dict in config.yaml mapping model identifiers to reasoning effort levels. A single chokepoint function, resolve_reasoning_config(...), now feeds every surface: CLI, gateway, TUI, cron, /model switches, and fallback paths.
agent:
reasoning_effort: "medium"
reasoning_overrides:
"openrouter/anthropic/claude-opus-4.5": "xhigh"
"openai/gpt-5": "low"
"gemini-flash": "none"
The resolution priority, as documented in the PR body:
- Session-scoped
/reasoning --session(unchanged - still wins)- Per-model override from
agent.reasoning_overrides- Global
agent.reasoning_effort- Provider default
Model matching is spelling-tolerant: dots and dashes are interchangeable, the provider/aggregator prefix is optional, and exact matches win over partial ones. gemini-flash never accidentally matches gemini-2.0-flash.
The PR also fixed a bug: the gateway previously resolved overrides against config.model.default even after a session-only /model switch. The fix makes both gateway message paths and /reasoning status respect the session's effective model.
Level 2: Per-auxiliary-task effort - PR #64597
PR #64597 extends the mechanism to all 16 auxiliary task blocks. Each task now accepts a reasoning_effort field:
auxiliary:
compression:
reasoning_effort: "low"
vision:
reasoning_effort: "none"
A single resolution point in _get_task_extra_body() folds the shorthand into extra_body.reasoning, which every auxiliary wire format already translates:
| Wire format | Translation |
|---|---|
| chat.completions | Passes `extra_body.reasoning` through (existing) |
| Codex Responses adapter | Maps to top-level `reasoning` + `include` (existing) |
| Anthropic Messages adapter | Forwards into `build_anthropic_kwargs(reasoning_config=...)` (fixed here - was hardcoded to `None`) |
The precedence rule: an explicit extra_body.reasoning on the same task wins over the shorthand. Invalid effort values are ignored with a warning. Empty string (the shipped default) is a no-op - nothing changes unless you configure it.
Level 3: Per-MoA-slot effort - PR #64631
PR #64631 (salvaging @justinschille's #61711) adds per-slot reasoning_effort to MoA presets and removes the ensemble-wide auxiliary.moa_reference/moa_aggregator knob in favor of slot-level control:
moa:
presets:
deep_review:
reference_models:
- provider: openai-codex
model: gpt-5.6-sol
reasoning_effort: low
- provider: openai-codex
model: gpt-5.6-sol
reasoning_effort: xhigh
aggregator:
provider: openai-codex
model: gpt-5.6-sol
reasoning_effort: high
Each reference advisor and the aggregator can set its own effort, including disabling thinking entirely for fast advisors while keeping deep reasoning for others. The reasoning_config projects through provider profiles - OpenRouter maps to extra_body.reasoning, custom/vLLM/GLM maps to top-level reasoning_effort, disable becomes think: false, and Anthropic Messages routes through build_anthropic_kwargs.
The live validation confirmed all three slots hitting different levels on the wire in a single MoA turn: advisor A at xhigh, advisor B with think: false, aggregator at low.
Why this matters
Before these PRs, running an expensive reasoning model as your main agent meant every side task - compression, vision, title generation, background review, curator - burned the same expensive thinking tokens. The workaround was to route aux tasks to a cheaper model entirely, which trades quality for cost.
These PRs add a midpoint: keep the side task on your reasoning model, but set reasoning_effort: "low" for compression and "none" for vision. The model still generates competent summaries and image descriptions - it just does not spend tens of thousands of thinking tokens doing it.
The per-MoA slot control is a different optimization: you can now run a fast advisor alongside a deep one in the same ensemble. One slot gets a quick take at low, another does deep analysis at xhigh, and the aggregator synthesizes both at whatever level makes sense. Each advisor only pays for the thinking depth you assigned it.
The unified resolution chokepoint in PR #64458 is the architectural win. Before, six different call sites independently resolved reasoning effort. Now one function feeds them all. When reasoning effort semantics change - say a new provider joins - only the chokepoint needs updating.
[^1]: #64458 - feat(config): per-model reasoning_effort overrides via unified resolution chokepoint. @teknium1 & @ScotterMonk. Merged July 14, 2026.
[^2]: #64597 - feat(auxiliary): per-task reasoning_effort for auxiliary models. @teknium1. Merged July 14, 2026.
[^3]: #64631 - feat(moa): per-slot reasoning_effort in MoA presets. @teknium1 & @justinschille. Merged July 15, 2026.
[^4]: Hermes Agent configuration docs - Auxiliary Models section.