Skip to content

feat(tools): add governance hook for memory retrieval (#1348)#1363

Open
AyushKashyapII wants to merge 1 commit into
supermemoryai:mainfrom
AyushKashyapII:feat/memory-governance-hook
Open

feat(tools): add governance hook for memory retrieval (#1348)#1363
AyushKashyapII wants to merge 1 commit into
supermemoryai:mainfrom
AyushKashyapII:feat/memory-governance-hook

Conversation

@AyushKashyapII

Copy link
Copy Markdown

Summary

Adds an optional governance hook at the memory-retrieval boundary — the point between Supermemory returning profile()/search() results and those results reaching an agent's context. Closes the generic-hook option raised in #1348.

Supermemory doesn't implement PII redaction, prompt-injection detection, or audit logging itself. Instead, this adds a pluggable extension point so any external governance provider (e.g. TealTiger, or an org's own compliance layer) can inspect, rewrite, drop, or block memories before they're formatted and injected into the LLM prompt — without hardcoding a dependency on any one vendor.

Why this approach (vs. the other options in #1348)

The issue proposed three paths: (a) a standalone package needing no core changes, (b) a generic hook API, (c) inline PII/injection detection built into core. This PR implements (b) — it's the only option that's actually a scoped, provider-agnostic change to this repo; (a) needs nothing here, and (c) would mean Supermemory building and maintaining its own redaction/detection logic, which duplicates what governance SDKs already do.

What changed

The hook is a plain function: (profile, context) => profile | Promise<profile>, called with the raw retrieved memories (not yet deduplicated or formatted) plus { containerTag, queryText, mode }. It's optional everywhere — omitting it changes nothing.

Wired into every place memories get fetched and handed to an LLM:

  • packages/tools/src/shared/types.ts — new MemoryGovernanceContext / MemoryGovernanceHook types, added to SupermemoryBaseOptions.
  • packages/tools/src/shared/memory-client.tsbuildMemoriesText() runs the hook right after the /v4/profile fetch, before dedup/formatting. This is the shared chokepoint used by most integrations.
  • Vercel AI SDK (vercel/middleware.ts), Mastra (mastra/processor.ts, mastra/types.ts), VoltAgent (voltagent/middleware.ts) — threaded through to buildMemoriesText. VoltAgent's separate "advanced search" path (which bypasses buildMemoriesText) also runs the hook on its raw results.
  • OpenAI middleware (openai/middleware.ts) — has its own duplicated fetch/format logic (doesn't use shared/), so the hook is wired in independently for both the Chat Completions and Responses API paths.
  • MCP server (apps/mcp/src/client.ts) — SupermemoryClient takes an optional governance: { onSearch?, onProfile? } hook, applied at the end of search()/getProfile(), right before results become MCP tool output.

Not included (open questions for maintainers)

  • apps/mcp/src/server.ts's getClient() doesn't wire a hook in — there's no existing config mechanism to source one from at request time in the hosted Cloudflare Workers deployment, and inventing one (env var, webhook, etc.) felt like a separate architectural decision.
  • This is retrieval-time only. Ingestion-time scanning would need to live in the backend API, which isn't part of this repo.

Test plan

  • Added a test in shared/memory-client.test.ts: stubs /v4/profile to return a memory containing a fake SSN, passes a governanceHook that redacts SSN-shaped strings, and asserts both (1) the hook receives the raw profile + correct context, and (2) the final formatted output contains [REDACTED] and never the real SSN.
  • bun run test in packages/tools — 90 passing, no regressions (2 pre-existing unrelated failures: one needs a live SUPERMEMORY_API_KEY, one has a pre-existing broken import on main).
  • bun run check-types — no new errors introduced; confirmed via git stash that the one remaining error in openai/middleware.ts pre-dates this change, and this change incidentally fixes a pre-existing type error in voltagent/middleware.ts

…1348)

Signed-off-by: Ayush KAshyap <kashyap11ayush02@gmail.com>
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