Memory API
curl --request POST \
--url https://api.statebase.org/v1/memoryimport requests
url = "https://api.statebase.org/v1/memory"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.statebase.org/v1/memory', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.statebase.org/v1/memory",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.statebase.org/v1/memory"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.statebase.org/v1/memory")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.statebase.org/v1/memory")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyAPI Reference
Memory API
Store and retrieve long-term knowledge with semantic search
POST
/
v1
/
memory
Memory API
curl --request POST \
--url https://api.statebase.org/v1/memoryimport requests
url = "https://api.statebase.org/v1/memory"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.statebase.org/v1/memory', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.statebase.org/v1/memory",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.statebase.org/v1/memory"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.statebase.org/v1/memory")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.statebase.org/v1/memory")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyMemory API
Memory enables your agents to remember facts across sessions. Unlike session state (which is ephemeral), memories are permanent and searchable via semantic similarity.Memory vs State
| Aspect | State | Memory |
|---|---|---|
| Scope | Single session | Cross-session |
| Lifecycle | Ephemeral (TTL) | Permanent |
| Structure | Nested JSON | Flat text + embeddings |
| Access | Direct read | Semantic search |
| Use Case | Working memory | Long-term knowledge |
Add Memory
POST /v1/memory
Stores a new memory with optional vector embedding for semantic search.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
session_id | string | ✅ Yes | Session to associate memory with |
content | string | ✅ Yes | Memory text (max 10,000 chars) |
type | string | No | Memory classification: "fact", "preference", "event", "policy" (default: "general") |
tags | array | No | Tags for categorization (e.g., ["travel", "preferences"]) |
metadata | object | No | Custom metadata |
embed | boolean | No | Generate vector embedding (default: true) |
Response
| Field | Type | Description |
|---|---|---|
id | string | Unique memory ID (format: mem_<12_chars>) |
session_id | string | Associated session |
content | string | Memory text |
type | string | Memory type |
tags | array | Tags |
metadata | object | Custom metadata |
created_at | string | ISO 8601 timestamp |
embedding_id | string | Vector DB ID (if embedded) |
vector_available | boolean | Whether semantic search is enabled |
Example
curl -X POST https://api.statebase.org/v1/memory \
-H "X-API-Key: sb_your_key" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_abc123",
"content": "User prefers concise responses without long explanations",
"type": "preference",
"tags": ["communication_style", "user_preferences"],
"metadata": {
"confidence": 0.95,
"source": "explicit_user_statement"
}
}'
from statebase import StateBase
sb = StateBase(api_key="sb_your_key")
memory = sb.memory.add(
session_id="sess_abc123",
content="User prefers concise responses without long explanations",
type="preference",
tags=["communication_style", "user_preferences"],
metadata={
"confidence": 0.95,
"source": "explicit_user_statement"
}
)
print(memory.id) # mem_xyz789
print(memory.vector_available) # True
import { StateBase } from '@statebase/node';
const sb = new StateBase({ apiKey: 'sb_your_key' });
const memory = await sb.memory.add({
sessionId: 'sess_abc123',
content: 'User prefers concise responses without long explanations',
type: 'preference',
tags: ['communication_style', 'user_preferences'],
metadata: {
confidence: 0.95,
source: 'explicit_user_statement'
}
});
console.log(memory.id); // mem_xyz789
{
"object": "memory",
"id": "mem_xyz789",
"session_id": "sess_abc123",
"created_at": "2026-01-31T04:30:00Z",
"content": "User prefers concise responses without long explanations",
"type": "preference",
"tags": ["communication_style", "user_preferences"],
"metadata": {
"confidence": 0.95,
"source": "explicit_user_statement"
},
"embedding_id": "vec_abc123",
"vector_available": true
}
Search Memories
POST /v1/memory/search
Performs semantic similarity search across all memories. Returns the most relevant memories based on vector similarity.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
query | string | ✅ Yes | Search query (will be embedded and compared) |
session_id | string | No | Filter to specific session’s memories |
user_id | string | No | Filter to specific user’s memories |
type | string | No | Filter by memory type |
tags | array | No | Filter by tags (returns memories with ANY of these tags) |
limit | integer | No | Max results to return (default: 10, max: 50) |
threshold | float | No | Minimum similarity score (0.0-1.0, default: 0.7) |
Response
| Field | Type | Description |
|---|---|---|
data | array | Array of memory results |
query | string | Original search query |
Memory Result Object
| Field | Type | Description |
|---|---|---|
id | string | Memory ID |
session_id | string | Associated session |
content | string | Memory text |
type | string | Memory type |
tags | array | Tags |
score | float | Similarity score (0.0-1.0, higher = more relevant) |
created_at | string | When memory was created |
Example
curl -X POST https://api.statebase.org/v1/memory/search \
-H "X-API-Key: sb_your_key" \
-H "Content-Type: application/json" \
-d '{
"query": "How does the user like to communicate?",
"session_id": "sess_abc123",
"limit": 5,
"threshold": 0.7
}'
memories = sb.memory.search(
query="How does the user like to communicate?",
session_id="sess_abc123",
limit=5,
threshold=0.7
)
for mem in memories:
print(f"[{mem.score:.2f}] {mem.content}")
print(f" Type: {mem.type}, Tags: {mem.tags}")
const memories = await sb.memory.search({
query: 'How does the user like to communicate?',
sessionId: 'sess_abc123',
limit: 5,
threshold: 0.7
});
memories.forEach(mem => {
console.log(`[${mem.score.toFixed(2)}] ${mem.content}`);
});
{
"object": "list",
"query": "How does the user like to communicate?",
"data": [
{
"id": "mem_xyz789",
"session_id": "sess_abc123",
"content": "User prefers concise responses without long explanations",
"type": "preference",
"tags": ["communication_style"],
"score": 0.94,
"created_at": "2026-01-31T04:30:00Z"
},
{
"id": "mem_abc456",
"session_id": "sess_abc123",
"content": "User gets frustrated with verbose AI responses",
"type": "observation",
"tags": ["communication_style", "sentiment"],
"score": 0.87,
"created_at": "2026-01-30T10:15:00Z"
}
]
}
Get Memory
GET /v1/memory/{memory_id}
Retrieves a specific memory by ID.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
memory_id | string | ✅ Yes | Memory ID |
Example
curl https://api.statebase.org/v1/memory/mem_xyz789 \
-H "X-API-Key: sb_your_key"
memory = sb.memory.get(memory_id="mem_xyz789")
print(memory.content)
print(memory.tags)
const memory = await sb.memory.get('mem_xyz789');
console.log(memory.content);
Update Memory
PATCH /v1/memory/{memory_id}
Updates an existing memory. If content is changed, a new embedding is generated.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
memory_id | string | ✅ Yes | Memory ID to update |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
content | string | No | New memory text |
type | string | No | New memory type |
tags | array | No | New tags (replaces existing) |
metadata | object | No | New metadata (merges with existing) |
Example
curl -X PATCH https://api.statebase.org/v1/memory/mem_xyz789 \
-H "X-API-Key: sb_your_key" \
-H "Content-Type: application/json" \
-d '{
"content": "User strongly prefers very concise, bullet-point responses",
"tags": ["communication_style", "high_priority"]
}'
updated_memory = sb.memory.update(
memory_id="mem_xyz789",
content="User strongly prefers very concise, bullet-point responses",
tags=["communication_style", "high_priority"]
)
const updated = await sb.memory.update('mem_xyz789', {
content: 'User strongly prefers very concise, bullet-point responses',
tags: ['communication_style', 'high_priority']
});
Delete Memory
DELETE /v1/memory/{memory_id}
Permanently deletes a memory and its vector embedding.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
memory_id | string | ✅ Yes | Memory ID to delete |
Example
curl -X DELETE https://api.statebase.org/v1/memory/mem_xyz789 \
-H "X-API-Key: sb_your_key"
sb.memory.delete(memory_id="mem_xyz789")
await sb.memory.delete('mem_xyz789');
List Memories
GET /v1/memory
Lists all memories with optional filtering.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | No | Filter by session |
user_id | string | No | Filter by user |
type | string | No | Filter by type |
tags | string | No | Comma-separated tags to filter by |
limit | integer | No | Max results (default: 20, max: 100) |
starting_after | string | No | Memory ID for pagination |
Example
curl "https://api.statebase.org/v1/memory?session_id=sess_abc123&type=preference&limit=10" \
-H "X-API-Key: sb_your_key"
memories = sb.memory.list(
session_id="sess_abc123",
type="preference",
limit=10
)
for mem in memories:
print(f"{mem.type}: {mem.content}")
const memories = await sb.memory.list({
sessionId: 'sess_abc123',
type: 'preference',
limit: 10
});
Memory Types
Use these standard types for consistency:| Type | Description | Example |
|---|---|---|
fact | Objective information | "User's company is Acme Corp" |
preference | User preferences | "User prefers dark mode" |
event | Historical events | "User completed onboarding on 2026-01-15" |
policy | Rules and policies | "Always ask for confirmation before deleting data" |
observation | Behavioral insights | "User tends to ask follow-up questions" |
general | Uncategorized | Any other memory |
Common Use Cases
1. User Preferences
# Store preference
sb.memory.add(
session_id=session.id,
content="User prefers metric units (Celsius, kilometers)",
type="preference",
tags=["units", "localization"]
)
# Later, retrieve preferences
prefs = sb.memory.search(
query="user measurement preferences",
session_id=session.id,
type="preference"
)
2. Conversation Summaries
# After long conversation, summarize and store
summary = llm.summarize(conversation_history)
sb.memory.add(
session_id=session.id,
content=summary,
type="event",
tags=["conversation_summary"],
metadata={"turn_count": len(conversation_history)}
)
3. Knowledge Base
# Store company policies
sb.memory.add(
session_id=session.id,
content="Refund policy: 30 days for unopened items, 14 days for opened items",
type="policy",
tags=["refunds", "customer_service"]
)
# Search when needed
policies = sb.memory.search(
query="refund policy",
type="policy",
limit=3
)
4. User History
# Track important events
sb.memory.add(
session_id=session.id,
content="User successfully completed payment for $299.99 order",
type="event",
tags=["transaction", "payment"],
metadata={
"amount": 299.99,
"order_id": "ORD-12345",
"timestamp": datetime.now().isoformat()
}
)
Best Practices
✅ Do This
- Use semantic search instead of keyword matching
- Tag memories for easy filtering
- Set confidence scores in metadata
- Consolidate similar memories (avoid duplicates)
- Use specific memory types (not just “general”)
❌ Avoid This
- Don’t store temporary data (use session state instead)
- Don’t store sensitive data unencrypted (use metadata encryption)
- Don’t create too many memories (focus on high-signal information)
- Don’t forget to clean up (delete outdated memories)
Embeddings
StateBase automatically generates vector embeddings using:- Default: Google Gemini (
text-embedding-004) - Alternative: OpenAI (
text-embedding-3-small)
Error Responses
| Status Code | Error Code | Description |
|---|---|---|
| 400 | invalid_request | Missing or invalid fields |
| 404 | memory_not_found | Memory doesn’t exist |
| 404 | session_not_found | Session doesn’t exist |
| 413 | content_too_large | Content exceeds 10,000 chars |
| 429 | rate_limit_exceeded | Too many requests |
Next Steps
- Sessions API: Manage session lifecycle
- Turns API: Log conversations
- RAG Agents Pattern: Build retrieval-augmented agents
Key Takeaway: Memory is how your agent learns over time. Use it for facts that should persist across sessions.