NewRelease 0.12.3 is out: Engine v0.12.3, Dashboard 0.5.2, Helm 0.12.3, the four SDKs, CLI 0.8.2 and MCP 0.12.3Release 0.12.3 is outSee what's new →
⚡ 5 MINUTE SETUP

Quick Start

This guide takes you from nothing to a running Dakera v0.12.3 server with persistent agent memory, in about five minutes. You start the server with Docker, store three memories, recall them with a natural-language question, and group memories into a session, using curl or the Python, TypeScript, Go or Rust SDK.

It is written for developers trying Dakera for the first time. Upgrading an existing v0.11.108 deployment? Read Upgrading to v0.12 instead.

Watch it run first: below is a real session of the five steps on this page, recorded on a clean machine with the same commands and values. Long waits are shortened and marked with their real length.

Quick Start, recorded
Recorded 2026-10-17 · Dakera 0.12.2 · dakera (PyPI) 0.14.0 · Python 3.13.16 · waits shortened
docker run -d \
--name dakera \
--restart unless-stopped \
-p 3000:3000 \
-e DAKERA_ROOT_API_KEY=my-dev-key \
-e DAKERA_STORAGE=filesystem \
-v dakera-data:/data \
-v dakera-models:/app/models \
ghcr.io/dakera-ai/dakera:0.12.2
809bac332c2141b679e1cdd3fc1ae1081ab72fb92529a18f57564a80ddb85cc8
curl http://localhost:3000/health/ready
{"downloads":[],"ready":false,"reason":"starting","starting":true,"version":"0.12.2"}
curl http://localhost:3000/health/ready
{"downloads":[],"ready":false,"reason":"loading the embedding model bge-large","starting":true,"version":"0.12.2"}
… 12 s later
curl http://localhost:3000/health/ready
{"ready":true,"version":"0.12.2","checks":{"storage":{"status":"ok","message":null},"embedding_engine":{"status":"ok","message":null},"tiered_engine":{"status":"disabled","message":null}}}
curl http://localhost:3000/health
{"service":"dakera","status":"healthy","version":"0.12.2","build_sha":"8a2e34ee064ee53203497d73a921c1f969ee162c","unreadable_records":0,"corrupt_records":0,"degraded":[],"embed_migration":{"state":"pending","remaining":0,"reembedded":0,"skipped":0},"config_warnings":[]}
python3 -m venv .venv
… 3.2 s later
source .venv/bin/activate
pip install dakera
Collecting dakera
Downloading dakera-0.14.0-py3-none-any.whl.metadata (20 kB)
… (16 lines trimmed)
Installing collected packages: urllib3, idna, charset_normalizer, certifi, requests, dakera
Successfully installed certifi-2026.7.22 charset_normalizer-3.5.2 dakera-0.14.0 idna-3.20 requests-2.34.2 urllib3-2.8.0
export DAKERA_API_KEY=my-dev-key
cat > client.py <<'EOF'
import os
from dakera import DakeraClient
client = DakeraClient(
base_url=os.getenv("DAKERA_API_URL", "http://localhost:3000"),
api_key=os.getenv("DAKERA_API_KEY")
)
EOF
cat > store.py <<'EOF'
from client import client
# Memory 1: UI preference
m1 = client.store_memory(
agent_id="my-agent",
content="User prefers dark mode and minimal UI animations",
importance=0.8,
tags=["preference", "ui"]
)
# Memory 2: Team process
m2 = client.store_memory(
agent_id="my-agent",
content="Team standup is every morning at 9:30 AM in the #daily channel",
importance=0.7,
tags=["team", "process"]
)
# Memory 3: Infrastructure
m3 = client.store_memory(
agent_id="my-agent",
content="The deployment pipeline uses GitHub Actions with a staging environment on port 8080",
importance=0.9,
tags=["infra", "deployment"]
)
for m in (m1, m2, m3):
print(m["id"], m["memory_type"], m["importance"], m["tags"])
EOF
python store.py
mem_18df49640f00b87e episodic 0.8 ['preference', 'ui']
mem_18df49641a1c3b15 episodic 0.7 ['team', 'process']
mem_18df49642624661e episodic 0.9 ['infra', 'deployment']
cat > recall.py <<'EOF'
from client import client
response = client.recall(
agent_id="my-agent",
query="how does the team deploy code?"
)
for m in response.memories:
print(f"{m.content} (score: {m.score:.2f})")
EOF
python recall.py
The deployment pipeline uses GitHub Actions with a staging environment on port 8080 (score: 0.46)
User prefers dark mode and minimal UI animations (score: 0.41)
Team standup is every morning at 9:30 AM in the #daily channel (score: 0.38)
cat > session.py <<'EOF'
from client import client
# Start a session
session = client.start_session(
agent_id="my-agent",
metadata={"task": "onboarding"}
)
print("started", session["id"])
# Store a memory within the session
m = client.store_memory(
agent_id="my-agent",
session_id=session["id"],
content="User completed the quickstart guide and stored 3 test memories",
importance=0.6
)
print("stored ", m["id"], "in", m["session_id"])
# End the session with a summary
ended = client.end_session(
session_id=session["id"],
summary="Completed user onboarding — stored preferences, team info, and infra context"
)
print("ended ", ended["session"]["ended_reason"], "·", ended["memory_count"], "memory")
EOF
python session.py
started sess_18df496481a9c40f
stored mem_18df496489b36724 in sess_18df496481a9c40f
ended client · 1 memory
Recorded on a shared 4-core Linux container with Docker 29.8.2 and the server image already pulled; waits shortened.16 commands · 21 s real time
Try it first — no install needed — The interactive playground at dakera.ai/playground lets you store memories, run semantic recall, explore the knowledge graph, and compare LLM memory quality right in the browser. Use it to get a feel for the API before spinning up your own server.
Prerequisites
  • Docker installed and running
  • curl or a REST client (for testing without an SDK)
  • Python 3.10+, Node.js 20.12+, Go 1.21+ or a current stable Rust toolchain (depending on your SDK choice)
  • ~5 minutes to complete
1

Run the server

Pull and start the v0.12.3 image from GitHub Container Registry. Data is kept on the dakera-data volume:

docker run -d \
  --name dakera \
  --restart unless-stopped \
  -p 3000:3000 \
  -e DAKERA_ROOT_API_KEY=my-dev-key \
  -e DAKERA_STORAGE=filesystem \
  -v dakera-data:/data \
  -v dakera-models:/app/models \
  ghcr.io/dakera-ai/dakera:0.12.3

DAKERA_ROOT_API_KEY is required while authentication is on (the default): with no key configured the server logs an error and exits. Set DAKERA_AUTH_ENABLED=false only for local development. Without DAKERA_STORAGE=filesystem the server keeps data in memory only (the default storage is memory). The dakera-models volume (/app/models) holds models the image does not ship and is optional with the default models.

Verify the server is running:

curl http://localhost:3000/health/ready   # 200 once the models are loaded
curl http://localhost:3000/health

The image ships its default models, so a cold start is ready in a few seconds (4.4 s measured) without network access. While models load, /health and /health/ready answer 503 with progress (/health/live answers 200); once loaded, /health reports the version and any config_warnings. Upgrading from v0.11? See Upgrading to v0.12.

Expected response:

{
  "service": "dakera",
  "status": "healthy",
  "version": "0.12.3",
  "unreadable_records": 0,
  "corrupt_records": 0,
  "degraded": [],
  "config_warnings": []
}

Docker images add a build_sha field. status is "degraded" when a component is running without something it should have (see degraded); config_warnings lists startup configuration the server accepted although it is not what it should be. For a readiness probe use GET /health/ready (200 once the embedding model is loaded and storage answers); for liveness use GET /health/live.

Use your server's public IP instead of localhost if running remotely. See Deployment for Compose, K8s, and Helm.

Troubleshooting

Port 3000 already in use — Change the host port: -p 3301:3000 and use :3301 in subsequent commands.

Cannot connect to Docker daemon — Start Docker Desktop (macOS/Windows) or run sudo systemctl start docker (Linux).

Connection refused on health check — The container is still starting. The REST port binds before the models load, so once it accepts connections /health/live answers 200 while /health/ready answers 503 with the phase and download progress; wait for /health/ready to answer 200 before the first request (other routes answer 503 + Retry-After: 5 meanwhile). Check container logs with docker logs dakera.

2

Install an SDK

python3 -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install dakera
npm install @dakera-ai/dakera
# yarn add @dakera-ai/dakera | pnpm add @dakera-ai/dakera
go get github.com/dakera-ai/dakera-go
# Cargo.toml
[dependencies]
dakera-client = "0.12"
tokio = { version = "1", features = ["full"] }
brew install dakera-ai/tap/dk   # or see the CLI page for apt, dnf and install scripts
export DAKERA_API_KEY=my-dev-key
dk init # interactive setup: server URL and default namespace
3

Store memories

Store three memories to see how semantic search works. Set your server URL and API key, then store each one:

# Memory 1: UI preference
curl -X POST http://localhost:3000/v1/memory/store \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "my-agent",
    "content": "User prefers dark mode and minimal UI animations",
    "importance": 0.8,
    "tags": ["preference", "ui"]
  }'

# Memory 2: Team process
curl -X POST http://localhost:3000/v1/memory/store \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "my-agent",
    "content": "Team standup is every morning at 9:30 AM in the #daily channel",
    "importance": 0.7,
    "tags": ["team", "process"]
  }'

# Memory 3: Infrastructure
curl -X POST http://localhost:3000/v1/memory/store \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "my-agent",
    "content": "The deployment pipeline uses GitHub Actions with a staging environment on port 8080",
    "importance": 0.9,
    "tags": ["infra", "deployment"]
  }'
import os
from dakera import DakeraClient

# export DAKERA_API_URL=http://<YOUR_SERVER_IP>:3000
# export DAKERA_API_KEY=my-dev-key

client = DakeraClient(
    base_url=os.getenv("DAKERA_API_URL", "http://localhost:3000"),
    api_key=os.getenv("DAKERA_API_KEY")
)

# Memory 1: UI preference
client.store_memory(
    agent_id="my-agent",
    content="User prefers dark mode and minimal UI animations",
    importance=0.8,
    tags=["preference", "ui"]
)

# Memory 2: Team process
client.store_memory(
    agent_id="my-agent",
    content="Team standup is every morning at 9:30 AM in the #daily channel",
    importance=0.7,
    tags=["team", "process"]
)

# Memory 3: Infrastructure
client.store_memory(
    agent_id="my-agent",
    content="The deployment pipeline uses GitHub Actions with a staging environment on port 8080",
    importance=0.9,
    tags=["infra", "deployment"]
)
import { DakeraClient } from '@dakera-ai/dakera';

const client = new DakeraClient({
  baseUrl: process.env.DAKERA_API_URL ?? 'http://localhost:3000',
  apiKey: process.env.DAKERA_API_KEY,
});

// Memory 1: UI preference
await client.storeMemory('my-agent', {
  content: 'User prefers dark mode and minimal UI animations',
  importance: 0.8,
  tags: ['preference', 'ui'],
});

// Memory 2: Team process
await client.storeMemory('my-agent', {
  content: 'Team standup is every morning at 9:30 AM in the #daily channel',
  importance: 0.7,
  tags: ['team', 'process'],
});

// Memory 3: Infrastructure
await client.storeMemory('my-agent', {
  content: 'The deployment pipeline uses GitHub Actions with a staging environment on port 8080',
  importance: 0.9,
  tags: ['infra', 'deployment'],
});
import (
    "context"
    "fmt"
    "os"

    dakera "github.com/dakera-ai/dakera-go"
)

ctx := context.Background()
serverURL := os.Getenv("DAKERA_API_URL")
if serverURL == "" { serverURL = "http://localhost:3000" }

client := dakera.NewClientWithOptions(dakera.ClientOptions{
    BaseURL: serverURL,
    APIKey:  os.Getenv("DAKERA_API_KEY"),
})

// Memory 1: UI preference
imp1 := float32(0.8)
_, err := client.StoreMemory(ctx, "my-agent", dakera.StoreMemoryRequest{
    Content:    "User prefers dark mode and minimal UI animations",
    Importance: &imp1,
    Tags:       []string{"preference", "ui"},
})
if err != nil { panic(err) }

// Memory 2: Team process
imp2 := float32(0.7)
_, err = client.StoreMemory(ctx, "my-agent", dakera.StoreMemoryRequest{
    Content:    "Team standup is every morning at 9:30 AM in the #daily channel",
    Importance: &imp2,
    Tags:       []string{"team", "process"},
})

// Memory 3: Infrastructure
imp3 := float32(0.9)
_, err = client.StoreMemory(ctx, "my-agent", dakera.StoreMemoryRequest{
    Content:    "The deployment pipeline uses GitHub Actions with a staging environment on port 8080",
    Importance: &imp3,
    Tags:       []string{"infra", "deployment"},
})
use dakera_client::{DakeraClient, StoreMemoryRequest};

let client = DakeraClient::builder(
    std::env::var("DAKERA_API_URL").unwrap_or_else(|_| "http://localhost:3000".into()),
)
.api_key(std::env::var("DAKERA_API_KEY").unwrap_or_default())
.build()?;

// Memory 1: UI preference
client.store_memory(
    StoreMemoryRequest::new("my-agent", "User prefers dark mode and minimal UI animations")
        .with_importance(0.8)
        .with_tags(vec!["preference".into(), "ui".into()]),
).await?;

// Memory 2: Team process
client.store_memory(
    StoreMemoryRequest::new("my-agent", "Team standup is every morning at 9:30 AM in the #daily channel")
        .with_importance(0.7)
        .with_tags(vec!["team".into(), "process".into()]),
).await?;

// Memory 3: Infrastructure
client.store_memory(
    StoreMemoryRequest::new("my-agent", "The deployment pipeline uses GitHub Actions with a staging environment on port 8080")
        .with_importance(0.9)
        .with_tags(vec!["infra".into(), "deployment".into()]),
).await?;

Each store call returns the stored memory and the embedding time (the SDKs unwrap memory for you; values here are illustrative):

{
  "memory": {
    "id": "mem_18a3b7c92d4f1e06",
    "memory_type": "episodic",
    "content": "User prefers dark mode and minimal UI animations",
    "agent_id": "my-agent",
    "importance": 0.8,
    "tags": ["preference", "ui"],
    "created_at": 1778827500,
    "last_accessed_at": 1778827500,
    "access_count": 0
  },
  "embedding_time_ms": 42
}
4

Now ask a question that doesn't match the exact wording of any memory. Dakera's semantic search finds the right one anyway:

curl -X POST http://localhost:3000/v1/memory/recall \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "my-agent", "query": "how does the team deploy code?"}'
response = client.recall(
    agent_id="my-agent",
    query="how does the team deploy code?"
)

for m in response.memories:
    print(f"{m.content} (score: {m.score:.2f})")
const response = await client.recall('my-agent', 'how does the team deploy code?');

response.memories.forEach(m =>
  console.log(`${m.content} (score: ${m.score.toFixed(2)})`)
);
response, err := client.Recall(ctx, "my-agent", dakera.RecallRequest{
    Query: "how does the team deploy code?",
})

for _, m := range response.Memories {
    fmt.Printf("%s (score: %.2f)\n", m.Content, m.Score)
}
use dakera_client::RecallRequest;

let response = client
    .recall(RecallRequest::new("my-agent", "how does the team deploy code?"))
    .await?;

for m in &response.memories {
    println!("{} (score: {:.2})", m.content, m.score);
}

Expected response shape — Memory 3 should rank highest even though your query said "deploy code" while the memory says "deployment pipeline":

{
  "memories": [
    {
      "memory": {
        "id": "mem_18a3b7ca1e5f2a09",
        "content": "The deployment pipeline uses GitHub Actions with a staging environment on port 8080",
        "importance": 0.9,
        "tags": ["infra", "deployment"],
        "created_at": 1778827502
        // …agent_id, memory_type, last_accessed_at, access_count
      },
      "score": 0.92,
      "smart_score": 0.81
    },
    // …the standup memory, with a lower score
  ],
  "query_embedding_time_ms": 18,
  "search_time_ms": 6,
  "rerank_report": { "applied": true, "candidates": 3 }
}

The scores above are illustrative. rerank_report says whether the cross-encoder ran, over how many candidates and, when it did not, why (skipped); the SDKs expose each result's memory fields and score directly.

Semantic search in action. You queried "how does the team deploy code?" — Dakera found the deployment memory even though it doesn't contain the word "deploy." This is the core value: your agents don't need exact keyword matches to recall relevant context.
5

Group memories with sessions

Sessions group related memories, for example one conversation, task or debugging run:

# Start a session
curl -X POST http://localhost:3000/v1/sessions/start \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "my-agent", "metadata": {"task": "onboarding"}}'
# → {"session": {"id": "sess_18a3b8e01a2c3d04", ...}}

# Store a memory within the session
curl -X POST http://localhost:3000/v1/memory/store \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "my-agent",
    "session_id": "sess_18a3b8e01a2c3d04",
    "content": "User completed the quickstart guide and stored 3 test memories",
    "importance": 0.6
  }'

# End the session with a summary
curl -X POST http://localhost:3000/v1/sessions/sess_18a3b8e01a2c3d04/end \
  -H "Authorization: Bearer my-dev-key" \
  -H "Content-Type: application/json" \
  -d '{"summary": "Completed user onboarding — stored preferences, team info, and infra context"}'
# Start a session
session = client.start_session(
    agent_id="my-agent",
    metadata={"task": "onboarding"}
)

# Store a memory within the session
client.store_memory(
    agent_id="my-agent",
    session_id=session["id"],
    content="User completed the quickstart guide and stored 3 test memories",
    importance=0.6
)

# End the session with a summary
client.end_session(
    session_id=session["id"],
    summary="Completed user onboarding — stored preferences, team info, and infra context"
)
// Start a session
const session = await client.startSession('my-agent', { task: 'onboarding' });

// Store a memory within the session
await client.storeMemory('my-agent', {
  session_id: session.id,
  content: 'User completed the quickstart guide and stored 3 test memories',
  importance: 0.6,
});

// End the session with a summary (dakera-js 0.12.2 and later)
await client.endSession(session.id, { summary: 'Completed the quickstart' });
// Start a session
session, err := client.StartSession(ctx, dakera.StartSessionRequest{
    AgentID:  "my-agent",
    Metadata: map[string]interface{}{"task": "onboarding"},
})

// Store a memory within the session
sessImp := float32(0.6)
client.StoreMemory(ctx, "my-agent", dakera.StoreMemoryRequest{
    SessionID:  session.ID,
    Content:    "User completed the quickstart guide and stored 3 test memories",
    Importance: &sessImp,
})

// End the session
client.EndSession(ctx, session.ID) // dakera-go v0.12.2 cannot send a summary
// Start a session (start_session_with_metadata attaches metadata)
let session = client.start_session("my-agent").await?;

// Store a memory within the session
client.store_memory(
    StoreMemoryRequest::new("my-agent", "User completed the quickstart guide and stored 3 test memories")
        .with_importance(0.6)
        .with_session(session.id.clone()),
).await?;

// End the session with a summary
client.end_session(
    &session.id,
    Some("Completed user onboarding — stored preferences, team info, and infra context".to_string()),
).await?;

A session carries metadata and, when it ends, an optional summary (or, over REST, "auto_summarize": true to have the server write one). Pass session_id in a recall request to search only that session's memories. The current Go and TypeScript SDKs end a session without a summary.

Your agent has persistent memory. Semantic search, session grouping, and natural language recall — all running on your infrastructure, surviving restarts, growing with usage.

What's next?

Add memory to Claude / Cursor Connect through MCP, no code required Explore the full API 130+ endpoints for memory, sessions, vectors, and admin See production patterns RAG pipelines, conversation memory, multi-agent workflows Dakera Cloud is coming Join the waitlist for managed hosting →
Stay sharp on agent memory
Benchmark results, SDK releases, and production patterns. Under 500 words per issue.
✓ You're in. First issue lands soon — watch for Dakera in your inbox.