hermes - 💡(How to fix) Fix Proposal: add transform_interim_output hook for interim assistant commentary

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…

This proposes an additive plugin hook named transform_interim_output for assistant-authored interim/pre-tool commentary before gateway delivery.

The existing transform_llm_output hook works for final assistant output, but interim commentary emitted during a turn can bypass it and go directly to the gateway commentary/status delivery path. A narrow interim-output hook would let plugins transform display text for this surface without mutating conversation history, adapter metadata, routing, credentials, or provider behavior.

Error Message

  • Hook exception logs and delivers original text.

Root Cause

  • Inside gateway/run.py:_interim_assistant_cb.
  • Immediately before _stream_consumer.on_commentary(text) for commentary streaming.
  • Immediately before _status_adapter.send(..., text, ...) for status-adapter fallback.
  • Not on already_streamed=True segment-break-only delivery, because no new text is emitted.

Fix Action

Code Example

transform_interim_output

---

{
    "text": str,
    "surface": "commentary" | "status",
    "session_id": str,
    "model": str,
    "platform": str,
    "already_streamed": bool,
}
RAW_BUFFERClick to expand / collapse

Summary

This proposes an additive plugin hook named transform_interim_output for assistant-authored interim/pre-tool commentary before gateway delivery.

The existing transform_llm_output hook works for final assistant output, but interim commentary emitted during a turn can bypass it and go directly to the gateway commentary/status delivery path. A narrow interim-output hook would let plugins transform display text for this surface without mutating conversation history, adapter metadata, routing, credentials, or provider behavior.

Problem

Current plugin hooks include transform_llm_output, pre_llm_call, and post_llm_call, but there is no supported transform hook for interim/commentary/status-output text.

Observed source path in Hermes Agent v0.14.0:

  • hermes_cli/plugins.py defines VALID_HOOKS without an interim/commentary/status-output transform hook.
  • run_agent.py:_emit_interim_assistant_message emits visible interim assistant text through interim_assistant_callback.
  • gateway/run.py:_interim_assistant_cb routes that text to StreamConsumer.on_commentary(text) or _status_adapter.send(..., text, ...).
  • run_agent.py invokes transform_llm_output only later for the final response.

As a result, plugins that safely transform final display text have no supported way to cover real interim assistant commentary.

Proposed hook

Hook name:

transform_interim_output

Invocation point:

  • Inside gateway/run.py:_interim_assistant_cb.
  • Immediately before _stream_consumer.on_commentary(text) for commentary streaming.
  • Immediately before _status_adapter.send(..., text, ...) for status-adapter fallback.
  • Not on already_streamed=True segment-break-only delivery, because no new text is emitted.

Proposed kwargs:

{
    "text": str,
    "surface": "commentary" | "status",
    "session_id": str,
    "model": str,
    "platform": str,
    "already_streamed": bool,
}

Return contract:

  • None means unchanged.
  • Empty string means unchanged.
  • First non-empty str return value replaces text.
  • Non-string returns are ignored.
  • Exceptions fail open: log the hook failure and deliver the original text.

This mirrors the current final-output transform behavior while keeping existing plugins safe by default.

Boundaries

The hook should only transform outgoing interim display text.

It should not:

  • mutate conversation history
  • mutate session_id, model, platform, chat routing, adapter metadata, or send timing
  • expose chat IDs, user IDs, auth metadata, tokens, cookies, environment values, provider credentials, or adapter-private metadata
  • send Telegram or any other platform message from inside the hook
  • run slash commands, tools, local models, provider calls, or network calls from inside the hook

Protected-token expectations

Plugins using this hook should preserve:

  • fenced code blocks, inline code, and language tags
  • slash commands such as /new, /start, and /sethome
  • filesystem paths
  • URLs and Markdown link destinations
  • JSON/YAML keys and values
  • provider and model names
  • command names and command output literals
  • opaque IDs, hashes, timestamps, and status tokens
  • Markdown table fences and indentation

If a plugin cannot prove preservation, it should return None.

Suggested tests

  • VALID_HOOKS includes transform_interim_output.
  • No registered hook leaves stream commentary unchanged.
  • No registered hook leaves status-adapter fallback unchanged.
  • Hook returning None leaves text unchanged.
  • Hook returning "" leaves text unchanged.
  • First non-empty string return replaces text exactly once.
  • Hook exception logs and delivers original text.
  • already_streamed=True creates only a segment break and does not duplicate transformed text.
  • Existing transform_llm_output final-response behavior remains unchanged.
  • Disabled or absent plugins leave interim text unchanged.

Patch sketch

A non-applied patch sketch is available here:

https://github.com/ichichuang/Hermes-Agent/blob/593d11f156dcedc3ca8be5e15cbf54f1be86af6c/docs/ai-plan/LANG-M24-draft-core-hook.patch

Full proposal notes are here:

https://github.com/ichichuang/Hermes-Agent/blob/593d11f156dcedc3ca8be5e15cbf54f1be86af6c/docs/ai-plan/LANG-M24-upstream-interim-output-hook-pr-prep.md

Rationale

This keeps the change additive and narrowly scoped:

  • no behavior change when no plugin registers the hook
  • no local runtime monkeypatching
  • no site-packages-only production dependency
  • no prompt-layer workaround
  • no provider/model/config/credential changes
  • final-output transform_llm_output remains unchanged

If maintainers agree with the direction, I can convert the sketch into a focused PR with tests.

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

hermes - 💡(How to fix) Fix Proposal: add transform_interim_output hook for interim assistant commentary