Download OpenAPI specification:
AgentMemory is a persistent, semantic memory service for AI agents. It stores conversation history, extracted facts, and vector embeddings, enabling agents to recall relevant past context across sessions and conversations.
AgentMemory organizes data in a three-level hierarchy:
When a memory block is written, AgentMemory automatically generates a vector embedding and an
optional LLM-generated summary. By default this happens asynchronously in the background.
Blocks are immediately readable after ingestion but only participate in semantic search once
their status reaches ready. Blocks with status: processing or status: extraction_failed
are excluded from search results.
Authentication is optional and controlled by the OIDC_AUTH_ENABLED server configuration.
When enabled, all endpoints except GET /health and GET /metrics require a valid JWT
Bearer token issued by the configured OIDC provider.
Include the token in every request: Authorization: Bearer <token>
Tokens are validated against the provider's JWKS endpoint. A 401 response indicates a
missing, malformed, or expired token. A 403 response indicates a valid token with
insufficient permissions.
All request and response bodies use application/json. All timestamps are ISO 8601 strings
in UTC. Errors are returned as a JSON object with an error code, a human-readable
message, and an optional details field.
Memory block ingestion is accepted immediately, but semantic extraction (embedding generation
and summarization) is rate-limited by the configured model provider. If the extraction queue
reaches capacity, ingestion requests return 503 with a retry_after_seconds field.
Create and manage user identities. A user is the top-level entity in the AgentMemory hierarchy — every session and memory block is owned by a user.
The user_id is application-defined and must be unique across the deployment. Use your application's native user identifier (UUID, account ID, or similar) as user_id to avoid maintaining a separate mapping table.
Deleting a user is a cascade operation — it permanently removes all sessions and memory blocks associated with that user. There is no soft-delete or recovery.
Create a new user with the specified ID, name, and optional metadata.
The user_id must be unique — attempting to create a user with an existing ID returns a conflict error.
| user_id required | string (User Id) |
| name required | string (Name) |
Metadata (object) or Metadata (null) (Metadata) |
{- "user_id": "user_123",
- "name": "John Doe",
- "metadata": {
- "department": "Engineering",
- "level": "senior",
- "role": "developer"
}
}{- "id": "string",
- "name": "string",
- "sessions": [
- "string"
], - "metadata": { }
}Find users matching the provided criteria (user_id, name, or metadata).
Multiple criteria are combined with AND logic. At least one criterion must be provided.
User Id (string) or User Id (null) (User Id) | |
Name (string) or Name (null) (Name) | |
Metadata (object) or Metadata (null) (Metadata) |
{- "user_id": "user_123",
- "name": "John Doe",
- "metadata": {
- "department": "Engineering"
}
}{- "id": "string",
- "name": "string",
- "sessions": [
- "string"
], - "metadata": { }
}Update an existing user's name and/or metadata.
At least one field must be provided. Omitted fields retain their existing values.
| user_id required | string (User Id) Unique identifier for the user |
Name (string) or Name (null) (Name) | |
Metadata (object) or Metadata (null) (Metadata) |
{- "name": "Jane Smith",
- "metadata": {
- "department": "Engineering",
- "role": "senior_developer"
}
}{- "id": "string",
- "name": "string",
- "sessions": [
- "string"
], - "metadata": { }
}Permanently delete a user and all associated sessions and memory blocks. This operation is irreversible — there is no soft-delete or recovery.
| user_id required | string (User Id) Unique identifier for the user |
{- "detail": [
- {
- "loc": [
- "string"
], - "msg": "string",
- "type": "string",
- "input": null,
- "ctx": { }
}
]
}Update the time-to-live (TTL) for memory blocks belonging to a user. Optionally scope the update to specific sessions or specific block IDs.
| user_id required | string (User Id) Unique identifier for the user |
Session Id (string) or Session Id (null) (Session Id) | |
Array of Block Ids (strings) or Block Ids (null) (Block Ids) | |
| new_ttl required | integer (New Ttl) >= 0 |
{- "session_id": "string",
- "block_ids": [
- "string"
], - "new_ttl": 0
}nullRetrieve all sessions for a user, including lifecycle state and annotations. Returns an empty list if the user has no sessions.
| user_id required | string (User Id) Unique identifier for the user |
{- "sessions": [
- {
- "user_id": "string",
- "session_id": "string",
- "start_time": "string",
- "end_time": "string",
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "metadata": { },
- "blocks_ttl": 0
}
], - "count": 0
}Create and manage conversation sessions. A session scopes memory blocks and defines the default retrieval boundary for semantic search.
Sessions have a two-state lifecycle:
POST /users/{user_id}/sessions/{session_id}/end to end a session.Deleting a session cascades to all of its memory blocks.
Create a new session for the specified user.
The session_id must be unique per user — attempting to create a session with a duplicate ID returns a conflict error.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) |
Annotations (object) or Annotations (null) (Annotations) | |
Metadata (object) or Metadata (null) (Metadata) | |
Memory Blocks Ttl (integer) or Memory Blocks Ttl (null) (Memory Blocks Ttl) |
{- "session_id": "session_456",
- "annotations": {
- "category": "technical",
- "intent": "support"
}, - "metadata": {
- "platform": "ios",
- "source": "web_chat"
}, - "memory_blocks_ttl": 3600
}{- "user_id": "string",
- "session_id": "string",
- "start_time": "string",
- "end_time": "string",
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "metadata": { },
- "blocks_ttl": 0
}Retrieve a session by ID, including its lifecycle state, annotations, and metadata.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
{- "user_id": "string",
- "session_id": "string",
- "start_time": "string",
- "end_time": "string",
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "metadata": { },
- "blocks_ttl": 0
}Update a session's annotations and/or metadata. At least one field must be provided. Omitted fields retain their existing values.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
Annotations (object) or Annotations (null) (Annotations) | |
Metadata (object) or Metadata (null) (Metadata) |
{- "annotations": {
- "intent": "support",
- "status": "resolved"
}, - "metadata": {
- "duration": 1200,
- "satisfaction": "high"
}
}{- "user_id": "string",
- "session_id": "string",
- "start_time": "string",
- "end_time": "string",
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "metadata": { },
- "blocks_ttl": 0
}Permanently delete a session and all its memory blocks. This operation is irreversible.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
{- "detail": [
- {
- "loc": [
- "string"
], - "msg": "string",
- "type": "string",
- "input": null,
- "ctx": { }
}
]
}Mark a session as ended. Once ended, no new memory blocks can be added.
Existing memory blocks remain readable and searchable. Returns the updated session with end_time set.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
{- "user_id": "string",
- "session_id": "string",
- "start_time": "string",
- "end_time": "string",
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "metadata": { },
- "blocks_ttl": 0
}Add, retrieve, update, and search memory blocks. A memory block is the atomic unit of knowledge — each block holds either a chat message exchange or a standalone fact, and is automatically processed for semantic search.
Adding memory — Submit messages or facts in a single request. Semantic extraction runs asynchronously by default; blocks are readable immediately and become searchable once extraction completes.
Searching memory — Provide a natural-language query to retrieve semantically similar blocks. Search is session-scoped by default. Set filters.session_ids to "all" to search across all sessions for a user. Only ready blocks are returned.
TTL and expiry — Memory blocks carry an optional time-to-live in seconds. TTL can be set per-block, per-session, or globally via server configuration.
Add one or more memory blocks to the session. Each block holds either a chat message (user + assistant turn) or a fact (declarative string). Blocks are written immediately and queued for semantic extraction. The session must be open — ended sessions reject new blocks.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
Array of Messages (objects) or Messages (null) (Messages) | |
Array of Facts (strings) or Facts (null) (Facts) | |
Annotations (object) or Annotations (null) (Annotations) | |
Created At (string) or Created At (null) (Created At) ISO 8601 timestamp indicating when the data was originally created. Stored as null if not provided. | |
| async_processing | boolean (Async Processing) Default: false |
Memory Block Ttl (integer) or Memory Block Ttl (null) (Memory Block Ttl) | |
Context Required (boolean) or Context Required (null) (Context Required) |
{- "messages": [
- {
- "assistant_content": "It's sunny and 72°F.",
- "user_content": "What's the weather?"
}
], - "facts": [
- "User prefers email notifications",
- "User is allergic to peanuts"
], - "annotations": {
- "category": "preferences",
- "importance": "high"
}, - "created_at": "2024-06-15T12:00:00",
- "async_processing": true,
- "memory_block_ttl": 3600,
- "context_required": true
}{- "message": "Successfully added 2 memory block(s)",
- "accepted_count": 2,
- "block_ids": [
- "block-abc123",
- "block-def456"
], - "rejected_count": 1,
- "rejected_details": {
- "actual_tokens": 500,
- "input_index": 0,
- "per_request_token_limit": 400,
- "reason": "memory block exceeds per-request token limit"
}
}Delete memory blocks by ID. Pass a list of block IDs to delete specific blocks,
or "all" to delete every block in the session.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
required | Array of Block Ids (strings) or "all" (string) (Block Ids) |
{- "block_ids": [
- "string"
]
}{- "deleted_count": 0
}Update the content, annotations, or TTL of an existing memory block.
Providing a new message or fact triggers re-extraction (new embedding and summary).
Omitted fields retain their existing values. Use this endpoint to retry extraction
on blocks with status: extraction_failed by setting async_processing: true.
If the block does not exist or has expired due to TTL, responds with 404.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
| block_id required | string (Block Id) Unique identifier for the memory block |
ChatMessage (object) or null | |
Fact (string) or Fact (null) (Fact) | |
Annotations (object) or Annotations (null) (Annotations) New annotations to overwrite existing ones. If None, existing annotations are preserved. | |
Memory Block Ttl (integer) or Memory Block Ttl (null) (Memory Block Ttl) New TTL in seconds. If None, existing TTL is preserved. | |
| async_processing | boolean (Async Processing) Default: false If True, semantic extraction runs in background via queue. |
Context Required (boolean) or Context Required (null) (Context Required) Whether semantic extraction is required. If None, uses environment variable. |
{- "message": {
- "assistant_content": "Updated answer",
- "user_content": "Updated question"
}, - "fact": "Updated fact about the user",
- "annotations": {
- "category": "updated",
- "importance": "high"
}, - "memory_block_ttl": 3600,
- "async_processing": true,
- "context_required": true
}{- "message": "Memory block updated successfully",
- "block": {
- "block_id": "string",
- "user_id": "string",
- "session_id": "string",
- "message": {
- "user_content": "What's the weather today?",
- "assistant_content": "It's sunny and 72°F."
}, - "fact": "string",
- "ingested_at": "string",
- "created_at": "string",
- "last_queued_at": "string",
- "fail_count": 0,
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "summary": "string",
- "contexts": [
- "string"
], - "status": "processing",
- "rel_score": 0
}
}Retrieve memory blocks using semantic similarity and/or filters. Provide a natural-language
query to rank blocks by relevance, or use filters alone for deterministic retrieval.
Search is session-scoped by default — set filters.session_ids to "all" to search
across all sessions for the user. Only ready blocks appear in results.
| user_id required | string (User Id) Unique identifier for the user |
| session_id required | string (Session Id) Unique identifier for the session |
Query (string) or Query (null) (Query) | |
FilterOptions (object) or null |
{- "query": "What are the user's preferences?",
- "filters": {
- "start_time": "2025-12-22T00:00:00",
- "end_time": "2025-12-22T23:59:59",
- "created_start_time": "2025-12-22T00:00:00",
- "created_end_time": "2025-12-22T23:59:59",
- "session_ids": [
- "session_123",
- "session_456"
], - "block_ids": [
- "block_001",
- "block_002"
], - "relevant_k": 10,
- "annotations": {
- "importance": "high"
}, - "order_by": "ingested_at"
}
}{- "memory_blocks": [
- {
- "block_id": "string",
- "user_id": "string",
- "session_id": "string",
- "message": {
- "user_content": "What's the weather today?",
- "assistant_content": "It's sunny and 72°F."
}, - "fact": "string",
- "ingested_at": "string",
- "created_at": "string",
- "last_queued_at": "string",
- "fail_count": 0,
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "summary": "string",
- "contexts": [
- "string"
], - "status": "processing",
- "rel_score": 0
}
], - "count": 0
}Paginated list of memory blocks for a user, ordered newest first.
Use session_ids to scope results to specific sessions.
Always specify limit and offset — unbounded requests on large datasets are slow.
| user_id required | string (User Id) Unique identifier for the user |
Session Ids (string) or Session Ids (null) (Session Ids) Comma-separated session IDs to filter by, or 'all' for all sessions | |
| limit | integer (Limit) [ 1 .. 200 ] Default: 20 Maximum number of memory blocks to return (1–200) |
| offset | integer (Offset) >= 0 Default: 0 Number of memory blocks to skip for pagination |
| order_by | string (Order By) Default: "ingested_at" Enum: "ingested_at" "created_at" Field to order results by. Defaults to 'ingested_at'. |
{- "memory_blocks": [
- {
- "block_id": "string",
- "user_id": "string",
- "session_id": "string",
- "message": {
- "user_content": "What's the weather today?",
- "assistant_content": "It's sunny and 72°F."
}, - "fact": "string",
- "ingested_at": "string",
- "created_at": "string",
- "last_queued_at": "string",
- "fail_count": 0,
- "annotations": {
- "property1": "string",
- "property2": "string"
}, - "summary": "string",
- "contexts": [
- "string"
], - "status": "processing",
- "rel_score": 0
}
], - "count": 0,
- "total": 0,
- "limit": 1,
- "offset": 0
}Monitor the operational status of AgentMemory and its dependencies.
GET /health is a public endpoint suitable for load balancer health probes. All other health endpoints require authentication and provide deeper diagnostic detail about the database connection, model service availability, and the semantic extraction queue.
| Status | Meaning |
|---|---|
healthy |
Component is operating normally |
degraded |
Component is reachable but not fully functional |
unhealthy |
Component is unreachable or critically impaired |
Check reachability and status of the configured embedding and LLM model services.
{- "status": "healthy",
- "embedding": {
- "status": "string",
- "model": "string",
- "retry_after": 0
}, - "llm": {
- "status": "string",
- "model": "string",
- "retry_after": 0
}
}Return lightweight readiness status for the semantic extraction queue.
{- "status": "string",
- "message": "string",
- "queue": {
- "size": 0,
- "queued_ids": 0,
- "processing": 0,
- "max_size": 0
}, - "rate_budget": {
- "available_requests": 0,
- "available_tokens": 0,
- "max_requests_per_minute": 0,
- "max_tokens_per_minute": 0,
- "per_request_token_limit": 0
}, - "statistics": {
- "total_enqueued": 0,
- "total_recovered": 0,
- "total_dispatched": 0,
- "total_completed": 0,
- "total_failed": 0,
- "queue_full": 0,
- "queue_duplicates": 0,
- "queue_oversized": 0,
- "recovery_duplicates": 0,
- "active_tasks": 0,
- "loop_running": true,
- "dispatcher_alive": true
}, - "loop_running": true,
- "dispatcher_alive": true
}Return detailed queue depth, model API rate budget, and cumulative throughput statistics for the semantic extraction queue.
{- "status": "string",
- "message": "string",
- "queue": {
- "size": 0,
- "queued_ids": 0,
- "processing": 0,
- "max_size": 0
}, - "rate_budget": {
- "available_requests": 0,
- "available_tokens": 0,
- "max_requests_per_minute": 0,
- "max_tokens_per_minute": 0,
- "per_request_token_limit": 0
}, - "statistics": {
- "total_enqueued": 0,
- "total_recovered": 0,
- "total_dispatched": 0,
- "total_completed": 0,
- "total_failed": 0,
- "queue_full": 0,
- "queue_duplicates": 0,
- "queue_oversized": 0,
- "recovery_duplicates": 0,
- "active_tasks": 0,
- "loop_running": true,
- "dispatcher_alive": true
}, - "loop_running": true,
- "dispatcher_alive": true
}Return current memory usage relative to the configured quota threshold. When usage exceeds the threshold, new ingestion requests are rejected until pressure subsides.
{- "status": "string",
- "message": "string",
- "accepting_requests": true,
- "usage_percent": 0,
- "threshold_percent": 0,
- "last_check": 0
}Expose Prometheus-compatible metrics for monitoring and alerting. This endpoint is public and requires no authentication, making it suitable for Prometheus scrape targets and infrastructure monitoring tools.
Download a ZIP archive of server logs and optional system diagnostics. Use this endpoint to collect diagnostic data for support requests or incident post-mortems. Requires authentication.
Download server logs and optional system diagnostics as a ZIP archive.
Use log_types to select log categories and start_time/end_time to narrow the time range.
Add sys_commands to include live system snapshots (CPU, memory, disk, network) in the archive.
Include this archive in support requests and incident post-mortems.
Start Time (string) or Start Time (null) (Start Time) Include log lines at or after this timestamp | |
End Time (string) or End Time (null) (End Time) Include log lines at or before this timestamp | |
Array of Log Types (strings) or Log Types (null) (Log Types) Log categories to include | |
Array of Sys Commands (strings) or Sys Commands (null) (Sys Commands) Optional system commands to run and include in the archive |
null