Skip to main content
Retrieve understands meaning rather than keywords. “Where does Alice work?”, “Alice’s employer”, and “What company is Alice at?” all surface the same memory. Your query is embedded and compared against stored memory embeddings, then results are ranked by relevance_score.

Parameters

Response

client.retrieve() returns the results list directly, and an empty list when nothing matches.

Memory types

Every result carries a memory_type. The same content can exist at more than one level, as raw evidence and as a distilled version of it, so filtering by type asks for exactly the layer you want. By default (prefer_observations: true) a note is returned in place of the facts it was built from, so you see one distilled result instead of the same content several times. Set prefer_observations: false to receive the raw facts alongside their note.

Entities and time

Each result carries structured signal beyond the raw text. The same entities are exposed as a browsable graph. See Graph.

Searching over time

Every memory carries two independent times, and knowing which is which is most of the work: They differ whenever you import history: a memory about last June that you upload today has an event time of last June and a record time of today. as_of and query_timestamp are not variants of each other: one filters, the other ranks, and both work on record time.
Use as_of to reproduce a past answer or audit a decision: “why did the agent say that on June 1st”. Use query_timestamp when the query itself contains a relative date, or when you want older-but-more-time-relevant memories to rank higher without excluding anything. Both take an ISO 8601 instant. A malformed one is rejected as 422 before the search runs, so a typo costs you nothing.
as_of filters on when a memory was recorded, not on when the event happened. A bulk import is recorded today no matter what timestamp each item carries, so as_of a year ago returns nothing from it. There is currently no filter on event time. timestamp and occurred_start affect ranking and are returned on results, but cannot be used as a range filter.
Under as_of, retrieval skips its graph-expansion pass and answers from semantic, keyword and temporal retrieval only. Expansion follows entity links without a time bound, so it could pull in a memory recorded after the cutoff: a wrong answer for point-in-time recall rather than a ranking artifact. The practical effect is that an as_of search is slightly narrower than the same search without it.

Prompt-ready context

Most callers take the results array and join it into a system prompt. Ask for format: "block" and that is done for you, including the token budget, which a hand-written loop usually skips.
Over the raw API:
  • results stays populated, so wanting both costs one round trip, not two.
  • The block is numbered plain text with no header, so you compose your own prompt around it.
  • context_max_tokens drops whole memories, lowest-ranked first. Text is never cut mid-sentence: half a fact still reads as a fact.
  • token_estimate is an estimate, derived from a characters-per-token approximation rather than a tokenizer. Treat it as a guide when budgeting a context window, not an exact count.
Omitting format behaves exactly as before.

Scoping within a space

A space is the coarse boundary. user_id, agent_id and session_id partition it, so one space can serve many end users without their memories mixing, and you do not need a space per user.
Scoping is strict, and that is the point:
  • A scoped search returns only memories written under the same scope. Bob’s memories can never appear in Alice’s results.
  • Memories stored without a scope are not returned to a scoped search either. If you turn scoping on for a space that already has history, that history stays visible to unscoped searches but not to scoped ones, so backfill the scope on those memories if you need them.
  • Passing several keys ANDs them: user_id + session_id returns only that user’s memories from that session.
  • Consolidated memories are built per user, so a synthesis never mixes two users’ facts. Sessions roll up into the user, which is what lets the memory improve across conversations.
Tags beginning with anona: are reserved for this and rejected with 422 reserved_tag, since otherwise a hand-written tag could impersonate another user’s scope. Use the scope fields instead.
Scoping costs nothing when unused. A request without these fields behaves exactly as it did before they existed.

Latency modes

mode trades relevance quality against speed.

Error responses

See the full error reference.

Next steps

Reason API

Get a synthesized answer instead of a ranked list.

Graph API

Inspect the entities behind your results.