Skip to main content

Memories API

Query and manage a character's memory of a specific player. Estuary automatically builds memory from conversations -- this API lets you read what the character remembers, search across it, visualize it as a knowledge graph, and edit it manually.

Read & visualize: /api/agents/{agent_id}/players/{player_id}/memories Manual edits (create / update / delete one): /api/v1/agents/{agent_id}/players/{player_id}/memories

:::info agent_id = character_id The agent_id in the URL path is the same id returned by the Characters API. :::

For background on how memory works, see Memory System.


List Memories

GET /api/agents/{agent_id}/players/{player_id}/memories

Returns a paginated list of memories.

Query Parameters

ParameterTypeDefaultDescription
memory_typestring--Filter by type: "fact", "preference", "relationship", "event", "emotional_state", "correction", "character_self", "spatial_change"
statusstring"active"Memory status: "active", "superseded", "decayed", or "deleted"
limitinteger50Results per page (1-200)
offsetinteger0Number of results to skip
sort_bystring"created_at"Sort field: "created_at", "confidence", "last_accessed_at"
sort_orderstring"desc""asc" or "desc"

Response

{
"memories": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": "user_def456",
"agentId": "550e8400-e29b-41d4-a716-446655440001",
"playerId": "player_xyz",
"memoryType": "fact",
"content": "The user works as a software engineer at a startup in San Francisco",
"confidence": 0.92,
"status": "active",
"source": "text_chat",
"memoryLayer": "ltm",
"importance": 0.78,
"sourceConversationId": "conv_def456",
"sourceQuote": "I work as a software engineer at this startup in SF",
"accessCount": 3,
"createdAt": "2026-02-10T15:30:00",
"lastAccessedAt": "2026-03-01T14:22:00",
"extractedAt": "2026-02-10T15:31:00",
"sourceMessageTimestamp": "2026-02-10T15:29:50",
"updatedAt": "2026-02-10T15:30:00"
}
],
"total": 87,
"limit": 50,
"offset": 0
}

Memory Object Fields

FieldTypeDescription
idstringUnique memory identifier (UUID)
userIdstringID of the developer account that owns the memory
agentIdstringCharacter (agent) ID this memory belongs to
playerIdstringPlayer ID this memory was extracted for
memoryTypestringOne of: fact, preference, relationship, event, emotional_state, correction, character_self, spatial_change
contentstringThe memory content text
confidencenumberConfidence score (0.0-1.0)
statusstring"active", "superseded", "decayed", or "deleted"
sourcestringOrigin of the memory: "text_chat" (auto-extracted from a conversation) or "manual_dashboard" (created via the Create Memory endpoint)
memoryLayerstring"ltm" (long-term) or "stm" (short-term). Controls how the memory ages -- short-term memories fade faster if unused
importancenumberImportance weight (0.0-1.0) used during retrieval ranking
sourceConversationIdstring | nullConversation that produced this memory. null for manually created memories
sourceQuotestring | nullOriginal conversation text that produced this memory. null for manually created memories
accessCountnumberHow many times this memory has been retrieved
createdAtstringISO 8601 creation timestamp
lastAccessedAtstring | nullISO 8601 timestamp of last retrieval
extractedAtstring | nullISO 8601 timestamp of extraction
sourceMessageTimestampstring | nullISO 8601 timestamp of the source message
updatedAtstring | nullISO 8601 last update timestamp

Examples

# All memories
curl "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories" \
-H "X-API-Key: est_your_api_key"

# Only fact memories, sorted by confidence
curl "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories?memory_type=fact&sort_by=confidence" \
-H "X-API-Key: est_your_api_key"
const res = await fetch(
`https://api.estuary-ai.com/api/agents/${agentId}/players/${playerId}/memories?memory_type=event&limit=20`,
{ headers: { "X-API-Key": "est_your_api_key" } }
);
const data = await res.json();
console.log(`${data.total} event memories`);

Create Memory

POST /api/v1/agents/{agent_id}/players/{player_id}/memories

Create a memory manually -- useful for seeding context, importing data, or building a dashboard that lets end users teach the character.

Request Body

JSON, Content-Type: application/json. All keys are camelCase.

FieldTypeRequiredDefaultDescription
contentstringYes--Memory text. 1-2000 characters
memoryTypestringYes--One of: "fact", "preference", "relationship", "event", "emotional_state", "correction", "character_self", "spatial_change"
importancenumberNo0.50.0-1.0. Higher values are surfaced more aggressively during retrieval
memoryLayerstringNo"stm""ltm" for memories you want preserved long-term; "stm" for ephemeral ones
confidencenumberNo1.00.0-1.0. Defaults to 1.0 because manual entries are presumed accurate

Unknown fields are rejected with 422 Unprocessable Entity.

Response

201 Created with the full Memory object. The created memory has source: "manual_dashboard" and sourceConversationId: null.

Quotas

Manual writes (create + update combined) are limited to 1,000 per day per developer account. Exceeding the cap returns 429 Too Many Requests:

{ "detail": "Manual memory write quota exceeded (1000/day)" }

The counter resets at UTC midnight.

Example

curl -X POST "https://api.estuary-ai.com/api/v1/agents/{agent_id}/players/player_xyz/memories" \
-H "X-API-Key: est_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"content": "The user is allergic to peanuts.",
"memoryType": "fact",
"importance": 0.9,
"memoryLayer": "ltm"
}'
const res = await fetch(
`https://api.estuary-ai.com/api/v1/agents/${agentId}/players/${playerId}/memories`,
{
method: "POST",
headers: {
"X-API-Key": "est_your_api_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "The user is allergic to peanuts.",
memoryType: "fact",
importance: 0.9,
memoryLayer: "ltm",
}),
}
);
const memory = await res.json();
console.log("Created", memory.id);

Update Memory

PATCH /api/v1/agents/{agent_id}/players/{player_id}/memories/{memory_id}

Partially update a memory. Send only the fields you want to change. Omitted fields are left untouched.

Request Body

Same field set as Create Memory -- all fields optional:

FieldTypeDescription
contentstringNew memory text (1-2000 chars)
memoryTypestringNew type
importancenumberNew importance (0.0-1.0)
memoryLayerstring"ltm" or "stm"
confidencenumberNew confidence (0.0-1.0)

Unknown fields return 422. A body with no recognized fields is a no-op and returns the existing memory unchanged.

Response

200 OK with the updated Memory object.

Returns 404 Not Found if the memory doesn't exist or belongs to a different agent/player. Counts toward the daily manual-write quota.

Example

curl -X PATCH "https://api.estuary-ai.com/api/v1/agents/{agent_id}/players/player_xyz/memories/{memory_id}" \
-H "X-API-Key: est_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "content": "The user is allergic to peanuts and tree nuts.", "importance": 0.95 }'

Delete a Memory

DELETE /api/v1/agents/{agent_id}/players/{player_id}/memories/{memory_id}

Delete a single memory. By default this is a soft delete -- the memory's status flips to "deleted" and it is excluded from retrieval, but the row is preserved so it can be inspected later. Pass ?hard=true to remove the row entirely.

Query Parameters

ParameterTypeDefaultDescription
hardbooleanfalseIf true, permanently removes the memory. If false, marks it deleted but preserves the row

Response

204 No Content on success. Empty body.

Returns 404 Not Found if the memory doesn't exist or belongs to a different agent/player.

Example

# Soft delete (recoverable)
curl -X DELETE "https://api.estuary-ai.com/api/v1/agents/{agent_id}/players/player_xyz/memories/{memory_id}" \
-H "X-API-Key: est_your_api_key"

# Hard delete (permanent)
curl -X DELETE "https://api.estuary-ai.com/api/v1/agents/{agent_id}/players/player_xyz/memories/{memory_id}?hard=true" \
-H "X-API-Key: est_your_api_key"

Memory Timeline

GET /api/agents/{agent_id}/players/{player_id}/memories/timeline

Returns memories grouped by date for timeline visualization.

Query Parameters

ParameterTypeDefaultDescription
group_bystring"day"Grouping period: "day", "week", "month"
start_datedatetime--Filter memories after this date (ISO 8601)
end_datedatetime--Filter memories before this date (ISO 8601)

Response

{
"timeline": [
{
"date": "2026-03-01",
"memories": [ /* Memory objects */ ]
},
{
"date": "2026-02-28",
"memories": [ /* Memory objects */ ]
}
],
"totalMemories": 87,
"groupBy": "day"
}

Example

curl "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories/timeline?group_by=week" \
-H "X-API-Key: est_your_api_key"

Memory Stats

GET /api/agents/{agent_id}/players/{player_id}/memories/stats

Returns aggregate statistics about a player's memory.

Response

{
"totalActive": 87,
"totalSuperseded": 5,
"totalDecayed": 3,
"byType": {
"fact": 32,
"preference": 15,
"relationship": 8,
"event": 18,
"emotional_state": 6,
"correction": 2,
"character_self": 4,
"spatial_change": 2
},
"coreFacts": 12
}
FieldTypeDescription
totalActivenumberActive memories
totalSupersedednumberMemories replaced by newer information
totalDecayednumberMemories that have decayed below threshold
byTypeobjectBreakdown of active memories by type
coreFactsnumberNumber of core facts

Example

curl "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories/stats" \
-H "X-API-Key: est_your_api_key"

Core Facts

GET /api/agents/{agent_id}/players/{player_id}/memories/core-facts

Returns the core facts the character knows about a player. Core facts are concise, structured statements (name, location, interests, etc.) always included in the LLM context.

Response

{
"coreFacts": [
{
"id": "fact_001",
"userId": "user_abc",
"agentId": "agent_xyz",
"playerId": "player_xyz",
"factKey": "name",
"factValue": "Alex",
"sourceMemoryId": "mem_abc123",
"createdAt": "2026-02-10T15:30:00",
"updatedAt": "2026-03-01T14:22:00"
},
{
"id": "fact_002",
"userId": "user_abc",
"agentId": "agent_xyz",
"playerId": "player_xyz",
"factKey": "occupation",
"factValue": "Software engineer at a startup",
"sourceMemoryId": "mem_def456",
"createdAt": "2026-02-12T10:00:00",
"updatedAt": null
}
]
}

Example

curl "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories/core-facts" \
-H "X-API-Key: est_your_api_key"

Knowledge Graph

GET /api/agents/{agent_id}/players/{player_id}/memories/graph

Returns the memory knowledge graph: clustered memories, entities, and their relationships.

Query Parameters

ParameterTypeDefaultDescription
include_entitiesbooleanfalseInclude entity nodes and relationship edges
include_character_memoriesbooleanfalseInclude the character's self-reflective memories

Response

{
"nodes": [
{ "id": "user_player_xyz", "type": "user", "label": "player_xyz" },
{ "id": "cluster_0", "type": "cluster", "label": "Work & Career", "memoryCount": 12 },
{ "id": "mem_abc", "type": "memory", "label": "Works as a software engineer...", "memoryType": "fact" },
{ "id": "ent_001", "type": "entity", "entityType": "person", "name": "Alex" }
],
"edges": [
{ "source": "user_player_xyz", "target": "cluster_0", "type": "has_cluster" },
{ "source": "cluster_0", "target": "mem_abc", "type": "contains" },
{ "source": "mem_abc", "target": "ent_001", "type": "mentions" }
],
"stats": {
"totalMemories": 87,
"totalEntities": 15,
"clusterCount": 6,
"clusters": { "Work & Career": 12, "Hobbies": 8 }
},
"stale": false
}

The stale flag indicates whether the response was served from a cache that is currently being refreshed in the background. When true, a fresh version is being computed and a subsequent request shortly after should return it.

Node types

TypeDescription
userThe player node (center of the graph)
clusterA topic group containing related memories
memoryAn individual memory
entityA person, place, or thing mentioned in memories

Edge types

TypeDescription
has_clusterUser -> Cluster
containsCluster -> Memory
mentionsMemory -> Entity
relationshipEntity -> Entity (with relationshipType and label)

Example

curl "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories/graph?include_entities=true" \
-H "X-API-Key: est_your_api_key"

Search Memories

POST /api/agents/{agent_id}/players/{player_id}/memories/search

Semantic search across a player's memories using vector similarity. The query is embedded once and matched against both text-derived and image-derived memories; results are merged and ranked by similarity.

Request Body

JSON, Content-Type: application/json.

FieldTypeRequiredDefaultDescription
querystringYes--Search query (1-500 chars)
limitintegerNo10Max results (clamped to 1-50)

Response

{
"results": [
{
"memoryId": "550e8400-e29b-41d4-a716-446655440000",
"similarity": 0.87,
"content": "The user talked about hiking in Rocky Mountain National Park last summer"
}
],
"query": "hiking trips",
"total": 1
}
FieldTypeDescription
memoryIdstringID of the matching memory. Pass to the List Memories endpoint (or filter the response) to get the full memory object
similaritynumberVector similarity score (higher = more relevant)
contentstringThe matching memory's content text, included for convenience

Example

curl -X POST "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories/search" \
-H "X-API-Key: est_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "query": "hiking trips", "limit": 5 }'
const res = await fetch(
`https://api.estuary-ai.com/api/agents/${agentId}/players/${playerId}/memories/search`,
{
method: "POST",
headers: {
"X-API-Key": "est_your_api_key",
"Content-Type": "application/json",
},
body: JSON.stringify({ query: "favorite foods", limit: 10 }),
}
);
const data = await res.json();
data.results.forEach((r) => {
console.log(`[${r.similarity.toFixed(2)}] ${r.content}`);
});

Delete All Memories

DELETE /api/agents/{agent_id}/players/{player_id}/memories?confirm=true

Permanently deletes all memories for a player-character pair. Useful for GDPR compliance and right-to-be-forgotten requests. To delete a single memory, use Delete a Memory instead.

warning

The confirm=true query parameter is required. Requests without it return 400 Bad Request. This action cannot be undone.

Response

{
"message": "Deleted 87 records",
"deletedCount": 87
}

Example

curl -X DELETE "https://api.estuary-ai.com/api/agents/{agent_id}/players/player_xyz/memories?confirm=true" \
-H "X-API-Key: est_your_api_key"