Agent Memory

Search and context compilation

Retrieve a compiled, prompt-ready context for a task, together with a receipt of exactly what was delivered.

At the start of a task you fetch the information the agent needs. Instead of a single result list, Agent Memory returns a compiled context that can be added straight to the prompt, plus a receipt for that delivery.

Endpoints

SurfaceCall
RESTPOST /v1/memory/retrieve
MCPsearch_memory (output is Markdown-like text + (receipt <id>))
Node / Pythonmemory.search(query, {...})
.NETRetrieveAsync / agent.SearchAsync

Example

curl -s -X POST $API/v1/memory/retrieve \
  -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -d "{
    \"workspaceId\": \"$WS\",
    \"runId\": \"billing-refactor-13\",
    \"semanticQuery\": \"how are invoice numbers generated\",
    \"topN\": 10,
    \"tags\": {\"facet\": \"billing\"},
    \"tokenBudget\": 2000
  }"

Request fields

FieldDefaultDescription
workspaceId—Required.
runId—Required. This run's current memories come back as sessionEntries; the receipt is tied to this run.
semanticQuery—Natural-language query.
applicationId—The application's memories + the workspace shared pool.
userId—Narrows to the end user and adds that user's profile and their user-visibility memories. Requires the act for users permission.
topN40Clamped to 1–100.
tags—Tag filter; every given key: value pair must match exactly (AND).
minScoreadaptiveFixed score threshold. If omitted, an adaptive threshold relative to the best result is applied.
tokenBudgetworkspace setting (4000)Upper limit for the compiled context, 256–32000. Tokens are counted with a real tokenizer.
modedeterministicassisted: LLM query parsing and reranking (if an LLM is available).
rerank—true requests LLM reranking for this call (requires assisted; combined with deterministic it returns 400).
includeSupersededfalseAlso returns superseded memories.
asOf, asOfAxis—Read as of a past point in time. See Time, provenance and explainability.
temporalAfter, temporalBefore, temporalAnchor—Filter and sort by memory creation time (createdAt).
expandSessions, expandSessionCount, expandSessionWindowoffExpands the episode context around the memories found.
rawfalseSkips context compilation; returns a raw result list.
explainfalseAdds diagnostics and a per-memory "why was this recalled" explanation.
overrides—Advanced: changes fusion and score weights for this call (rrfK, legWeights, factorWeights, utilityWeight, valueAware, scoringVersion).

MCP search_memory takes a subset of these fields: query, runId, userId, facet, includeSuperseded, explain, tokenBudget, mode, rerank.

Response: the compiled context

FieldContents
receiptIdDelivery receipt.
blocksBlocks pinned to every context.
userProfileThe user profile, if userId was given.
platformEntriesPlatform-wide rules.
tenantFloors, tenantEntriesAdmin-approved tenant-wide rules. Floors go into every context.
workspaceEntriesMemories matching the query, in score order. Each one includes trust (a trust breakdown).
proceduresRelevant learned procedures.
relevantEpisodesSimilar past tasks.
sessionSummary, sessionEntriesSummary and current memories of the same runId.
supersededHiddenCountNumber of superseded memories that were hidden.
compilationtokenBudget, tokensUsed, and per-section included / dropped / tokens.
diagnosticsWith explain: true: how many candidates each search leg found, the threshold, weights, stage timings.

How search works

  1. Short type queries (queries of up to five words that contain a type name, such as "recent decisions" or "corrections") are routed directly to the type list.
  2. Other queries run on parallel search legs: vector similarity, PostgreSQL full-text search, entity name matching, episode sentences, a 2-hop expansion in the relationship graph from the top vector results, and type-based structural search.
  3. The legs are combined with reciprocal-rank fusion (k=60). If no leg finds anything, the result is empty; only memories found by the search legs move on to the next stages.
  4. Visibility, application, facet, user, validity time and superseded filters are applied.
  5. The score is a weighted sum of the five components shown in the explain output: rrf (fusion relevance, 0.35), recency (0.15), accessFreq (0.10), importance (0.30), confidence (0.10). Recency decays exponentially from the memory's creation time. The weights can be changed per call with overrides.factorWeights.
  6. In assisted mode, if an LLM is available, the candidate list can be scored 0–10 by the LLM and reranked.
  7. The context compiler fits sections into the budget in order: blocks → profile → platform rules → tenant rules → procedures → workspace memories → episodes → run summary → run memories. Admin rules (platform policies and floors) are reserved first; if the budget can't even hold those, it returns 422 CONTEXT_BUDGET_TOO_SMALL.

Memories of type artifact_ref are not returned by search; read them by ID.

"Why was this recalled?"

explain: true (in MCP, explain=true) adds an explanation to each memory:

{
  "legs": [{"leg": "Vector", "rank": 0, "rawScore": 0.30, "rrfContribution": 0.0164}],
  "rrfScore": 0.0301,
  "factors": [{"name": "rrf", "value": 1, "weight": 0.35, "contribution": 0.35},
              {"name": "recency", "value": 0.9999, "weight": 0.15, "contribution": 0.15}],
  "floorApplied": 0.2346,
  "reranker": {"status": "skipped"},
  "finalScore": 0.7821,
  "trust": {"composite": 0.738, "confidence": 0.8, "evidence": 0.289, "freshness": 1.0,
            "utility": 0.5, "contradictionRisk": 0, "sourceAuthority": 1}
}

To see a memory's source and history, use explain_memory / GET /v1/memory/{id}/explain separately.

Trust score

Each memory comes with a trust breakdown computed at read time: confidence, evidence count, freshness (a forgetting curve whose stability grows with use), utility, source authority, and risk (open contradiction, stale, or superseded). The trust score does not affect ranking; it is there so the agent or application can decide how much to rely on the information.

Receipts and usage

On every search, the memories the compiler actually delivered are written to a receipt (receiptId), and only their usage counters are incremented. When you send an outcome or feedback with this receipt, credit goes only to the delivered memories. See Feedback and outcomes.

Limits

  • The tag filter supports only exact matches joined with AND; there are no OR, NOT, range or contains operators.
  • The temporal* fields work on creation time; natural-language time expressions like "last week" are not interpreted.
  • Full-text search uses PostgreSQL ts_rank_cd ranking (not BM25); the language configuration defaults to simple (no stemming).
  • Reranking is done only with an LLM; there is no option for a separate reranker model.
  • When running locally / self-hosted, the default embedding is hashing, so semantic similarity is limited. See Configuration.

On this page