Skip to main content

Memories

A Memory is an AI-generated summary of a segment of a chat conversation. Each Memory carries a short and a long form of the summary plus extracted facts (topics, decisions, actions, entities) and a vector embedding used for semantic recall during later turns of the conversation.

Memory routes are guarded by chat ownership rather than a permission. The Memory read_access scope joins the parent chat on the requester's username, so a Memory is visible only to the owner of its chat. There is no permission.ai.manage or BYOK gate on these routes.

A Memory's summary is not a single summary string. The persisted shape is:

FieldTypeDescription
idstring (UUID)Memory id
chatIdstring (UUID)Parent chat id
titlestringShort title for the Memory
l1stringDetailed summary, Markdown
l2stringOne- or two-sentence summary
topicsstring[]Extracted topics
decisionsstring[]Extracted decisions
actionsstring[]Extracted action items
entitiesstring[]Extracted entities (names, files, systems)
vectorstring | nullEmbedding stored as text (null until embedded)
reasonstringWhy the Memory was created (see below)
createdAt / updatedAtdateTimestamps

Creation reasons (reason enum):

  • user_created - default for an explicit create with no other reason
  • user_requested - requested by the user during the conversation
  • completed_discussion - a discussion reached its natural conclusion
  • made_decision - a decision was recorded
  • solved_problem - a problem was resolved
  • natural_break - a natural break in the conversation
  • topic_change - the conversation shifted to a new topic
  • autosave - created automatically by the autosave policy

GET /api/chats/{id}/memories

List a chat's Memories, ordered by createdAt ascending. Each Memory carries an aggregated messageCount (the number of messages assigned to it).

Authentication: Required (chat ownership)

Pre-blocks: chat.lookup

Response:

A HAL collection under _embedded["inf:memory"]. Each item includes the Memory fields above plus messageCount. vector is returned as text (or null when the Memory has not been embedded).

List a chat’s memoriesGET /api/chats/00000000-0000-4000-8000-000000000001/memories
GET /api/chats/{id}/memories returns the chat’s memories ordered by createdAt ascending, each with an aggregated `messageCount`. Fields are title, l1 (detailed markdown), l2 (short summary), topics/decisions/actions/entities arrays, vector (embedding as text), and reason — not a single `summary`.
Response · 200
[
{
"permissions": {},
"id": "00000000-0000-4000-8000-000000000002",
"chatId": "00000000-0000-4000-8000-000000000001",
"title": "Q4 revenue targets",
"l1": "## Overview\nThe team reviewed **Q4 revenue targets** and growth strategies for the Order Desk.",
"l2": "Reviewed Q4 revenue targets and growth strategies.",
"vector": null,
"topics": [
"Revenue",
"Growth"
],
"decisions": [
"Raise the Q4 target to $2.5M"
],
"actions": [
"Draft the revised forecast"
],
"entities": [
"Order Desk",
"Q4_report.pdf"
],
"reason": "topic_change",
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"messageCount": 2
}
]
Captured from the API examples test suite; ids and timestamps are normalized.

POST /api/chats/{id}/memories

Create a Memory from the chat's most recent un-memorized messages. The summary is always AI-generated; you cannot supply your own summary text.

Authentication: Required (chat ownership)

Pre-blocks: chat.lookup

Request Body:

FieldTypeRequiredDescription
messageIdstringNoSummarize up to and including this message
asOfdateNoSummarize messages up to this timestamp
reasonstringNoCreation reason (default user_created)

There is no messageIds array and no summary field. The server selects the un-memorized messages itself and generates the summary and embedding.

Example Request:

{ "reason": "user_requested" }

Response:

Responds 200 with the created Memory.

Requires un-memorized messages

A Memory needs at least a user/assistant pair of messages that have not already been assigned to a Memory. With nothing new to summarize, the route answers 400 No new messages to create memory from before making any AI call.

Create a memory with nothing to summarizePOST /api/chats/00000000-0000-4000-8000-000000000001/memories
POST /api/chats/{id}/memories payload is { messageId?, asOf?, reason? } (default reason `user_created`). A memory needs at least a user/assistant pair of un-memorized messages; otherwise the route answers 400 "No new messages to create memory from" before any AI call. The success path is live-AI (summary + embedding) and is not captured.
Request body
{
"reason": "user_created"
}
Response · 400
{
"statusCode": 400,
"error": "Bad Request",
"message": "No new messages to create memory from"
}
Captured from the API examples test suite; ids and timestamps are normalized.

The success path calls a live model provider to generate the summary and the embedding, so it is not captured here.


GET /api/memories/{id}

Retrieve a single Memory together with its assigned messages. Each message is returned in UI-message shape, with any attached files embedded in the message metadata.

Authentication: Required (chat ownership)

This route is itself the memory.lookup server method. Access is enforced by the Memory read_access scope, so an unknown or not-owned id answers 404.

Response:

Get a memoryGET /api/memories/00000000-0000-4000-8000-000000000001
GET /api/memories/{id} returns one memory plus its `messages` (each a UI-shaped message with files). Guarded by the memory read_access scope (chat ownership).
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/memories/00000000-0000-4000-8000-000000000001"
}
},
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"chatId": "00000000-0000-4000-8000-000000000002",
"title": "Q4 revenue targets",
"l1": "## Overview\nThe team reviewed **Q4 revenue targets** and growth strategies for the Order Desk.",
"l2": "Reviewed Q4 revenue targets and growth strategies.",
"vector": null,
"topics": [
"Revenue",
"Growth"
],
"decisions": [
"Raise the Q4 target to $2.5M"
],
"actions": [
"Draft the revised forecast"
],
"entities": [
"Order Desk",
"Q4_report.pdf"
],
"reason": "topic_change",
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"messages": [
{
"id": "00000000-0000-4000-8000-000000000003",
"role": "user",
"parts": [
{
"text": "What were our Q4 targets?",
"type": "text"
}
],
"metadata": {
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"liked": null,
"memoryId": "00000000-0000-4000-8000-000000000001",
"explanation": null,
"files": []
}
},
{
"id": "00000000-0000-4000-8000-000000000004",
"role": "assistant",
"parts": [
{
"text": "The Q4 targets were $2.5M in net revenue.",
"type": "text"
}
],
"metadata": {
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"liked": null,
"memoryId": "00000000-0000-4000-8000-000000000001",
"explanation": null,
"files": []
}
}
]
}
Captured from the API examples test suite; ids and timestamps are normalized.

A Memory id that does not exist (or that the requester does not own) answers 404:

Get a memory that does not existGET /api/memories/00000000-0000-4000-8000-000000000001
An unknown (or not-owned) memory id answers 404 via the read_access scope.
Response · 404
{
"statusCode": 404,
"error": "Not Found",
"message": "Memory not found"
}
Captured from the API examples test suite; ids and timestamps are normalized.

PUT /api/memories/{id}

Regenerate a Memory's summary and embedding from its assigned messages.

Authentication: Required (chat ownership)

Request Body:

FieldTypeRequiredDescription
actionstringYesMust be regenerate

Example Request:

{ "action": "regenerate" }

Response:

Responds 200 with an envelope, not the raw Memory:

{
"success": true,
"message": "Memory regenerated successfully",
"memory": {
"id": "…",
"l1": "…",
"l2": "…",
"topics": ["…"],
"decisions": ["…"],
"actions": ["…"],
"entities": ["…"],
"createdAt": "…"
}
}
Use cases

Regenerate to refresh a summary after messages were edited, or to re-embed with an updated model.

Regeneration calls a live model provider for the summary and embedding, so the response is not captured here.


DELETE /api/memories/{id}

Delete a Memory. Its messages remain; only the Memory record and its embedding are removed.

Authentication: Required (chat ownership)

The handler resolves the Memory through the read_access scope and answers 404 for an unknown or not-owned id.

Response:

Responds 200 with { "success": true } (the Informer convention). This route does not return 204 No Content.

Delete a memoryDELETE /api/memories/00000000-0000-4000-8000-000000000001
DELETE /api/memories/{id} removes the memory (its messages remain) and returns 200 with body { success: true } — the Informer convention, NOT 204 No Content as the page claimed.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/memories/00000000-0000-4000-8000-000000000001"
}
},
"success": true
}
Captured from the API examples test suite; ids and timestamps are normalized.

POST /api/chats/{id}/memories/search

Semantic search over a chat's Memories using vector similarity. The query text is embedded with the same model used to embed the Memories.

Authentication: Required (chat ownership)

Pre-blocks: chat.lookup

Request Body:

FieldTypeRequiredDescription
querystringYesSearch text (1-500 characters)
limitintegerNoMax results (1-20, default 5)

Example Request:

{ "query": "revenue growth strategies", "limit": 5 }

Response:

Responds 200 with an envelope. Each result is a flattened Memory with a relevance score, not a nested { memory, score } pair:

{
"success": true,
"query": "revenue growth strategies",
"totalResults": 1,
"results": [
{
"id": "…",
"rank": 1,
"summary": "…",
"details": "…",
"topics": ["…"],
"decisions": ["…"],
"actions": ["…"],
"entities": ["…"],
"messageId": "…",
"createdAt": "…",
"relevance": 0.87
}
]
}

summary is the Memory's l2, details is its l1, and relevance is derived from the vector distance (null when no distance is available). Higher relevance indicates a closer match.

Context retrieval

Memory search injects relevant prior discussion back into a conversation, improving response quality on recurring topics.

Search embeds the query with a live model provider, so the response is not captured here.