Skip to content

Read memories

This guide shows how to read memories with each of Alvia’s six read operations, and which one to use. Every read answers from what applies now.

For endpoint schemas and status codes, use the API reference.

You need Operation Endpoint
A short answer to put in a prompt or act on Context POST /v1/memories/context
The one memory that best matches, with its ID and details Recall POST /v1/memories/recall
Several candidate memories, ranked Search POST /v1/memories/search
A memory whose ID you already have Get GET /v1/memories/{memory_id}
A memory’s versions and relationships Inspect GET /v1/memories/{memory_id}/inspect
Every memory, for example to show or export them List GET /v1/memories

Context, recall and search take the same request body:

Field Required Description
query Yes The question, 1 to 1,000 characters.
scope No Limit the read to matching memories. See Projects and scope.
occurred_after No Only memories from this time on. See Point-in-Time Reasoning and change over time.
occurred_before No Only memories from before this time.
limit No Search only: how many results, 1 to 50. Defaults to 25. Values outside the range are clamped.

Write the query as the question your application needs answered, such as “What did Acme decide about the onboarding rollout?”.

Use scope for the user, agent or application whose memories you need. Scope fields narrow the result together. Add occurred_after and occurred_before only when the date range is part of the question; see Filter by date for what they include.

Context finds the memory that best matches the query and resolves it with its related and contradicting memories into one to three sentences.

POST /v1/memories/context
curl https://api.alvia.ai/v1/memories/context \
-H "Authorization: Bearer $ALVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What did Acme decide about the rollout?",
"scope": { "organization_id": "acme" }
}'
Response
{
"context": "Acme replaced its company-wide launch with a finance-team pilot on September 24, 2026. The wider rollout waits until its security review is complete."
}

When Alvia has no context for the question right now, the response is 404 with code not_found: for example, no memory matches the query. Treat it as “no context for now”: answer without it, or ask the user. Each call looks again, so a later call can return context. If context returns 404 on every call, check the scope and that memories have formed.

When context cannot finish its answer in time, it returns 503 with code capacity_exceeded. Answer without context while a user waits, or retry after Retry-After.

Alvia writes the answer from the current text of the best match and of the memories linked to it, with the date each was stated. Use the answer as context for your model or your logic, and keep the decision in your application. A new version or a forget of a memory the answer used shows in the next answer.

Recall returns the single best memory, with its ID, so you can show it, give feedback on it or forget it.

POST /v1/memories/recall
curl https://api.alvia.ai/v1/memories/recall \
-H "Authorization: Bearer $ALVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Where should invoices go?",
"scope": { "organization_id": "acme" }
}'
Response
{
"status": "active",
"memory_id": "mem_01K6Z1M4TB7D9E2F5G8H3J6K0P",
"content": "Acme's invoices go to ap@acme.example.",
"category": "preference",
"is_favorited": false,
"sentiment": "neutral",
"occurred_at": "2026-10-02T11:15:00-07:00",
"ranked_score": 0.8731,
"scope": {
"organization_id": "acme",
"user_id": "u_4821",
"application_id": null,
"agent_id": null,
"team_id": null
},
"entities": { "organization/Acme": 0.71, "identifier/ap@acme.example": 0.29 }
}

A recall miss returns 200 with status not_found, so a miss needs no error handling:

Response
{ "status": "not_found" }

Check status to tell a match from a miss. On recall, 404 means the project’s deletion started during the call.

Search returns up to limit memories, best first:

POST /v1/memories/search
curl https://api.alvia.ai/v1/memories/search \
-H "Authorization: Bearer $ALVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "query": "Atlas migration plans", "limit": 5 }'
Response
{
"object": "list",
"data": [
{
"status": "active",
"memory_id": "mem_01K6YB2C8D5E7F9G1H3J4K6M8N",
"content": "The team froze Atlas schema changes until the cutover on October 6, 2026.",
"category": "decision",
"is_favorited": false,
"sentiment": "neutral",
"occurred_at": "2026-09-28T16:30:00-04:00",
"ranked_score": 0.9112,
"scope": {
"organization_id": "acme",
"user_id": null,
"application_id": "eng-assistant",
"agent_id": null,
"team_id": null
},
"entities": { "project/Atlas": 0.64, "datetime/October 6, 2026": 0.36 }
}
],
"has_more": false,
"url": "/v1/memories/search"
}

Search returns its best candidates ranked by ranked_score, with no minimum score, so it returns results even for a loose match. Compare ranked_score within one response and apply your own cut-off to keep the matches that fit your use. Search returns its results in one response, so has_more is false.

Get returns one active memory, in the same shape as recall but without ranked_score:

GET /v1/memories/{memory_id}
curl https://api.alvia.ai/v1/memories/mem_01K6Z1M4TB7D9E2F5G8H3J6K0P \
-H "Authorization: Bearer $ALVIA_API_KEY"

It returns 404 when the memory does not exist, was forgotten, is still forming or belongs to another project.

Inspect returns one active memory with its versions, how Alvia classified each one and why, and its relationships to other active memories. Use it to show how a memory changed and what it relates to. To read a memory’s current text, use get.

GET /v1/memories/{memory_id}/inspect
curl \
https://api.alvia.ai/v1/memories/mem_01K6R8QJ2N4P6S8T0V2X4Z6B8D/inspect \
-H "Authorization: Bearer $ALVIA_API_KEY"

This response is for the Atlas memory in Example: a database upgrade in Change over time. In this example, Alvia classifies the September statement as a supersession, so the memory has two versions:

Response
{
"memory_id": "mem_01K6R8QJ2N4P6S8T0V2X4Z6B8D",
"scope": {
"organization_id": "acme",
"user_id": null,
"application_id": "eng-assistant",
"agent_id": null,
"team_id": null
},
"occurred_at": "2026-09-29T09:00:00-04:00",
"is_favorited": false,
"sentiment": "neutral",
"head_version": 2,
"versions": [
{
"version": 2,
"content": "Atlas uses PostgreSQL 17 as its primary database (stated September 29, 2026).",
"category": "decision",
"entities": { "project/Atlas": 0.51, "tool/PostgreSQL 17": 0.49 },
"occurred_at": "2026-09-29T09:00:00-04:00",
"created_at": "2026-09-29T13:00:41.218Z",
"outcome": "supersession",
"explanation": "The new statement replaces PostgreSQL 16 with PostgreSQL 17 as the Atlas primary database."
},
{
"version": 1,
"content": "The Atlas team chose PostgreSQL 16 as its primary database (stated March 10, 2026).",
"category": "decision",
"entities": { "project/Atlas": 0.52, "tool/PostgreSQL 16": 0.48 },
"occurred_at": "2026-03-10T10:00:00-05:00",
"created_at": "2026-03-10T15:00:38.402Z",
"outcome": "novel"
}
],
"relationships": [
{
"target_id": "mem_01K6S4H7MC3R5T7V9X1Z3B5D7F",
"edge_type": "related",
"created_at": "2026-04-02T14:21:07.730Z"
}
]
}

The response holds the memory’s memory_id, scope, occurred_at, is_favorited and sentiment, as get does, and these fields:

Field Description
head_version The number of the current version.
versions The memory’s newest versions, up to 100, newest first. The first is the current one.
relationships The memory’s newest relationships to active memories, up to 20, newest first.

Each version has these fields:

Field Description
version The version number. The first version is 1.
content The text of this version.
category The kind of fact. See Category.
entities The things this version names, as "type/name" keys with a weight from 0 to 1.
occurred_at The memory’s occurred_at as of this version. A new version keeps the previous version’s time when it is later.
created_at When Alvia recorded this version, in UTC.
outcome How Alvia classified the fact that formed this version. See Classification.
explanation Why the classifier chose the outcome. A novel first version has none, so the field is left out.

Each relationship has these fields:

Field Description
target_id The related memory’s ID. Get or inspect that memory by its ID.
edge_type related, or contradiction when the two memories conflict.
created_at When Alvia recorded the relationship, in UTC.

The dashboard shows the same versions and relationships in a memory’s History and Relationships. Inspect returns 404 when the memory does not exist, was forgotten, is still forming or belongs to another project.

List orders active memories by when each first formed, newest first: a memory imported today with an older occurred_at lists before memories written earlier, and a new version keeps a memory’s place. It takes these query parameters:

  • limit: 1 to 20, default 10
  • starting_after: the ID of the last memory on the previous page, to get the next page
  • ending_before: the ID of the first memory on the current page, to go back a page
  • the scope fields, such as organization_id
GET /v1/memories
curl "https://api.alvia.ai/v1/memories?limit=20&organization_id=acme" \
-H "Authorization: Bearer $ALVIA_API_KEY"

To get every page, repeat the request with starting_after set to the last ID until has_more is false. Send the same scope parameters on every page:

GET /v1/memories
import os
import requests
API_KEY = os.environ["ALVIA_API_KEY"]
params = {"limit": 20, "organization_id": "acme"}
while True:
response = requests.get(
"https://api.alvia.ai/v1/memories",
headers={"Authorization": f"Bearer {API_KEY}"},
params=params,
timeout=30,
)
response.raise_for_status()
page = response.json()
for memory in page["data"]:
print(memory["memory_id"], memory["content"])
if not page["has_more"]:
break
params["starting_after"] = page["data"][-1]["memory_id"]
Field Description
status active for a memory, not_found for a recall miss.
memory_id The memory’s ID: mem_ and 26 characters.
content The current text. Alvia can add resolved dates to it, as in “(stated September 23, 2026)”.
category The kind of fact. See Category.
is_favorited Whether you marked the memory as a favorite.
sentiment The feedback you gave: neutral, positive or negative.
occurred_at When the memory’s content was stated or observed, in the offset it was sent with.
ranked_score Search and recall only. Relevance from 0 to 1; compare within one response only.
scope All five scope fields, in lowercase. Fields you did not set are null.
entities The things the memory names, as "type/name" keys with a weight from 0 to 1.

New fields can appear in responses. Ignore fields you do not use, and handle category values you do not know.

Each completed read uses reads from your monthly allowance, whatever it returns:

  • Context uses five reads, a 404 included.
  • Inspect uses three reads, a 404 included.
  • Recall, search and get use one read each, and each page of a list uses one.

See Limits and allowances.

  • Retry only reads that failed: network errors, 5xx responses and 429 responses, after the wait in Retry-After or, without one, a delay. A 400 or a 5xx uses no read. See Production checklist.
  • A 429 with monthly_read_quota_reached succeeds only after the allowance resets.
  • Do not retry a 400. Fix the request first.
  • Do not retry a 404 from get or inspect: there is no such memory. After a 404 from context, ask again on a later call, such as the next turn, rather than in a loop.
Error Cause
400 validation_error A field is missing, out of range, too long or unknown, or occurred_before is not after occurred_after. errors names each field.
400 invalid_argument List: a cursor is not a memory ID, or both cursors were sent.
401 unauthorized The API key is missing or not valid.
404 not_found Context: no context for the query right now. Get and inspect: no such active memory. Any read: the project’s deletion started during the call.
429 rate_limit_exceeded Too many requests per second, or context is briefly limited in high demand. Retry after Retry-After.
429 rate_limit_exceeded
monthly_read_quota_reached
The monthly read allowance is used up.
503 capacity_exceeded Alvia is briefly at capacity, or context could not finish its answer in time. Retry after Retry-After.

See Errors for every code.