Skip to content

fix(agent): preserve final_response on failure returns - #56176

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-c48666d6
Jul 1, 2026
Merged

fix(agent): preserve final_response on failure returns#56176
teknium1 merged 1 commit into
mainfrom
hermes/hermes-c48666d6

Conversation

@teknium1

@teknium1 teknium1 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

AIAgent.run_conversation() now returns an actionable final_response on every terminal-failure branch, so callers that index result["final_response"] directly surface the real error instead of crashing with a KeyError.

Root cause: run_conversation() promises a dict with final_response, but 16 failure branches violated that contract — 8 omitted the key entirely, 8 set it to literal None. run_agent.py's chat() (result["final_response"]) and the __main__ printer index it directly, turning a real provider/context failure into an opaque KeyError: 'final_response'. The original report: a MeshBoard worker exited with hermes -z: agent failed: 'final_response' after upstream stream drops + 400/502s.

Changes

  • agent/conversation_loop.py: all 16 offending terminal-failure returns now set final_response to the same actionable text already present in error (invalid-response retry exhaustion, stream-drop/truncation, 413 payload + context-compression exhaustion, max_tokens-over-cap, incomplete REASONING_SCRATCHPAD, Codex incomplete, invalid tool call). Every branch already carried usable error text — this mirrors it into final_response.
  • tests/run_agent/test_run_agent.py: AST regression test that fails if any run_conversation() dict return omits final_response or sets it to a literal None; tightens the invalid-response test to assert final_response == error.
  • scripts/release.py: AUTHOR_MAP entry for the contributor.

Validation

Before After
run_conversation() failure-branch contract 8 omit final_response, 8 return None all 16 carry actionable text
Direct-index caller on failure KeyError: 'final_response' returns error string
tests/run_agent/test_run_agent.py 412 passed
tests/run_agent/test_413_compression.py 25 passed
E2E (real AIAgent, forced retry exhaustion) final_response == error, non-None str

Salvage of #39345 by @OmarB97 — his fix approach and AST regression test reapplied to current main (line numbers had drifted ~4 months); authorship preserved.

Infographic

System 7 style infographic

@teknium1
teknium1 force-pushed the hermes/hermes-c48666d6 branch from 2675fd4 to 025eafc Compare July 1, 2026 08:30
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Jul 1, 2026
@teknium1
teknium1 force-pushed the hermes/hermes-c48666d6 branch 2 times, most recently from 86cf697 to c80f024 Compare July 1, 2026 08:53
AIAgent.run_conversation() promises a dict with final_response, but 16
terminal-failure branches returned dicts that either omitted the key or
set it to None. Callers that index result['final_response'] directly
(run_agent.py chat() + the __main__ printer) turn a real provider/context
failure into an opaque KeyError instead of surfacing the actionable error.

Every offending branch already carried usable 'error' text, so this
mirrors that text into final_response for all 16 sites (8 that omitted the
key, 8 that returned None). Adds an AST regression test that fails if any
run_conversation() dict return omits final_response or sets it to a literal
None, and tightens the invalid-response test to assert final_response == error.
@teknium1
teknium1 force-pushed the hermes/hermes-c48666d6 branch from c80f024 to b4f71a9 Compare July 1, 2026 08:54
@teknium1
teknium1 merged commit 053424c into main Jul 1, 2026
31 checks passed
@teknium1
teknium1 deleted the hermes/hermes-c48666d6 branch July 1, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants