Operational diagnosis
July 31, 2026 · HST

Hermes Agent / Slack Runtime

Iteration Budget Exhaustion

The warning is a hard safety ceiling, not the primary failure. In the ForgeCAD incident, the agent spent the entire 150-call allowance doing useful but mostly serial work and never chose to stop, report, or hand off the remaining phases.

150 / 150Hard limit reached
145Persisted tool-calling model turns
188Tool executions in the incident
89%Model turns with only one tool call
0Normal text completions before cutoff

01 / Direct Answer

What The Warning Actually Means

Hermes counts model-loop iterations, not individual tool executions. Each time the model responds with another tool call, one iteration is consumed. When the configured limit is exhausted, Hermes removes tools and asks the model for a summary. That summary can describe progress, but it cannot finish the interrupted work.

This is expected fail-safe behavior. The defect is that long tasks can reach the ceiling while still progressing, and the current runtime has weak mechanisms for checkpointing, phase completion, bounded continuation, or shared parent-and-subagent resource control.

02 / Internal Evidence

ForgeCAD Incident Reconstruction

06:39:51 HST

Adam requested research, two Share Preview reports, CAD-asset discovery, a production app, deployment, verification, and a screenshot in one Slack turn.

06:40–07:17

The parent agent ran 145 persisted tool-calling model turns and 188 tools. Every persisted assistant turn ended in tool_calls; none ended with a normal text answer.

Throughout

129 of 145 tool batches contained one tool call. Only 16 batches used any parallelism. The average was 1.30 tools per model iteration despite independent work being available.

07:17:59 HST

Context compression branched the session and preserved the active task list. The shared iteration budget remained consumed; compression did not reset the turn allowance.

07:19:18 HST

Hermes injected the tool-less maximum-iterations summary request. The model accurately reported that deployment and proof were unfinished.

Source: local Hermes session database and the ForgeCAD Slack thread. Session evidence was inspected read-only.

03 / Root Cause

Why It Happened

One Turn Contained Six Projects

The request bundled investigation, artifact creation, source discovery, application development, deployment, and production proof. The agent treated the whole chain as one uninterrupted loop rather than completing and reporting the requested pre-build deliverables first.

Serial Tool Use Burned Model Calls

Most model turns requested exactly one tool. Independent reads, searches, file operations, and verification checks were rarely batched, so the model repeatedly paid one iteration to decide the next small action.

No Natural Yield Point

The runtime does not require a phase checkpoint after a long tool-only streak. As long as tools keep succeeding, the agent can continue until the hard ceiling without producing a user-facing milestone.

The Ceiling Is Lower Than Current Hermes

ForgeBot runs Hermes v0.17.0 with agent.max_turns: 150. Current official documentation describes a 500-turn default, and the latest tagged release is v0.19.1.

Loop Guardrails Are Warning-Only

tool_loop_guardrails.hard_stop_enabled is false. More importantly, successful but diverse serial work does not look like a repeated failure, so ordinary loop detection would not have stopped this incident anyway.

Compression Preserved Work, Not Budget

Context compression correctly kept the task state and branched the session, but the same per-agent iteration budget remained the governing safety boundary. Compression solved context size, not execution capacity.

04 / External Evidence

Known Hermes Failure Modes With The Same Symptom

Important distinction: the ForgeCAD incident was not the known “reasoning-only response misclassified as incomplete” bug. Its stored finish reasons were all tool_calls. However, ForgeBot’s installed source still contains that older faulty logic, so other 150/150 incidents may have a different root cause.
EvidenceFindingRelevance
Issue #64434 / PR #64764Completed reasoning-only Responses turns could be misclassified as incomplete, triggering retries and exhausting 150 iterations. Fixed July 15, 2026.Installed runtime predates the fix. Not observed in this ForgeCAD trace, but a credible cause of other identical warnings.
Official configuration docsCurrent docs describe a 500-turn default and one grace call before the final summary.Local cap is 150. Raising it reduces cutoff frequency but does not cure inefficient execution.
Issue #16068Bounded auto-continue after max iterations was proposed and closed as not planned.Upstream deliberately keeps the summary-only backstop; a ForgeFX-specific continuation policy would be local product behavior.
Issue #67253Parent and subagents lack one shared aggregate resource budget; independent child budgets can multiply work.Delegation prevents parent exhaustion but needs its own cost/time controls.
Agent loop internalsA model response containing tool calls loops; a plain text response exits. IterationBudget is the hard backstop.Matches the incident exactly: 145 stored tool-call turns and no plain-text exit.

05 / Frequency

How Often It Is Happening

The local session store contains 815 Slack sessions. Six reached at least 150 recorded model calls (0.74%), 13 reached at least 140 (1.60%), and 41 reached at least 100 (5.03%). The overall average is 28.7 calls. This is a tail-risk pattern concentrated in large build, media, Unity, and repository-action tasks—not normal chat traffic.

The database is strong evidence of high-call sessions, but not a perfect warning counter: status messages are delivered outside ordinary session content, historical caps changed, and post-compression persistence can make the stored call count differ slightly from the displayed 150/150.

06 / Solutions

Recommended Fix Stack

RankActionExpected EffectTrade-Off
01Upgrade ForgeBot from Hermes v0.17.0 to v0.19.1. Preserve and reconcile the three carried local commits, then run gateway and Slack regression checks.Removes known Codex response-classification bugs and roughly six weeks of gateway, session, compression, and agent-loop fixes.Upgrade risk is real because the checkout has carried commits and local state. It must be staged and verified, not blindly installed.
02Split large Slack requests into explicit phases with visible yields. Research → preview reports → build → deploy → proof. Finish and report each required milestone before entering the next.Prevents one tool loop from owning an entire multi-project request. Aligns execution with Adam’s requested ordering.Produces more than one user-facing update unless the phases run as durable background work.
03Use durable workers for long builds. Give independent research/build lanes bounded subagent or Kanban budgets; run builds and deploy polling as tracked background processes.Keeps the Slack parent focused on orchestration and reporting instead of spending 100+ decisions on mechanics.Without aggregate controls, delegation can increase total calls. Cap child scope, concurrency, and deliverables.
04Add a budget-aware checkpoint policy. After 40 consecutive tool-only model turns or at 70% of the allowance, require a durable state write and a phase decision: finish, delegate, or yield.Stops silent drift before the hard wall and protects unfinished state.Earlier upstream “budget pressure” prompts caused premature abandonment. The policy should request a checkpoint and phase decision, not “stop now.”
05Batch independent calls and route mechanical loops through programmatic execution. Enforce parallel read/search batches and use the refunded programmatic tool runner for repeated deterministic operations.Directly attacks the observed 89% single-tool-turn rate.Over-batching can make failures harder to isolate. Only batch independent work.
06Raise agent.max_turns only after controls are in place. Move from 150 toward the current 500-turn default, with warning thresholds and hard-stop telemetry.Gives legitimate complex work more runway.Alone, it turns a 40-minute cutoff into a longer, more expensive cutoff. This is capacity, not control.
07Enable hard loop stops for unattended gateway work. Keep warning thresholds and turn on hard stops for repeated exact failures and idempotent no-progress calls.Prevents obvious retry loops from consuming the full budget.Would not have stopped ForgeCAD because its calls were diverse and mostly successful.
08Instrument the gateway. Record per-turn tool-only streak, calls by tool, parallel batch ratio, compression count, time, and exit reason; alert at 70%, 90%, and exhaustion.Makes causes measurable and separates productive long work from retries, stalls, and loops.Adds operational telemetry and needs a quiet dashboard rather than more Slack chatter.

07 / Proposed Rollout

Safe Implementation Order

Day 1 — Runtime + Baseline

  1. Snapshot current version, config, carried commits, and gateway health.
  2. Upgrade in an isolated worktree/profile.
  3. Run model, tool, compression, Slack, and resume tests.
  4. Deploy only after the same tests pass on the live gateway.

Day 1 — Behavior Controls

  1. Add phase checkpoints for long Slack tasks.
  2. Require delegation or durable background execution for multi-deliverable builds.
  3. Enable hard stops for repeated failures.
  4. Keep the 150 limit during the first comparison window.

Week 1 — Measure

  1. Track 50+, 100+, 140+, and exhausted turns.
  2. Measure single-tool batch rate and tool-only streaks.
  3. Classify each high-call turn: productive, retrying, stalled, or misparsed.
  4. Compare completion and interruption rates.

Week 2 — Capacity Decision

  1. If productive tasks still hit the cap, raise to 300.
  2. If controls remain effective, evaluate 500.
  3. If serial drift persists, strengthen phase-yield rules instead of adding more budget.
  4. Keep one-click manual continuation for edge cases.

08 / Source Coverage

Internal And External Sources

Internal

ForgeFX Slack source thread and local Hermes state.db session/message records for the ForgeCAD turn.

Internal

Live ForgeBot configuration: Hermes v0.17.0, agent.max_turns: 150, compression at 70%, warning-only loop guardrails.

Internal

Installed Hermes source: conversation loop, iteration budget, turn finalizer, Codex Responses normalization.

External

Upstream GitHub evidence: #64434, #64764, #16068, and #67253.