hermes - 💡(How to fix) Fix [Bug]: /goal can spam repeated completion messages when goal_judge errors fail-open to continue

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

A persistent /goal loop can spam a gateway channel with repeated near-identical "Goal is complete / I'm stopping" messages when the assistant has reached a terminal answer but the goal judge fails with an API/transport error. The current fail-open behavior treats judge errors as continue, so the goal loop immediately queues another continuation prompt; the agent then repeats the same terminal completion message, and this can happen repeatedly in Discord/Telegram/etc.

This is different from false-positive goal completion (#18421) and explicit-incomplete completion (#26986): here the assistant is explicitly trying to stop, but the judge cannot evaluate and the loop keeps driving more turns.

Error Message

In a gateway session, the same completion message was sent repeatedly every few seconds, e.g. variants of:

Root Cause

I'm stopping here because the requested goal is complete.

Code Example

Goal is complete.

The requested artifact is already done and saved at:

/path/to/generated_artifact.md

I'm stopping here because the requested goal is complete.

---

{
  "status": "cleared",
  "turns_used": 16,
  "max_turns": 20,
  "last_verdict": "continue",
  "last_reason": "judge error: BadRequestError",
  "consecutive_parse_failures": 0
}

---

return "continue", f"judge error: {type(exc).__name__}", False

---

# hermes_cli/goals.py
except Exception as exc:
    logger.info("goal judge: API call failed (%s) — falling through to continue", exc)
    return "continue", f"judge error: {type(exc).__name__}", False
RAW_BUFFERClick to expand / collapse

Summary

A persistent /goal loop can spam a gateway channel with repeated near-identical "Goal is complete / I'm stopping" messages when the assistant has reached a terminal answer but the goal judge fails with an API/transport error. The current fail-open behavior treats judge errors as continue, so the goal loop immediately queues another continuation prompt; the agent then repeats the same terminal completion message, and this can happen repeatedly in Discord/Telegram/etc.

This is different from false-positive goal completion (#18421) and explicit-incomplete completion (#26986): here the assistant is explicitly trying to stop, but the judge cannot evaluate and the loop keeps driving more turns.

Observed behavior

In a gateway session, the same completion message was sent repeatedly every few seconds, e.g. variants of:

Goal is complete.

The requested artifact is already done and saved at:

/path/to/generated_artifact.md

I'm stopping here because the requested goal is complete.

The persisted goal state showed that the goal had not been marked done by the judge:

{
  "status": "cleared",
  "turns_used": 16,
  "max_turns": 20,
  "last_verdict": "continue",
  "last_reason": "judge error: BadRequestError",
  "consecutive_parse_failures": 0
}

The assistant messages in the same session contained many repeated terminal responses pointing to the same generated artifact path.

Expected behavior

If the goal judge errors while the assistant's latest response is explicitly terminal (e.g. "Goal is complete", "I'm stopping here", "requested goal is complete"), Hermes should not blindly continue the /goal loop and spam the messaging platform.

At minimum one of these should happen:

  1. Pause the goal with a user-visible notice such as "goal judge errored; assistant appears to have stopped/completed, pausing to avoid spam".
  2. Treat terminal completion phrasing as a safe stop condition only when the judge is unavailable.
  3. Detect repeated near-identical final responses and auto-pause after 1-2 repeats.
  4. Suppress repeated duplicate gateway deliveries from goal continuations.

Actual behavior

judge_goal() catches exceptions and returns:

return "continue", f"judge error: {type(exc).__name__}", False

Then GoalManager.evaluate_after_turn() keeps the state active and returns should_continue=True as long as the turn budget has not been exhausted. The continuation prompt asks the agent to continue or stop if complete, so the agent repeatedly replies with a terminal completion message, but the judge keeps failing open to continue.

Likely root cause area

  • hermes_cli/goals.py::judge_goal() exception path
  • hermes_cli/goals.py::GoalManager.evaluate_after_turn() handling for last_reason like judge error: BadRequestError
  • Gateway post-turn goal continuation paths that queue the next turn when decision["should_continue"] is true

Relevant code shape:

# hermes_cli/goals.py
except Exception as exc:
    logger.info("goal judge: API call failed (%s) — falling through to continue", exc)
    return "continue", f"judge error: {type(exc).__name__}", False

Suggested fix

Add a spam-safe fallback before returning should_continue=True on judge API errors:

  • Detect explicit terminal phrases in last_response, e.g.:
    • goal is complete
    • requested goal is complete
    • i'm stopping
    • i am stopping here
    • stopping because .* complete
  • If the judge errored and the response is terminal, set status to paused (or done, if maintainers prefer) with paused_reason="goal judge error after terminal assistant response".
  • Add regression coverage for:
    1. judge raises BadRequestError/generic exception;
    2. assistant response says "Goal is complete... I'm stopping...";
    3. evaluate_after_turn() returns should_continue=False and does not queue another continuation;
    4. non-terminal responses still fail open to continue as today.

A second defense-in-depth guard could detect repeated near-identical final responses in a goal loop and pause, even if the text does not match the explicit phrase list.

Impact

  • Gateway users can receive repeated spam messages in Discord/Telegram/etc.
  • The loop consumes model calls until max goal turns are exhausted or the user manually interrupts/clears the goal.
  • The behavior is confusing because the assistant says it is stopping, but the outer goal controller keeps restarting it.

Related issues

  • #18421 — /goal judge false positive when assistant claims file created but write failed
  • #26986 — keep persistent goals active when the response explicitly reports incomplete work

This issue is the inverse operational failure: assistant response is terminal, but judge errors fail-open to continue and causes repeated terminal-message spam.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

If the goal judge errors while the assistant's latest response is explicitly terminal (e.g. "Goal is complete", "I'm stopping here", "requested goal is complete"), Hermes should not blindly continue the /goal loop and spam the messaging platform.

At minimum one of these should happen:

  1. Pause the goal with a user-visible notice such as "goal judge errored; assistant appears to have stopped/completed, pausing to avoid spam".
  2. Treat terminal completion phrasing as a safe stop condition only when the judge is unavailable.
  3. Detect repeated near-identical final responses and auto-pause after 1-2 repeats.
  4. Suppress repeated duplicate gateway deliveries from goal continuations.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING