Skip to content

fix(api): send tool progress as custom SSE event to prevent model corruption#7500

Merged
teknium1 merged 1 commit into
mainfrom
salvage/bucket-o
Apr 11, 2026
Merged

fix(api): send tool progress as custom SSE event to prevent model corruption#7500
teknium1 merged 1 commit into
mainfrom
salvage/bucket-o

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Tool progress markers (⏰ terminal, 🔍 web_search) were injected directly into delta.content chunks in the SSE stream. OpenAI-compatible frontends (Open WebUI, LobeChat, LibreChat) store delta.content verbatim as assistant messages and send them back — polluting conversation history and potentially causing models to imitate the markers instead of calling tools.

Sends tool progress as custom event: hermes.tool.progress SSE events instead. Per SSE spec, clients that don't understand custom events silently ignore them. Clients that do can render them as progress UI.

Changes

  • gateway/platforms/api_server.py: _on_tool_progress pushes tagged tuples, new _emit() helper routes to custom SSE event
  • tests/gateway/test_api_server.py: Tests verify markers appear as custom events and do NOT leak into delta.content

Test results

106 API server tests passing

Salvaged from #7014 (@Bartok9). Fixes #6972.

…ruption (#6972)

Tool progress markers (e.g. `⏰ list`) were injected directly into
SSE delta.content chunks. OpenAI-compatible frontends (Open WebUI,
LobeChat, etc.) store delta.content verbatim as the assistant message
and send it back on subsequent requests. After enough turns, the model
learns to emit these markers as plain text instead of issuing real tool
calls — silently hallucinating tool results without ever running them.

Fix: Send tool progress as a custom `event: hermes.tool.progress` SSE
event instead of mixing it into delta.content. Per the SSE spec, clients
that don't understand a custom event type silently ignore it, so this is
backward-compatible. Frontends that want to render progress indicators
can listen for the custom event without persisting it to conversation
history.

The /v1/runs endpoint already uses structured events — this aligns the
/v1/chat/completions streaming path with the same principle.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Tool progress markers in SSE content corrupt model behavior over time (Open WebUI / OpenAI-compatible API)

1 participant