Skip to content

fix(hermes): wrong JSON keys in sync_turn cause empty auto-compressed observations#384

Open
grodingo wants to merge 1 commit into
rohitg00:mainfrom
grodingo:fix/hermes-plugin-key-mismatch
Open

fix(hermes): wrong JSON keys in sync_turn cause empty auto-compressed observations#384
grodingo wants to merge 1 commit into
rohitg00:mainfrom
grodingo:fix/hermes-plugin-key-mismatch

Conversation

@grodingo
Copy link
Copy Markdown

@grodingo grodingo commented May 15, 2026

Problem

The Hermes plugin's sync_turn() sends conversation observations to the /agentmemory/observe endpoint with keys "input" and "output":

# integrations/hermes/__init__.py:345-348
"data": {
    "tool_name": "conversation",
    "input": user[:500],
    "output": assistant[:2000],
},

However, the server's mem::observe handler (in src/functions/observe.ts) extracts observation data using "tool_input" and "tool_output":

raw.toolName = d["tool_name"];
raw.toolInput = d["tool_input"];    // ← expects "tool_input"
raw.toolOutput = d["tool_output"];  // ← expects "tool_output"

This is consistent with how the Claude Code hooks (dist/hooks/post-tool-use.mjs) send data:

data: {
    tool_name: data.tool_name,
    tool_input: data.tool_input,
    tool_output: truncate(cleanOutput, 8e3),
}

Impact

Since raw.toolInput and raw.toolOutput are always undefined, the compression prompt built by buildCompressionPrompt() (in src/prompts/compression.ts) contains only the timestamp, hookType, and toolName="conversation". The LLM receives no actual content and produces generic, useless observations:

title: "Agent initiated conversation"
narrative: "No specific content was provided"
importance: 1
facts: []
concepts: []

Every conversation turn produces identical garbage, polluting the memory store and making injected context useless (the mem::context function serves these empty observations back into the agent's prompt).

Fix

Rename the keys to match what the server expects:

"data": {
    "tool_name": "conversation",
    "tool_input": user[:500],
    "tool_output": assistant[:2000],
},

Verification

Tested locally with agentmemory v0.9.12 + DeepSeek deepseek-v4-flash as the compression LLM. After the fix, the same observation payload produces:

type: discovery
title: "Verified fix for agentmemory plugin key naming"
subtitle: "Renamed input/output to tool_input/tool_output"
importance: 6
narrative: "The conversation confirms that the agentmemory plugin fix has been applied..."
facts: ["The fix in __init__.py lines 415-416 replaces ..."]
concepts: ["agentmemory plugin", "tool_input/tool_output key renaming"]

Summary by CodeRabbit

  • Bug Fixes
    • Updated payload field names in the Hermes integration for improved clarity and consistency in tool interaction handling.

Review Change Stack

The Hermes plugin's sync_turn() method sends conversation observations
to the agentmemory /observe endpoint using keys 'input' and 'output',
but the server's mem::observe handler extracts data using 'tool_input'
and 'tool_output' (see src/functions/observe.ts).

This key mismatch means raw.toolInput and raw.toolOutput are always
undefined. When auto-compress is enabled, the LLM receives a nearly
empty compression prompt (only timestamp + hookType + toolName), which
produces generic, useless observations like:

  title: "Agent initiated conversation"
  narrative: "No specific content was provided"
  importance: 1

With the corrected keys, DeepSeek/Vision models receive the actual
conversation content and produce meaningful, structured observations:

  title: "Verified fix for agentmemory plugin key naming"
  importance: 6
  concepts: ["agentmemory plugin", "tool_input/tool_output key renaming"]
  facts: ["The fix replaces 'input'/'output' keys with..."]
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

@grodingo is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 688521c9-5435-4a15-a8bb-91e112560af7

📥 Commits

Reviewing files that changed from the base of the PR and between 4b354b7 and 5c0ee3b.

📒 Files selected for processing (1)
  • integrations/hermes/__init__.py

📝 Walkthrough

Walkthrough

AgentMemoryProvider.sync_turn() in the Hermes integration updates the payload sent to the observe endpoint by renaming conversation fields from input/output to tool_input/tool_output while maintaining the same truncation logic (user[:500] and assistant[:2000]).

Changes

Observe endpoint field names

Layer / File(s) Summary
Observe payload field renaming
integrations/hermes/__init__.py
The observe request body in sync_turn() switches serialized conversation fields from input/output to tool_input/tool_output with identical truncation behavior for user and assistant turns.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Possibly related PRs

  • rohitg00/agentmemory#107: Introduced the Hermes plugin's sync_turn implementation that this PR now modifies.
  • rohitg00/agentmemory#252: Also modifies integrations/hermes/__init__.py's AgentMemoryProvider.sync_turn(), updating how the observe request is constructed.

Poem

🐰 A field renamed with care and grace,
tool_input finds its rightful place,
tool_output takes the other side,
Truncation holds its steady stride!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main change: fixing wrong JSON keys ('input'/'output' → 'tool_input'/'tool_output') in sync_turn that caused auto-compression observations to be empty.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

1 participant