Bug Description
The tool-loop guardrails (agent/tool_guardrails.py) key their repetition tracking on the tool-call signature (tool name + canonical args) or on classified failure. Two loop shapes slip through both:
- Varying-args / fixed-result loop. A tool call that "succeeds" with different arguments on every call but keeps returning the same blocked/empty/error-page body. For ex.
execute_code wrapping a web fetch against a source that consistently 404s or soft-blocks a scraper. The exact-failure counter never fires (failed is false), and the _no_progress tracker is keyed by signature and scoped to an idempotent-tool allowlist, so it never sees the loop either.
- Repeated multimodal results. A vision tool result of shape
{"_multimodal": True, "content": [...]} embeds a base64 image payload, so str(result) is unique on every call even when the meaningful content (a placeholder caption like "Image loaded into your context") is identical. Repetition is never detected.
Observed running a local model (qwen3.6-35b) in unattended/gateway sessions: one session burned its iteration budget re-fetching the same blocked page with slightly different arguments; another re-loaded the same image via a vision tool 6 times with zero guard activity.
Steps to Reproduce
- Enable tool-loop guardrails (defaults are fine; optionally
hard_stop_enabled: true).
- Have the agent call a tool that returns the same substantial error/blocked-page body regardless of arguments (e.g. fetch a URL that always serves the same 404/soft-block page), with the model varying the query args each attempt.
- Watch the loop run past every configured threshold with no warning appended to the tool results.
- Variant: have the agent load the same image via a vision/multimodal tool repeatedly - same outcome.
Expected Behavior
After N calls returning substantially identical content, the guardrails should treat it like the other repetition axes: append a soft warning to the tool result, and (when hard_stop_enabled) halt the loop at a higher threshold.
Actual Behavior
No guard fires at any point; the loop only ends when the iteration budget runs out.
Affected Component
Agent Core (conversation loop, context compression, memory)
Messaging Platform (if gateway-related)
No response
Debug Report
Not attaching "hermes debug share" links for this one: it's a code-level behavior
gap in agent/tool_guardrails.py, fully reproducible from unit tests and not
environment-specific, and my recent logs contain private gateway-session content.
Confirmed the gap still exists on current main by inspection — there is no
repetition tracking keyed on result content, only on call signature and
classified failure. Happy to share specific redacted log excerpts on request.
System info (from "hermes debug share --local"):
version: 0.18.0 (2026.7.1)
os: Darwin 25.4.0 arm64 (macOS 15, Apple Silicon)
python: 3.11.15
openai_sdk: 2.24.0
provider: lmstudio (local OpenAI-compatible endpoint)
model: Qwen3.6-35B-A3B-MLX-8bit
toolsets: hermes-cli
memory: built-in
gateway: telegram
Operating System
macOS 15
Python Version
3.11.15
Hermes Version
0.18.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
No response
Are you willing to submit a PR for this?
Bug Description
The tool-loop guardrails (
agent/tool_guardrails.py) key their repetition tracking on the tool-call signature (tool name + canonical args) or on classified failure. Two loop shapes slip through both:execute_codewrapping a web fetch against a source that consistently 404s or soft-blocks a scraper. The exact-failure counter never fires (failedis false), and the_no_progresstracker is keyed by signature and scoped to an idempotent-tool allowlist, so it never sees the loop either.{"_multimodal": True, "content": [...]}embeds a base64 image payload, sostr(result)is unique on every call even when the meaningful content (a placeholder caption like "Image loaded into your context") is identical. Repetition is never detected.Observed running a local model (qwen3.6-35b) in unattended/gateway sessions: one session burned its iteration budget re-fetching the same blocked page with slightly different arguments; another re-loaded the same image via a vision tool 6 times with zero guard activity.
Steps to Reproduce
hard_stop_enabled: true).Expected Behavior
After N calls returning substantially identical content, the guardrails should treat it like the other repetition axes: append a soft warning to the tool result, and (when
hard_stop_enabled) halt the loop at a higher threshold.Actual Behavior
No guard fires at any point; the loop only ends when the iteration budget runs out.
Affected Component
Agent Core (conversation loop, context compression, memory)
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
macOS 15
Python Version
3.11.15
Hermes Version
0.18.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
No response
Are you willing to submit a PR for this?