Skip to content

fix: pass agentId per-call for integration-scoped memory#665

Open
chdlc wants to merge 1 commit into
rohitg00:mainfrom
chdlc:fix/pass-agentid-per-call
Open

fix: pass agentId per-call for integration-scoped memory#665
chdlc wants to merge 1 commit into
rohitg00:mainfrom
chdlc:fix/pass-agentid-per-call

Conversation

@chdlc
Copy link
Copy Markdown

@chdlc chdlc commented May 27, 2026

What

All integrations (Hermes, OpenClaw, MCP server) send write and search requests without agentId in the request body. This means all memories land with null agentId — effectively unscoped — even when the server has multi-agent isolation enabled.

Why

When multiple agents (e.g. Hermes + Cursor + OpenClaw) share a single agentmemory server, memories from all agents get mixed together because the server has no way to distinguish which agent owns each write. The AGENT_ID env var exists as a server-level setting, but integrations never injected their own identity into request bodies.

How

src/config.ts: loadAgentScope() reads AGENTMEMORY_AGENT_ID with fallback to AGENT_ID. This lets integrations define their own identity via AGENTMEMORY_AGENT_ID in their process env, while the server keeps using AGENT_ID as its default.

integrations/hermes/__init__.py: initialize() captures agent_id from kwargs["agent_identity"] (the Hermes profile name) with AGENTMEMORY_AGENT_ID env var as fallback, and passes it to:

  • session/start — tags the session
  • remember (memory_save + on_memory_write) — tags saved memories
  • observe (sync_turn) — tags turn observations

integrations/openclaw/plugin.mjs: Reads AGENTMEMORY_AGENT_ID from process env and forwards it in smart-search and observe calls.

src/mcp/server.ts: The standalone MCP server reads getAgentId() and forwards it automatically in memory_save and memory_smart_search. Any MCP client (Cursor, Claude Desktop, Cline, etc.) that sets AGENTMEMORY_AGENT_ID in its MCP config env gets correct agent tagging without modifying individual tool calls.

When no agent identity is available, no agentId field is sent — preserving legacy unscoped behavior.

Verification

  • All 116 test suites pass (1252 tests)
  • New tests cover AGENTMEMORY_AGENT_ID precedence, MCP forwarding, and OpenClaw forwarding
  • Existing tests remain passing
  • No new lifecycle hooks — manifests stay in sync

Summary by CodeRabbit

  • New Features

    • Clients can set AGENTMEMORY_AGENT_ID so agents include an agentId in memory service requests, enabling per-agent identification and optional isolation.
  • Documentation

    • Expanded multi-agent memory docs: how to set AGENTMEMORY_AGENT_ID, precedence vs legacy AGENT_ID, per-request overrides, and shared vs isolated behaviors.
  • Tests

    • Added/updated tests to verify agentId selection, forwarding, and plugin behavior (including length handling).

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

@chdlc 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
Contributor

coderabbitai Bot commented May 27, 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: 88ef085d-d9dd-4e6c-a79f-dc549f572112

📥 Commits

Reviewing files that changed from the base of the PR and between 04ad752 and f250372.

📒 Files selected for processing (8)
  • README.md
  • integrations/hermes/__init__.py
  • integrations/openclaw/plugin.mjs
  • src/config.ts
  • src/mcp/server.ts
  • test/agent-id-scope.test.ts
  • test/mcp-agent-id.test.ts
  • test/openclaw-plugin.test.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • test/openclaw-plugin.test.ts
  • src/config.ts
  • test/agent-id-scope.test.ts
  • integrations/hermes/init.py
  • README.md
  • integrations/openclaw/plugin.mjs
  • src/mcp/server.ts
  • test/mcp-agent-id.test.ts

📝 Walkthrough

Walkthrough

AgentMemory now prefers AGENTMEMORY_AGENT_ID (falling back to AGENT_ID) and conditionally forwards an agentId field in memory-related requests across Hermes, OpenClaw, and MCP flows; README and tests updated to cover sourcing, precedence, and forwarding behavior.

Changes

Agent ID propagation and tests

Layer / File(s) Summary
Agent scope loading and tests
src/config.ts, test/agent-id-scope.test.ts
loadAgentScope() reads AGENTMEMORY_AGENT_ID first (fallback to AGENT_ID); tests snapshot/clear/restore AGENTMEMORY_AGENT_ID and assert precedence.
MCP: include agentId in memory tool payloads
src/mcp/server.ts, test/mcp-agent-id.test.ts
Import getAgentId() and conditionally spread agentId into mem::remember (memory_save) and mem::smart-search (memory_smart_search) triggers; add Vitest tests that mock triggers and assert payload.agentId equals AGENTMEMORY_AGENT_ID.
Hermes integration: init and propagation
integrations/hermes/__init__.py
AgentMemoryProvider.initialize stores agent_identity/AGENTMEMORY_AGENT_ID; conditionally includes agentId in session/start, remember (memory_save), observe (sync_turn), and remember (on_memory_write for add/update).
OpenClaw plugin: env sourcing and request payloads
integrations/openclaw/plugin.mjs, test/openclaw-plugin.test.ts
Plugin reads AGENTMEMORY_AGENT_ID (trim/truncate) and conditionally includes it as agentId in /agentmemory/smart-search (before_agent_start) and /agentmemory/observe (agent_end); tests mock fetch and assert body.agentId matches env.
Docs: multi-agent memory
README.md
Document AGENTMEMORY_AGENT_ID usage in integration/MCP environments, precedence with AGENT_ID, details of shared vs isolated behavior, which fields are tagged, read filters and query params, and per-request overrides.

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • rohitg00/agentmemory#654: Adds agent scoping and getAgentId/loadAgentScope changes that this PR extends by prioritizing AGENTMEMORY_AGENT_ID and forwarding agentId through MCP and integrations.

"A rabbit hums to every call and trace,
Hiding an id in a tiny space,
Whiskers twitch, memories find their place,
Optional carrots, tagged with grace.
🐇✨"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% 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 accurately describes the main change: adding agentId forwarding across integrations for multi-agent memory scoping.
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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

@chdlc chdlc marked this pull request as draft May 27, 2026 15:45
@chdlc chdlc force-pushed the fix/pass-agentid-per-call branch 4 times, most recently from b83d692 to 04ad752 Compare May 27, 2026 18:28
@chdlc chdlc changed the title fix(hermes): pass agentId in request body for multi-agent isolation fix: pass agentId per-call for integration-scoped memory May 27, 2026
@chdlc chdlc marked this pull request as ready for review May 27, 2026 18:32
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
README.md (1)

1141-1188: ⚡ Quick win

Clarify the distinction between server default and per-client agent identity.

The documentation covers the technical details but mixes server-side configuration (AGENT_ID in ~/.agentmemory/.env) with client-side configuration (AGENTMEMORY_AGENT_ID in integration/MCP env) without clearly explaining why you'd use one vs the other. Consider restructuring this section to:

  1. Lead with the use case distinction before diving into examples:

    • AGENT_ID: Set once in the agentmemory server's ~/.agentmemory/.env when you run a single-role server (e.g., "architect" server)
    • AGENTMEMORY_AGENT_ID: Set per-client/integration when multiple clients with different roles share one agentmemory server (e.g., Hermes "architect", OpenClaw "reviewer", MCP "researcher" all connecting to the same server)
  2. Make precedence rules more prominent — the statement "If both AGENTMEMORY_AGENT_ID and AGENT_ID are present in the same process, AGENTMEMORY_AGENT_ID wins" (line 1172) is buried. Surface it earlier or in a callout.

  3. Clarify "When no agent id is set" (line 1187) — does this mean neither variable is set in any process, or just not set in a specific context? Be explicit: "When neither AGENT_ID nor AGENTMEMORY_AGENT_ID is set..."

  4. Group examples by deployment scenario rather than by variable:

    • "Single-role server" (just AGENT_ID)
    • "Multi-client shared server" (AGENTMEMORY_AGENT_ID per client)
    • "Per-request overrides" (body field in API calls)

This is documentation-only, so no runtime impact, but clearer structure reduces user confusion when choosing which variable to set.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 1141 - 1188, The docs mix server-side vs client-side
config—restructure the Multi-agent memory section to lead with use-case
distinction (explain AGENT_ID is the server default set in the agentmemory
server env for single-role deployments, and AGENTMEMORY_AGENT_ID is a
per-client/integration env when multiple clients share one server), surface the
precedence rule early (explicitly state “if both AGENTMEMORY_AGENT_ID and
AGENT_ID are present in the same process, AGENTMEMORY_AGENT_ID wins”), clarify
the “When no agent id is set” sentence to read “When neither AGENT_ID nor
AGENTMEMORY_AGENT_ID is set in a process…” and regroup examples into three clear
scenarios: Single-role server (AGENT_ID), Multi-client shared server
(AGENTMEMORY_AGENT_ID per client), and Per-request overrides (agentId field in
API requests).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/config.ts`:
- Around line 284-287: The current selection of AGENTMEMORY_AGENT_ID vs AGENT_ID
uses raw = env["AGENTMEMORY_AGENT_ID"] || env["AGENT_ID"], which treats
whitespace-only AGENTMEMORY_AGENT_ID as present and prevents falling back;
update the logic in the loadAgentScope/config block so you first read
AGENTMEMORY_AGENT_ID, trim it, and if the trimmed value is non-empty use it,
otherwise read and trim AGENT_ID and use that; finally enforce the 128-char
slice and null-return if the resulting agentId is empty. Reference the variables
raw and agentId (and the AGENTMEMORY_AGENT_ID / AGENT_ID env keys) to locate the
change.

---

Nitpick comments:
In `@README.md`:
- Around line 1141-1188: The docs mix server-side vs client-side
config—restructure the Multi-agent memory section to lead with use-case
distinction (explain AGENT_ID is the server default set in the agentmemory
server env for single-role deployments, and AGENTMEMORY_AGENT_ID is a
per-client/integration env when multiple clients share one server), surface the
precedence rule early (explicitly state “if both AGENTMEMORY_AGENT_ID and
AGENT_ID are present in the same process, AGENTMEMORY_AGENT_ID wins”), clarify
the “When no agent id is set” sentence to read “When neither AGENT_ID nor
AGENTMEMORY_AGENT_ID is set in a process…” and regroup examples into three clear
scenarios: Single-role server (AGENT_ID), Multi-client shared server
(AGENTMEMORY_AGENT_ID per client), and Per-request overrides (agentId field in
API requests).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ce334bcb-e586-49c7-b1d4-862cc7c84b35

📥 Commits

Reviewing files that changed from the base of the PR and between d7adeea and 04ad752.

📒 Files selected for processing (8)
  • README.md
  • integrations/hermes/__init__.py
  • integrations/openclaw/plugin.mjs
  • src/config.ts
  • src/mcp/server.ts
  • test/agent-id-scope.test.ts
  • test/mcp-agent-id.test.ts
  • test/openclaw-plugin.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • integrations/hermes/init.py

Comment thread src/config.ts Outdated
Read AGENTMEMORY_AGENT_ID as the integration-level agent identity,
with AGENT_ID kept as the server-level fallback.

Forward agentId from Hermes, OpenClaw, and the MCP server in write and
search calls so single-server multi-agent deployments can scope memory
per integration without modifying individual requests.

Add coverage for AGENTMEMORY_AGENT_ID precedence, MCP forwarding, and
OpenClaw forwarding.

Signed-off-by: Christian de la Cruz <chrisdlc119@outlook.com>
@chdlc chdlc force-pushed the fix/pass-agentid-per-call branch from 04ad752 to f250372 Compare May 27, 2026 20:10
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