Agent Memory
API Reference

Memory governance

Share a memory, explain how it is known, tail the change feed, review quarantined memories and run retrieval evaluations.

Share a memory

POST /v1/memory/{id}/share — raise a memory's visibility. Supports Idempotency-Key.

{ "workspaceId": "…", "visibility": "workspace", "applicationId": null, "agentId": null, "userId": null }

Visibility only widens: private → agent → user → workspace → tenant. The caller needs the share capability and must own the memory (or be a tenant admin); tenant also requires promote.

StatusMeaning
200{ "id": "…", "visibility": "workspace" }
400Unknown visibility value.
403Missing capability, or policy_denied (not the owner).
404Unknown or not visible to the subject.
422The target is not above the current visibility.

A share writes a history row and a share row in the change feed. MCP: share_memory. SDKs: share(). See Identity and visibility.

Explain a memory

GET /v1/memory/{id}/explain?workspaceId=… — "how do you know this?" for one memory. Optional query: applicationId, agentId, userId.

The response contains:

FieldContents
memoryThe memory with its provenance and temporal fields.
trustThe read-time trust breakdown: composite, confidence, evidence, freshness, utility, contradictionRisk, sourceAuthority.
lineageorigin (run, episode, entry it was promoted from), derivedFrom, derivedInto, supersededBy, supersedes, and recorded evidence sources.
evidenceThe originating episode and its first events, sourceRef and how the memory was extracted.
historyThe memory's history rows.
usageUsage count, last access, how often it was injected, used or ignored, and recent outcomes of runs it was delivered to.
contradictionsOpen contradictions.
dependentsHow many memories derive from it, with a sample.

Every linked memory is authorized for the caller separately. A link to a memory you may not see is returned with "redacted": true and its type, excerpt and lifecycle state nulled — "not visible" and "no longer exists" are deliberately indistinguishable. When episode events were withheld, evidence.redacted is true and the episode's goal and summary are null. 404 for an unknown or foreign memory.

MCP: explain_memory. SDKs: explain().

Change feed

GET /v1/memory/changesets?workspaceId=… — the workspace's change feed, oldest first. Content never enters the feed; rows carry policy fields only.

QueryNotes
workspaceIdRequired.
actionOne of create, update, delete, share, promote, policy_change.
memoryIdOnly changes to this memory.
sinceOnly rows created at or after this instant.
cursorThe nextCursor of a previous page.
limit1–500, default 50.
{
  "rows": [
    {
      "seq": "1042",
      "id": "…",
      "memoryId": "…",
      "action": "delete",
      "actor": "support-bot",
      "actorRole": "agent",
      "oldValues": { "lifecycle_state": "Active" },
      "newValues": { "lifecycle_state": "SoftDeleted", "dependents_flagged": "2", "dependents_flagged_ids": "…,…" },
      "reason": null,
      "createdAt": "2026-10-01T09:00:00Z"
    }
  ],
  "nextCursor": "1042",
  "hasMore": false
}

nextCursor is returned whenever a page is non-empty and echoed back when nothing is new, so tailing the feed is a single loop: keep the cursor and call again. A malformed cursor, action or limit is 400.

  • Blast radius of a delete: ?memoryId=<id>&action=delete — the delete row lists the dependents that were flagged stale.
  • Tenant-level rows (a tenant convention's promotion) are not in a workspace feed; they surface in the console.

MCP: get_changesets.

Review a quarantined memory

Appended content is screened for prompt-injection and data-exfiltration patterns. Flagged content is stored quarantined: never recalled, merged, consolidated, promoted or shared until reviewed.

POST /v1/memory/{id}/review

{ "workspaceId": "…", "action": "release", "applicationId": null }
FieldNotes
actionrelease makes the memory live; reject keeps it out. Anything else is 400.

Response: { "id": "…", "status": "released" } or "rejected". A memory that is not quarantined (or not in this workspace) answers 404. Requires the curate capability.

Retrieval evaluation

POST /v1/memory/evals/run — a retrieval regression run. You supply queries and the memory IDs each one should surface; the product runs its own retrieval for each case (deterministic, at the maximum token budget) and scores the results. No LLM judge, no side effects: evaluation reads create no receipts, touch no usage counters and earn no credit. One metered operation per run.

{
  "workspaceId": "…",
  "agentId": "support-bot",
  "k": 10,
  "datasetVersion": "2026-10-01",
  "cases": [
    {
      "query": "what can Alex eat?",
      "expectedIds": ["8b0c1c0e-…"],
      "forbiddenIds": ["…"],
      "staleIds": ["…"]
    }
  ]
}
FieldNotes
cases1–200 cases. Each needs a non-empty query and expectedIds; forbiddenIds must never surface; staleIds are out-of-date memories.
kCut-off, clamped to 1–100. Default 10.
agentIdThe agent whose view is evaluated.
applicationId, datasetVersionOptional.

The response includes passed (false if any forbidden ID appears in any case's top k), hitRate, recallAtK, precisionAtK, mrr, ndcgAtK with 95% bootstrap intervals, abstentionAccuracy, forbiddenRate, staleRate, zeroResultRate, latency percentiles, meanContextTokens, llmCalls, a manifest and perCase results. Two runs are comparable only when their manifest.comparableKey matches.

Use it as a CI gate after a configuration change or an upgrade.

On this page