Skip to content
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1458,34 +1458,35 @@ AGENTMEMORY_COMPRESS_MODEL=your-cheap-compression-model

Sources: [OpenRouter pricing for Sonnet 4.6](https://openrouter.ai/anthropic/claude-sonnet-4.6/pricing), [DeepSeek V4 Pro](https://openrouter.ai/deepseek/deepseek-v4-pro), [DeepSeek pricing notes](https://api-docs.deepseek.com/quick_start/pricing/).

### Multi-agent memory (`AGENT_ID` + `AGENTMEMORY_AGENT_SCOPE`)
### Multi-agent memory (`AGENTMEMORY_AGENT_ID` / `AGENT_ID` + `AGENTMEMORY_AGENT_SCOPE`)

In multi-agent setups where several roles share one agentmemory server (architect / developer / reviewer / researcher / support-agent), `AGENT_ID` tags every write with the role that made it. `AGENTMEMORY_AGENT_SCOPE` controls whether recall filters by that tag.
In multi-agent setups where several roles share one agentmemory server (architect / developer / reviewer / researcher / support-agent), `AGENTMEMORY_AGENT_ID` tags writes from an integration or MCP client with the role that made them. Legacy `AGENT_ID` remains supported as the server-level fallback. `AGENTMEMORY_AGENT_SCOPE` controls whether recall filters by that tag.

```env
TEAM_ID=company
USER_ID=engineering-team
AGENTMEMORY_USER_ID=alice
AGENT_ID=architect
AGENTMEMORY_AGENT_ID=architect
AGENTMEMORY_AGENT_SCOPE=isolated # optional; default "shared"
```

If both `AGENTMEMORY_AGENT_ID` and `AGENT_ID` are set, `AGENTMEMORY_AGENT_ID` wins. Use that in integration or MCP-client environments so one shared server can keep its own default `AGENT_ID` while each client still tags requests with its role.

Two modes:

| Mode | Tag writes | Filter recall | When to use |
|------|------------|---------------|-------------|
| `shared` (default) | yes | no | Cross-agent context with audit trail. Architect can see what developer noted, but every row records who said it. |
| `isolated` | yes | yes | Strict separation. Architect never sees developer's observations / memories / sessions. |

What gets tagged when `AGENT_ID` is set: `Session.agentId`, `RawObservation.agentId`, `CompressedObservation.agentId`, `Memory.agentId`. The role flows from `api::session::start` → `mem::observe` → `mem::compress` → KV.
What gets tagged when `AGENTMEMORY_AGENT_ID` or `AGENT_ID` is set: `Session.agentId`, `RawObservation.agentId`, `CompressedObservation.agentId`, `Memory.agentId`. The role flows from integration/MCP calls into REST or iii functions, then from `api::session::start` / `api::observe` / `api::remember` into KV.

What gets filtered in isolated mode: `mem::smart-search`, `/agentmemory/memories`, `/agentmemory/observations`, `/agentmemory/sessions`. Each endpoint accepts `?agentId=<role>` to override per-request, and `?agentId=*` to opt out of the env scope entirely. `/memories` also accepts `?includeOrphans=true` to surface pre-AGENT_ID memories whose `agentId` is undefined.

Per-call override at the SDK / REST layer: every mutating endpoint (`/session/start`, `/remember`) accepts an `agentId` field in the request body that wins over the env. Useful for runtimes routing many roles through one server process.
Per-call override at the SDK / REST layer: mutating endpoints that create memory records (`/session/start`, `/observe`, `/remember`) accept an `agentId` field in the request body that wins over the env. The MCP server and standalone shim also forward `AGENTMEMORY_AGENT_ID` for `memory_save` and `memory_smart_search`. Useful for runtimes routing many roles through one server process.

Session `agent` and `metadata` fields are descriptive attribution, not isolation. Hooks can store the client/model/role/source that produced a session, and recall/search/context output can show compact labels such as `claude-code reviewer via session-start (claude-sonnet-4-6)`. Filtering still uses only `agentId` and `AGENTMEMORY_AGENT_SCOPE`; `agent.client` or `agent.agentType` never grant or restrict access.

When `AGENT_ID` is unset, memory remains unscoped (legacy behavior, no tags, no filters).
When both `AGENTMEMORY_AGENT_ID` and `AGENT_ID` are unset, memory remains unscoped (legacy behavior, no tags, no filters).

### Multi-user team memory (`TEAM_MODE` + `userId`)

Expand Down
81 changes: 81 additions & 0 deletions docs/todos/2026-06-18-issue-528-agentid-per-call/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Issue 528 Agent ID Per-Call Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Pass integration-specific agent IDs through memory save/search/observe/session calls without forcing all clients to share the server-level `AGENT_ID`.

**Architecture:** Add a resolved integration-agent identity in config, using `AGENTMEMORY_AGENT_ID` before legacy `AGENT_ID`. At each integration boundary, add the resolved ID to outbound REST/MCP payloads only when non-empty, so legacy unscoped behavior is unchanged.

**Tech Stack:** TypeScript ESM, Vitest, Node MCP stdio shim, Python Hermes plugin tests via Vitest `spawnSync`, OpenClaw JavaScript plugin tests.

---

## Files

- Modify: `src/config.ts`
- Modify: `src/mcp/server.ts`
- Modify: `src/mcp/standalone.ts`
- Modify: `src/triggers/api.ts`
- Modify: `integrations/hermes/__init__.py`
- Modify: `integrations/openclaw/plugin.mjs`
- Modify: `README.md`
- Modify: `test/agent-id-scope.test.ts`
- Modify: `test/mcp-server-surface.test.ts`
- Modify: `test/mcp-standalone.test.ts`
- Modify: `test/openclaw-plugin.test.ts`
- Modify: `test/integration-plaintext-http.test.ts`

## Task 1: Config Regression

- [ ] Add config tests proving `AGENTMEMORY_AGENT_ID` trims/caps like `AGENT_ID`, wins over `AGENT_ID`, and unset/blank values fall back to legacy behavior.
- [ ] Implement config resolution in `src/config.ts` by reading `AGENTMEMORY_AGENT_ID` first and then `AGENT_ID`.
- [ ] Run: `corepack pnpm exec vitest run test/agent-id-scope.test.ts`
- [ ] Expected: the new config tests pass and existing `#554` scope behavior remains intact.

## Task 2: MCP Server Forwarding

- [ ] Add MCP server tests proving `memory_save` and `memory_smart_search` include the resolved agent ID when available and preserve explicit `agentId` override when callers pass one.
- [ ] Update `src/mcp/server.ts` to import/use `getAgentId()` and add `agentId` to `mem::remember` and `mem::smart-search` payloads only when resolved.
- [ ] Run: `corepack pnpm exec vitest run test/mcp-server-surface.test.ts`
- [ ] Expected: trigger payloads show the correct per-call `agentId`.

## Task 3: REST Boundary Consumption

- [ ] Add REST tests proving `/agentmemory/remember` forwards whitelisted `body.agentId` to `mem::remember` and `/agentmemory/observe` forwards whitelisted `body.agentId` to `mem::observe`.
- [ ] Update `src/triggers/api.ts` to validate/whitelist optional non-empty string `agentId` for `remember` and `observe`, preserving rejection of malformed required fields.
- [ ] Run: `corepack pnpm exec vitest run test/api-boundary-coverage.test.ts`
- [ ] Expected: REST trigger payloads include `agentId` only when supplied as a usable string.

## Task 4: Standalone Shim Forwarding

- [ ] Add standalone tests proving proxy mode sends `agentId` in `/remember` and `/smart-search` request bodies, and local fallback stores/returns agent IDs for different clients.
- [ ] Update `src/mcp/standalone.ts` validation and payload helpers to preserve resolved `agentId` on save/search.
- [ ] Run: `corepack pnpm exec vitest run test/mcp-standalone.test.ts`
- [ ] Expected: proxy bodies and local fallback records contain the resolved agent ID only when configured.

## Task 5: Integration Payloads

- [ ] Add OpenClaw tests for `AGENTMEMORY_AGENT_ID` in before-start smart search and agent-end observe payloads.
- [ ] Add Hermes tests for `agent_identity` and env fallback flowing into session/search/save/observe payloads.
- [ ] Update `integrations/openclaw/plugin.mjs` and `integrations/hermes/__init__.py` to attach `agentId` from integration identity.
- [ ] Run: `corepack pnpm exec vitest run test/openclaw-plugin.test.ts test/integration-plaintext-http.test.ts`
- [ ] Expected: integration payloads carry the expected agent ID and omit it when no identity is configured.

## Task 6: Docs, Cleanup, Verification

- [ ] Update README multi-agent section to document `AGENTMEMORY_AGENT_ID` precedence for integrations and MCP clients.
- [ ] Run a focused simplification pass on touched code, preserving APIs, schema, auth, routes, storage, and isolation contracts.
- [ ] Run targeted suite: `corepack pnpm exec vitest run test/agent-id-scope.test.ts test/api-boundary-coverage.test.ts test/mcp-server-surface.test.ts test/mcp-standalone.test.ts test/openclaw-plugin.test.ts test/integration-plaintext-http.test.ts`
- [ ] Run full suite: `corepack pnpm test`
- [ ] Stage intended files and run `gitleaks protect --staged --redact`.
- [ ] Run Semgrep because integration/tenancy boundary handling changed: `semgrep scan --config p/default --error --metrics=off .`
- [ ] Run OSV only if dependency files changed; otherwise record skip reason.
- [ ] Commit, push branch to `origin`, open PR against `main`, wait for checks when available, merge PR, verify issue linkage/close.

## Self-Review

Spec coverage: the plan covers the issue's config, Hermes, OpenClaw, MCP server, standalone MCP shim, documentation, and verification claims.

Placeholder scan: no placeholder steps remain; each task names files, command, and expected result.

Type consistency: `agentId` remains the existing serialized field across REST, MCP payloads, local fallback records, and search results.
81 changes: 81 additions & 0 deletions docs/todos/2026-06-18-issue-528-agentid-per-call/todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Issue 528 Agent ID Per-Call Scope

Scope: repository worktree `/Users/A1538552/.codex/worktrees/d561/agentmemory`, branch `issue/528-agentid-per-call`, target `origin/main`.

## Sprint Contract

Goal: fix integration-scoped memory calls so each integration can pass its own agent identity per call instead of relying only on the server-level `AGENT_ID`.

Scope:
- `src/config.ts` agent identity resolution.
- `src/triggers/api.ts` REST `remember`/`observe` `agentId` whitelisting.
- MCP server handlers for `memory_save` and `memory_smart_search`.
- Standalone MCP shim proxy and local fallback paths.
- Hermes and OpenClaw integration REST calls.
- Focused regression tests and documentation for `AGENTMEMORY_AGENT_ID`.

Non-goals:
- No new MCP tools or REST endpoints.
- No schema, migration, auth, route, or storage-boundary changes.
- No PRs against `rohitg00/agentmemory`; only `origin` (`wbugitlab1/agentmemory`) with target `main`.

Acceptance criteria:
- `AGENTMEMORY_AGENT_ID` wins over legacy `AGENT_ID` for integration/client identity selection.
- Integrations omit `agentId` when no usable identity exists, preserving legacy unscoped behavior.
- MCP server and standalone shim forward the resolved integration agent ID to save/search calls.
- REST `/remember` and `/observe` consume whitelisted per-call `agentId` values from integrations.
- Hermes and OpenClaw include the resolved integration agent ID in session, search, save, and observe payloads.
- Regression tests cover distinct agent IDs and fallback behavior.

Intended verification:
- `corepack pnpm exec vitest run test/agent-id-scope.test.ts test/api-boundary-coverage.test.ts test/mcp-server-surface.test.ts test/mcp-standalone.test.ts test/openclaw-plugin.test.ts test/integration-plaintext-http.test.ts`
- `corepack pnpm test`
- Security gates required before commit: `gitleaks protect --staged --redact`; Semgrep because integration boundary behavior changes; OSV only if dependency/lockfile surfaces change.

Known boundaries:
- This touches tenancy/isolation tagging but does not change storage schema or authorization.
- Remote writes, PR creation, merge, and issue close are authorized by the current delegated user request for this issue flow only.

Stop conditions:
- Evidence shows issue is already fixed or invalid.
- Fix requires schema/auth/migration/dependency changes.
- Verification or security gate fails and cannot be resolved with a scoped fix.

## Feature / Verification Matrix

| Change | Verification method | Status | Evidence |
| --- | --- | --- | --- |
| Config resolves per-integration agent ID | Add/run config tests | Done | `test/agent-id-scope.test.ts`; targeted suite passed 281/281 on 2026-06-18 |
| REST remember/observe consume per-call agent ID | Add/run API boundary tests | Done | `test/api-boundary-coverage.test.ts`; includes malformed `agentId` rejection; targeted suite passed 281/281 |
| MCP server forwards agent ID for save/search | Add/run MCP server tests | Done | `test/mcp-server-surface.test.ts`; env and explicit tool `agentId` precedence covered; targeted suite passed 281/281 |
| Standalone shim forwards/persists agent ID | Add/run standalone tests | Done | `test/mcp-standalone.test.ts`; local fallback and proxy mode covered; targeted suite passed 281/281 |
| Hermes/OpenClaw REST payloads include agent ID | Add/run integration tests | Done | `test/openclaw-plugin.test.ts` and `test/integration-plaintext-http.test.ts`; no-agent legacy omission and env fallback covered; targeted suite passed 281/281 |
| Project checks and security gates | Run targeted/full tests plus gates | Done | After merging current `origin/main`, targeted suite passed 281 tests; `corepack pnpm test` passed 194 files / 2744 tests; `corepack pnpm run lint` passed; `gitleaks protect --staged --redact` no leaks before commits; current-tree `gitleaks detect --source . --redact --no-git` no leaks; final Semgrep 0 findings |

## Subagent Ledger

| Workstream | Scope | Edits allowed | Expected output | Result | Residual risk |
| --- | --- | --- | --- | --- | --- |
| Independent issue validation | Read-only repo and issue evidence | No | Valid/stale/duplicate conclusion with files, commands, evidence, risks | Valid: origin/main `4d5fbe20...` still dropped per-call/client `agentId` at REST/MCP/integration boundaries | Low: reviewer noted tenancy-sensitive surface; covered by targeted regression tests |
| Plan pre-review | Plan/task record only | No | High/Medium findings or ACCEPT | High finding accepted: add REST `/remember` and `/observe` consumption; Medium recall finding triaged below | None |
| Final implementation review | Working-tree diff | No | High/Medium findings or ACCEPT | Three Medium findings fixed: observe malformed `agentId` rejection, explicit MCP `agentId` precedence tests, stale task record | None after rerun |

## Progress

- 2026-06-18: Confirmed clean worktree, detached `HEAD` equal to `origin/main` (`4d5fbe20f5cd8273687da459ec1128dfaf4f5226`), then created branch `issue/528-agentid-per-call`.
- 2026-06-18: Issue #528 is open and tracks upstream PR 665 text; upstream patch body claims integration calls omit `agentId`.
- 2026-06-18: Initial local evidence shows `loadAgentScope()` only reads `AGENT_ID`, MCP `memory_save`/`memory_smart_search` do not forward a resolved `agentId`, standalone proxy/local fallback do not include agent identity, and Hermes/OpenClaw integration calls omit `agentId`.
- 2026-06-18: Plan review found missing REST consumption of `agentId` for `/remember` and `/observe`; plan updated to include `src/triggers/api.ts` and API tests. Reviewer's `memory_recall` concern is tracked as scope-sensitive: upstream issue names MCP `memory_smart_search`; existing MCP recall already accepts explicit `agentId` and isolated-mode env fallback through `mem::search`, so implementation remains focused on save/smart-search unless tests show a concrete regression.
- 2026-06-18: Wrote failing tests first; initial targeted run failed with 9 expected agentId propagation failures after `corepack pnpm install --frozen-lockfile --ignore-scripts` resolved pnpm ignored-build hardening.
- 2026-06-18: Implemented `AGENTMEMORY_AGENT_ID` precedence, REST `agentId` whitelisting, MCP server/shim forwarding, Hermes/OpenClaw payload tagging, generated skill references, and README docs.
- 2026-06-18: Targeted suite passed: `corepack pnpm exec vitest run test/agent-id-scope.test.ts test/api-boundary-coverage.test.ts test/mcp-server-surface.test.ts test/mcp-standalone.test.ts test/openclaw-plugin.test.ts test/integration-plaintext-http.test.ts` -> 6 files, 281 tests.
- 2026-06-18: Full suite passed: `corepack pnpm test` -> 194 files, 2741 tests.
- 2026-06-18: Full suite initially failed because generated skill references were stale; `corepack pnpm run skills:gen` regenerated `plugin/skills/agentmemory-config/REFERENCE.md` and `plugin/skills/agentmemory-mcp-tools/REFERENCE.md`, after which full suite passed.
- 2026-06-18: Lint passed: `corepack pnpm run lint`.
- 2026-06-18: Security gates passed: `gitleaks protect --staged --redact` scanned ~33.52 KB and found no leaks; `semgrep scan --config p/default --error --metrics=off .` scanned 851 tracked files with 0 findings. OSV was not run because this task did not change dependencies, lockfiles, container images, vendored code, or third-party package surfaces.
- 2026-06-18: `origin/main` advanced to `47f904cdb488d77be7748896679b7477a0c9477d`; merged it into `issue/528-agentid-per-call` to avoid reverse diffs in the PR. Post-merge PR diff remained scoped to Issue #528 files.
- 2026-06-18: Post-merge targeted suite passed: 6 files, 281 tests. Post-merge full suite passed: 194 files, 2744 tests. Post-merge lint passed.
- 2026-06-18: Final current-tree security checks after merge/docs commit: `gitleaks detect --source . --redact --no-git` scanned ~23.57 MB and found no leaks; `semgrep scan --config p/default --error --metrics=off .` scanned 855 tracked files with 0 findings. Semgrep reported four individual rule timeouts but completed successfully with no blocking findings. A broader full-history `gitleaks detect --source . --redact` reported pre-existing historical findings across repository history; this task did not rewrite history, and staged/current-tree secret checks are clean.
- 2026-06-18: After opening PR #1001, GitHub reported the branch was behind `main`; fetched latest `origin/main` and merged it. Refreshed checks passed: targeted suite 6 files / 281 tests, `corepack pnpm test` 194 files / 2744 tests, `corepack pnpm run lint`, current-tree `gitleaks detect --source . --redact --no-git` scanned ~23.58 MB with no leaks, and Semgrep scanned 857 tracked files with 0 findings.
- 2026-06-18: Before merge, `origin/main` advanced again with issue #511 team private user identity. Merged `origin/main`, resolved conflicts in `README.md` and `src/config.ts` by preserving `resolveUserId()` / `AGENTMEMORY_USER_ID` behavior and this issue's `AGENTMEMORY_AGENT_ID` precedence. Regenerated skill references with `corepack pnpm run skills:gen`. Final refreshed checks passed: expanded targeted suite 8 files / 298 tests, `corepack pnpm test` 195 files / 2755 tests, `corepack pnpm run lint`, current-tree `gitleaks detect --source . --redact --no-git` scanned ~23.61 MB with no leaks, and Semgrep scanned 859 tracked files with 0 findings.
- 2026-06-18: `origin/main` advanced once more with issue #520 metacognition work. Merged cleanly. Final local checks passed: targeted suite plus new policy tests 10 files / 307 tests, `corepack pnpm test` 197 files / 2764 tests, `corepack pnpm run lint`, current-tree `gitleaks detect --source . --redact --no-git` scanned ~23.64 MB with no leaks, and Semgrep scanned 862 tracked files with 0 findings.
Loading
Loading