Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hermes_cli/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ def get_bundled_plugins_dir() -> Path:
"post_tool_call",
"transform_terminal_output",
"transform_tool_result",
# Transform LLM output before it's returned to the user.
# Plugins return a string to replace the response text, or None/empty to leave unchanged.
# First non-None string wins. Useful for vocabulary/personality transformation.
"transform_llm_output",
"pre_llm_call",
"post_llm_call",
"pre_api_request",
Expand Down
21 changes: 21 additions & 0 deletions run_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -14035,6 +14035,27 @@ def _stop_spinner():
else:
logger.info(_diag_msg, *_diag_args)

# Plugin hook: transform_llm_output
# Fired once per turn after the tool-calling loop completes.
# Plugins can transform the LLM's output text before it's returned.
# First hook to return a string wins; None/empty return leaves text unchanged.
if final_response and not interrupted:
try:
from hermes_cli.plugins import invoke_hook as _invoke_hook
_transform_results = _invoke_hook(
"transform_llm_output",
response_text=final_response,
session_id=self.session_id or "",
model=self.model,
platform=getattr(self, "platform", None) or "",
)
for _hook_result in _transform_results:
if isinstance(_hook_result, str) and _hook_result:
final_response = _hook_result
break # First non-empty string wins
except Exception as exc:
logger.warning("transform_llm_output hook failed: %s", exc)

# Plugin hook: post_llm_call
# Fired once per turn after the tool-calling loop completes.
# Plugins can use this to persist conversation data (e.g. sync
Expand Down
Loading