hermes - 💡(How to fix) Fix [Bug]: send_message schema declares `required: []` but handler enforces `target`/`message` at runtime [4 pull requests]

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…

SEND_MESSAGE_SCHEMA in tools/send_message_tool.py declares no required parameters, but _handle_send() enforces target and message imperatively at runtime when action='send'. This means the model-side schema validator can't catch malformed calls — they only fail inside the tool body, surfacing as repeated [Tool loop warning: repeated_exact_failure_warning] entries in gateway logs.

Error Message

WARNING run_agent: Tool send_message returned error (0.00s): {"error": "Both 'target' and 'message' are required when action='send'"}

Root Cause

  • Errors that should be caught by schema validation surface as runtime tool failures + duplicate-call warnings — noisy and consumes tool-loop budget
  • Frontier models that do honor schema required are penalized for not getting that signal — they trust the schema and don't infer the imperative constraint
  • The fix is a 1-line schema change with no behavior regression (conditional requirement when action='send' can be modeled with JSON Schema if/then)

Fix Action

Fixed

RAW_BUFFERClick to expand / collapse

Summary

SEND_MESSAGE_SCHEMA in tools/send_message_tool.py declares no required parameters, but _handle_send() enforces target and message imperatively at runtime when action='send'. This means the model-side schema validator can't catch malformed calls — they only fail inside the tool body, surfacing as repeated [Tool loop warning: repeated_exact_failure_warning] entries in gateway logs.

Versions

  • Repo: NousResearch/hermes-agent main (verified at HEAD on 2026-05-26)
  • Image observed: nousresearch/hermes-agent digest sha256:b6e41c155d6bfce5ad83c5d0fec670086db8a43250e4511c9474134be5482d33

Where in source

tools/send_message_tool.py:

```python

lines 118-147

SEND_MESSAGE_SCHEMA = { "name": "send_message", ... "parameters": { "type": "object", "properties": { "action": { ... }, "target": { ... }, "message": { ... } }, "required": [] # ← nothing required at schema level } }

lines 171-174

target = args.get("target", "") message = args.get("message", "") if not target or not message: return tool_error("Both 'target' and 'message' are required when action='send'") ```

Repro

  1. Run an agent against this tool with a model that uses schema-side argument validation (any frontier model with strict tool-arg checks)

  2. Prompt the agent in a way that causes it to call `send_message` without a clear target (e.g., "send Vic a quick ping" with no platform mentioned and no `list` action context)

  3. Observe gateway log:

    ``` WARNING run_agent: Tool send_message returned error (0.00s): {"error": "Both 'target' and 'message' are required when action='send'"} [Tool loop warning: repeated_exact_failure_warning; count=4; send_message has failed 4 times with identical arguments.] WARNING run_agent: Removed duplicate tool call: send_message ```

  4. Note that the model retries the same malformed call multiple times before the tool-loop guard trips, because schema validation never blocked the call.

Why this matters

  • Errors that should be caught by schema validation surface as runtime tool failures + duplicate-call warnings — noisy and consumes tool-loop budget
  • Frontier models that do honor schema required are penalized for not getting that signal — they trust the schema and don't infer the imperative constraint
  • The fix is a 1-line schema change with no behavior regression (conditional requirement when action='send' can be modeled with JSON Schema if/then)

Proposed fix

The simplest change — list target and message as required, since they're already enforced imperatively:

```python "required": ["target", "message"] ```

This is technically more restrictive than the current behavior (it would block action='list' calls that omit target/message), so the surgical version uses if/then to keep list valid argument-free:

```python "required": ["action"], "allOf": [ { "if": { "properties": { "action": { "const": "send" } } }, "then": { "required": ["target", "message"] } } ] ```

Either form lets the model's argument validator catch the bad call upstream instead of paying for a runtime round-trip + duplicate-suppression.

Happy to PR

If a maintainer signals which form (flat-required vs if/then) you'd prefer, I'm happy to send a small PR.

Context

Found while triaging a recurring memory-cap symptom on a single-user, multi-agent Hermes deployment. Not a high-traffic bug but it shows up reliably whenever an agent constructs send_message without a clear delivery target from prior list/context.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING