Skip to content

[Bug]: Background review ignores terminal failed results and can end silently incomplete #61962

Description

@whyhkzk

Bug Description

agent/background_review.py calls review_agent.run_conversation(...) but discards the return value. The conversation loop reports terminal failures (content-policy rejection, context/payload overflow, Ollama runtime-context too small, etc.) by returning a dict with failed: true — it does not necessarily raise.

The review fork also sets suppress_status_output = True and runs inside thread_scoped_silence(), so the conversation loop's own failure messages are intentionally hidden. The discarded result is therefore the only signal, and the failure itself is never surfaced.

Two consequences:

  • If no memory/skill action completed before the failure, the user sees nothing at all.
  • If earlier tool calls already committed writes, Hermes prints the successful-action summary without disclosing that the review ended incomplete.

Orthogonal to #54115 / PR #54255: those concern foreground and review slots sharing one n_ctx on a single local inference server, and guard the pre-spawn path. This is about the caller ignoring a terminal result, on every provider and every code path.

Observed on main at commit a0032f5f9.

Steps to Reproduce

No provider credentials, model download, or platform-specific runtime required.

  1. Make review_agent.run_conversation() return a terminal failure instead of raising. Any of the loop's failed: true shapes reproduces it; the one the review fork actually reaches is context overflow, because the fork sets compression_enabled = False:

    {
        "failed": True,
        "compaction_disabled": True,
        "error": "Context overflow and auto-compaction is disabled ...",
    }
  2. Optionally leave a successful memory or skill_manage tool result in review_agent._session_messages before returning the failure.

  3. Observe _run_review_in_thread() run to completion without ever calling _emit_auxiliary_failure(). With step 2, the user sees only the successful-action summary and no indication the review ended early.

On a live setup the overflow needs more than a merely long conversation — _compute_threshold_tokens() already reserves the output allowance and triggers foreground compaction at a fraction of context_length - max_tokens (75% for windows under 512K, 85% once that budget falls to 64K or below), so the snapshot handed to the review normally sits below the threshold with headroom. The overflow is reached when that headroom is consumed anyway: a small context window, a foreground compression cooldown, a shared n_ctx on a local server, or the review fork's own ≤16 tool iterations growing the request. The reporting defect does not depend on any of that — it applies to every failed: true shape the loop can return.

Expected Behavior

  • Treat result.get("failed") as a terminal, user-visible auxiliary failure.
  • Do not raise at the run_conversation() boundary — earlier successful memory/skill writes are real and must still be summarized.
  • After delivering any partial-action summary, emit the auxiliary failure warning.
  • Derive the warning from error, falling back to final_response: failures that break out of the tool loop and fall through finalize_turn() carry no error key at all.
  • For the fork's intentional compression_enabled = False overflow, the warning should not recommend /compress or changing foreground compression.enabled — those cannot repair an already-failed isolated review.
  • Preserve existing behavior for the successful path and for iteration-budget exhaustion (which does not set failed).

Actual Behavior

The return value of run_conversation() is never inspected. Only raised exceptions reach the outer handler that calls _emit_auxiliary_failure(). Terminal failures returned as data are silent, or appear as an unqualified partial success.

Affected Component

Agent Core (conversation loop, context compression, memory)

Messaging Platform (if gateway-related)

All. The defect is in the shared background-review path; both CLI printing and gateway callback delivery are affected.

Debug Report

Not collected. Deterministic control-flow defect — no provider credentials,
model download, or platform-specific runtime required.

main            a0032f5f9
file            agent/background_review.py (blob 3f4e5efcd)
failing path    _run_review_in_thread() -> run_conversation() -> discarded result

Operating System

Windows 11 (defect is OS-independent)

Python Version

3.14.3

Hermes Version

0.18.2

Additional Logs / Traceback (optional)

None. There is no traceback: the failure is returned as data, not raised.

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/agentCore agent runtime: loop, agent_init, prompt builder, context-compression, responses endpointtype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions