Skip to content

fix(agent): filter malformed tool calls before persistence and replay#5071

Open
giwaov wants to merge 1 commit into
NousResearch:mainfrom
giwaov:fix/filter-malformed-tool-calls
Open

fix(agent): filter malformed tool calls before persistence and replay#5071
giwaov wants to merge 1 commit into
NousResearch:mainfrom
giwaov:fix/filter-malformed-tool-calls

Conversation

@giwaov

@giwaov giwaov commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

What changed and why

Hermes could persist malformed assistant tool calls (empty \ unction.name, empty \ unction.arguments) into the SQLite session database. Once persisted, these invalid entries were replayed on every subsequent request in that session, causing repeated HTTP 400 errors from strict OpenAI-compatible providers:

\
HTTP 400: InternalError.Algo.InvalidParameter: The function.arguments parameter of the code model must be in JSON format.
\\

Fix

Added validation in two places:

  1. **_flush_messages_to_session_db**: Skip tool calls with falsy
    ame\ or \�rguments\ before writing to the database. Handles both the \ ool_calls\ attribute path (raw API response objects) and the dict path (pre-normalized messages). If all tool calls in a message are invalid, \ ool_calls_data\ is set to \None\ so the row is written cleanly.

  2. **_sanitize_api_messages**: Strip malformed tool calls from assistant messages before every API call. This protects sessions that were already poisoned by older versions. Handles both flat dict format (
    ame/\�rguments\ at top level) and nested format (\ unction.name/\ unction.arguments).

How to test

  1. Resume a session that has a malformed tool call stored in its history (empty name or empty arguments)
  2. Send a new message
  3. Verify the request succeeds without HTTP 400 errors - the malformed entries are silently dropped

Platform tested

Windows 11

Related issue

Closes #4662

Drop tool calls with empty function names or empty arguments before
persisting assistant messages to the session database and before replaying
stored history to the LLM provider. Previously, malformed tool calls (e.g.
empty name/arguments from edge-case provider responses) could be written to
SQLite and then replayed on every subsequent request in that session,
causing repeated HTTP 400 errors from strict OpenAI-compatible providers.

The fix adds validation in two places:
- _flush_messages_to_session_db: skip tool calls with falsy name or arguments
  before writing to the database.
- _sanitize_api_messages: strip malformed tool calls from assistant messages
  before every API call, protecting sessions that were already poisoned.

Closes NousResearch#4662
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #14407 — same malformed-tool-call validation fix for #4662. Both add validation in flush + sanitize paths.

1 similar comment
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #14407 — same malformed-tool-call validation fix for #4662. Both add validation in flush + sanitize paths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Malformed persisted tool calls can poison a session and cause repeated 400 errors on subsequent requests

2 participants