PUBLIC ALPHA

Dakera Documentation

The memory engine for AI agents. A single Rust binary that replaces five separate services — vector search, full-text search, embeddings, agent memory, and knowledge graphs.

Public Alpha — Dakera is live. Self-hosted binary, all SDKs, CLI, and MCP server are fully operational and available now. Dakera Cloud (managed hosting, SLA, team monitoring) is coming next — join the waitlist →

What Dakera replaces

Instead of runningDakera provides
Qdrant · Pinecone · WeaviateHNSW, IVF, and SPFresh vector indexes
Elasticsearch · OpenSearchBM25 full-text search engine
OpenAI / Cohere embeddings APIOn-device ONNX inference — zero API calls
Redis / Postgres memory layerDecay-weighted agent memory with sessions
Neo4j knowledge graphBuilt-in entity graph with cross-agent network
87.6% on LoCoMo — Dakera's memory engine scores 87.6% on the full LoCoMo benchmark (50 sessions, 1,540 questions, May 2026). Read the methodology →

Start here

I want to…Go to
Get Dakera running in 5 minutesQuick Start →
Add memory to Claude Desktop, Code, or CursorMCP Server →
Integrate from PythonPython SDK →
Integrate from TypeScript / NodeTypeScript SDK →
Integrate from Go or RustGo SDK → · Rust SDK →
Use from the command lineCLI Reference →
See all configuration optionsConfiguration →
Deploy to productionDeployment →
Understand the retrieval pipelineArchitecture →
Security hardening for productionSecurity →
Use with LangChain, CrewAI, LlamaIndex, or AutoGenIntegrations →

Key capabilities

Hybrid Retrieval

Vector + BM25 full-text combined in one call. Reciprocal Rank Fusion merges results. Sub-10ms for millions of vectors.

On-device Embeddings

MiniLM, BGE, and E5 models run via ONNX at startup. No external embedding API required.

Memory Decay

Access-weighted importance scoring. Memories fade naturally when not recalled. Configurable half-life.

Knowledge Graphs

Entity extraction, relationship storage, and cross-agent network visualization — no schema design required.

Session Management

Group memories by agent session. Auto-generate session summaries. Per-session deduplication.

MCP Native

83 tools for Claude Desktop, Claude Code, Cursor, and Windsurf. No code changes required.

Packages

PackageVersionLanguageInstallRegistry
dakera-py0.11.54Python 3.10+pip install dakeraPyPI
dakera-js0.11.54Node 20+ / Bun / Denonpm install dakeranpm
dakera-rs0.11.54Rust 1.70+cargo add dakera-clientcrates.io
dakera-go0.11.54Go 1.21+go get github.com/dakera-ai/dakera-gopkg.go.dev
dakera-cli0.5.5Rust 1.70+cargo install dakera-clicrates.io
dakera-mcp0.9.8Rust binarydownload binary or docker pullGitHub Releases
dakera0.11.55Rust serverdocker pull ghcr.io/dakera-ai/dakera:latestDocker Hub

Release artifacts

Every release publishes pre-built binaries, Docker images, and source archives. All artifacts are signed and checksummed.

ArtifactWhere to find it
Server binary + Docker imagehub.docker.com/r/dakera/dakera
MCP binary (Linux x64/arm64, macOS, Windows)github.com/dakera-ai/dakera-mcp/releases
Helm chart OCI packageoci://ghcr.io/dakera-ai/dakera-helm/dakera
Helm chart repo (dakera-helm)ArtifactHub · GitHub Pages index
Python SDKpypi.org/project/dakera/#history
TypeScript SDKnpmjs.com/package/dakera
Rust SDKcrates.io/crates/dakera-client/versions
Go SDKpkg.go.dev/github.com/dakera-ai/dakera-go
Deploy repo (Docker Compose, Kubernetes)github.com/dakera-ai/dakera-deploy

Quick Start

Store your first memory in under 10 minutes.

1

Run the server

Pull and start the official Docker image from GitHub Container Registry:

docker run -d \
  --name dakera \
  --restart unless-stopped \
  -p 3300:3300 \
  -e DAKERA_PORT=3300 \
  -e DAKERA_ROOT_API_KEY=my-dev-key \
  -e DAKERA_STORAGE=filesystem \
  -e DAKERA_STORAGE_PATH=/data \
  -v dakera-data:/data \
  ghcr.io/dakera-ai/dakera:latest

Verify it's healthy (replace localhost with your server's IP if running remotely):

curl http://localhost:3300/health
# {"service":"dakera","status":"healthy","version":"0.11.55"}

# Remote server:
curl http://<YOUR_SERVER_IP>:3300/health
Deploying to a cloud VM? Use the server's public IP (http://<SERVER_IP>:3300) in all SDK and MCP configs below. See Deployment for Docker Compose, Kubernetes, and Helm options.
2

Install a SDK

pip install dakera
npm install dakera
# yarn add dakera | pnpm add dakera
go get github.com/dakera-ai/dakera-go
# Cargo.toml
[dependencies]
dakera-client = "0.11"
cargo install dakera-cli
dk init # interactive setup wizard
3

Store a memory

Use env vars to configure the server URL — works for local and remote servers:

import os
from dakera import DakeraClient

# Configure via env vars (recommended) or pass directly:
# export DAKERA_URL=http://<YOUR_SERVER_IP>:3300
# export DAKERA_API_KEY=my-dev-key

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

client.memories.store(
    agent_id="my-agent",
    content="User prefers dark mode",
    importance=0.8,
    tags=["preference", "ui"]
)
import { DakeraClient } from 'dakera';

// Configure via env vars (recommended):
// DAKERA_URL=http://<YOUR_SERVER_IP>:3300
// DAKERA_API_KEY=my-dev-key

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

await client.memories.store({
  agentId: 'my-agent',
  content: 'User prefers dark mode',
  importance: 0.8,
  tags: ['preference', 'ui'],
});
import (
    dakera "github.com/dakera-ai/dakera-go"
    "os"
)

serverURL := os.Getenv("DAKERA_URL")
if serverURL == "" { serverURL = "http://localhost:3300" }

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

client.Memories.Store(ctx, &dakera.StoreRequest{
    AgentID:    "my-agent",
    Content:    "User prefers dark mode",
    Importance: 0.8,
    Tags:       []string{"preference", "ui"},
})
use dakera_client::{DakeraClient, Config, memory::StoreRequest};

let client = DakeraClient::new(Config {
    base_url: std::env::var("DAKERA_URL")
        .unwrap_or_else(|_| "http://localhost:3300".into()),
    api_key: std::env::var("DAKERA_API_KEY").ok(),
    ..Default::default()
})?;

client.memories().store(StoreRequest {
    agent_id: "my-agent".into(),
    content: "User prefers dark mode".into(),
    importance: Some(0.8),
    tags: vec!["preference".into()],
    ..Default::default()
}).await?;
4

Recall memories

response = client.memories.recall(
    agent_id="my-agent",
    query="what UI preferences does the user have?"
)

for m in response.memories:
    print(m.content, m.importance, m.score)
const response = await client.memories.recall({
  agentId: 'my-agent',
  query: 'what UI preferences does the user have?',
});

response.memories.forEach(m => console.log(m.content, m.importance, m.score));
You're done. Your agent now has persistent memory. Recalled memories get automatic importance boost — frequently accessed memories stay relevant longer.

What's next?

Add to Claude / Cursor → How memory works → API Reference → LangChain & framework integrations →

MCP Server

Dakera ships as a native MCP server — 83 tools for Claude Desktop, Claude Code, Cursor, Windsurf, and any MCP-compatible client. No code changes required.

What is MCP? The Model Context Protocol allows AI assistants to call external tools. Dakera exposes its complete API as 83 callable MCP tools.

Install the MCP binary

Download a pre-built binary in one command — no Rust or build tools required:

# Linux x64 (also works in WSL)
curl -fsSL https://github.com/dakera-ai/dakera-mcp/releases/latest/download/dakera-mcp-linux-x64.tar.gz \
  | tar -xz -C /usr/local/bin
chmod +x /usr/local/bin/dakera-mcp

# Linux arm64
curl -fsSL https://github.com/dakera-ai/dakera-mcp/releases/latest/download/dakera-mcp-linux-arm64.tar.gz \
  | tar -xz -C /usr/local/bin

# Verify
dakera-mcp --version
# macOS Apple Silicon (M1/M2/M3)
curl -fsSL https://github.com/dakera-ai/dakera-mcp/releases/latest/download/dakera-mcp-macos-arm64.tar.gz \
  | tar -xz -C /usr/local/bin

# macOS Intel
curl -fsSL https://github.com/dakera-ai/dakera-mcp/releases/latest/download/dakera-mcp-macos-x64.tar.gz \
  | tar -xz -C /usr/local/bin

# Verify
dakera-mcp --version
# PowerShell — Windows x64
Invoke-WebRequest `
  -Uri "https://github.com/dakera-ai/dakera-mcp/releases/latest/download/dakera-mcp-windows-x64.zip" `
  -OutFile "$env:TEMP\dakera-mcp.zip"
Expand-Archive "$env:TEMP\dakera-mcp.zip" -DestinationPath "C:\tools\dakera-mcp" -Force

# Add C:\tools\dakera-mcp to your PATH, then verify:
dakera-mcp --version
# Requires Rust 1.70+
git clone https://github.com/dakera-ai/dakera-mcp
cd dakera-mcp
cargo build --release
# binary: ./target/release/dakera-mcp

Or browse all releases and checksums on the GitHub Releases page.

Point the MCP server at your Dakera instance

Set two environment variables — DAKERA_API_URL is the address of your running Dakera server (the IP or hostname where you deployed it), and DAKERA_API_KEY is the root key you set when starting the server.

Where is my server? If you started Dakera with docker run -p 3300:3300 ... on a remote host, use http://<SERVER_IP>:3300. For a local dev machine use http://localhost:3300. For Kubernetes with an ingress, use your ingress hostname.
# Quick test — verify connectivity before wiring up any client:
export DAKERA_API_URL=http://<YOUR_SERVER_IP>:3300
export DAKERA_API_KEY=<your-api-key>
dakera-mcp --test-connection
# Connected to Dakera v0.11.55 — 83 tools available

Environment variables

VariableDescriptionDefault
DAKERA_API_URLDakera server base URL — set to your server addresshttp://localhost:3300
DAKERA_API_KEYAPI key for authenticationnone
RUST_LOGLog level (e.g. dakera_mcp=debug)dakera_mcp=info

Connect your AI client

In all configs below, replace <YOUR_SERVER_IP> with your Dakera server address and <your-api-key> with your root API key. Use /usr/local/bin/dakera-mcp (Linux/macOS) or the full path where you extracted the binary.

// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
// %APPDATA%\Claude\claude_desktop_config.json (Windows)
{
  "mcpServers": {
    "dakera": {
      "command": "/usr/local/bin/dakera-mcp",
      "env": {
        "DAKERA_API_URL": "http://<YOUR_SERVER_IP>:3300",
        "DAKERA_API_KEY": "<your-api-key>"
      }
    }
  }
}

Restart Claude Desktop after editing. Use Settings → Developer → MCP Servers to verify "dakera" shows as connected.

// .mcp.json in your project root (or ~/.claude/settings.json for global)
{
  "mcpServers": {
    "dakera": {
      "command": "/usr/local/bin/dakera-mcp",
      "env": {
        "DAKERA_API_URL": "http://<YOUR_SERVER_IP>:3300",
        "DAKERA_API_KEY": "<your-api-key>"
      }
    }
  }
}

Run claude mcp list to confirm dakera is loaded. Run claude mcp get dakera to see connection status.

// ~/.cursor/mcp.json
{
  "mcpServers": {
    "dakera": {
      "command": "/usr/local/bin/dakera-mcp",
      "env": {
        "DAKERA_API_URL": "http://<YOUR_SERVER_IP>:3300",
        "DAKERA_API_KEY": "<your-api-key>"
      }
    }
  }
}
// ~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "dakera": {
      "command": "/usr/local/bin/dakera-mcp",
      "env": {
        "DAKERA_API_URL": "http://<YOUR_SERVER_IP>:3300",
        "DAKERA_API_KEY": "<your-api-key>"
      }
    }
  }
}
// ~/.config/zed/settings.json
{
  "context_servers": {
    "dakera": {
      "command": {
        "path": "/usr/local/bin/dakera-mcp",
        "env": {
          "DAKERA_API_URL": "http://<YOUR_SERVER_IP>:3300",
          "DAKERA_API_KEY": "<your-api-key>"
        }
      }
    }
  }
}
# Open WebUI — add as an external tool server
# Admin Panel → Settings → Tools → Add Tool Server

Server URL:  http://<YOUR_SERVER_IP>:3300
# Or run the MCP binary as a sidecar and point at its HTTP bridge:
DAKERA_API_URL=http://<YOUR_SERVER_IP>:3300 \
  DAKERA_API_KEY=<your-api-key> \
  dakera-mcp --http-bridge --port 8811

# Then add http://localhost:8811 as tool server in Open WebUI

Verify the connection

# In Claude Code — ask Claude to use the dakera MCP server:
List the Dakera MCP tools available.
# Expected: Claude responds with 83 tool names across 8 categories

# Or test the underlying server directly:
curl -s -H "Authorization: Bearer <your-api-key>" \
  http://<YOUR_SERVER_IP>:3300/health
# {"service":"dakera","status":"healthy","version":"0.11.55"}

Tool categories (83 tools)

CategoryKey toolsCount
Memorystore, recall, batch_recall, search, memory_get, memory_update, memory_importance, forget, consolidate, batch_forget10
Memory Feedbackmemory_feedback, memory_feedback_get, agent_feedback_summary3
Sessionssession_start, session_end, session_list, session_get, session_memories5
Agentsagent_stats, agent_memories, agent_sessions3
Knowledgeknowledge_graph, knowledge_summarize, knowledge_deduplicate, knowledge_network_cross_agent4
Knowledge Graphgraph_link_memory, graph_traverse, graph_path, graph_export, kg_query, kg_traverse, kg_export7
Entity Extractionextract_entities, auto_tag, memory_entities, extract, extractor_get, extractor_set, entity_types_get, entity_types_set8
Namespacesnamespace_list, namespace_get, namespace_create, namespace_delete, namespace_configure, namespace_key_create, namespace_key_list, namespace_key_delete, namespace_key_usage9
Vectorsvector_upsert, vector_upsert_columns, vector_query, vector_batch_query, vector_multi_search, vector_unified_query, vector_delete, vector_bulk_update, vector_bulk_delete, vector_count, vector_export, vector_aggregate, vector_explain, vector_warm14
Full-text & Inferencefulltext_index, fulltext_search, fulltext_stats, fulltext_delete, upsert_text, text_query, batch_query_text, hybrid_search8
Decay & AutoPilotdecay_config_get, decay_config_set, decay_stats, autopilot_trigger, autopilot_status5
Admin & Otheraudit_query, memory_export, memory_import, encryption_rotate_key, agent_feedback_summary, memory_policy_get, memory_policy_set7

Tool reference

Memory tools (10)

ToolDescription
dakera_storeStore a memory — content, type, importance score, tags, optional session link and hard-expiry timestamp
dakera_recallSemantic similarity search — returns ranked memories with scores
dakera_batch_recallFilter-based bulk recall without embedding — returns memories matching all predicates
dakera_searchAdvanced search — tag and type filters applied before ranking
dakera_memory_getRetrieve a specific memory by ID
dakera_memory_updateUpdate content, importance, or tags — re-embeds on content change
dakera_memory_importanceBatch-update importance scores for multiple memories
dakera_forgetDelete memories by ID list or tag filter
dakera_consolidateMerge a list of memories into a single summary memory
dakera_batch_forgetFilter-based bulk delete — requires Admin scope

dakera_store parameters

ParameterTypeRequiredDefaultDescription
agent_idstringYesAgent namespace to store the memory in
contentstringYesMemory content text
memory_typestringNoepisodicType: episodic, semantic, procedural, or working
importancenumberNo0.5Importance score 0.0–1.0. Higher values survive decay longer
tagsstring[]No[]Tags for categorisation and filter-based recall
session_idstringNoSession ID to associate this memory with
expires_atintegerNoHard-delete at this Unix timestamp (seconds). Bypasses decay math
// Example
{
  "agent_id": "my-agent",
  "content": "User prefers concise bullet-point summaries.",
  "memory_type": "semantic",
  "importance": 0.8,
  "tags": ["preference", "style"]
}

dakera_recall parameters

ParameterTypeDefaultDescription
agent_idstringRequired. Agent namespace to recall from
querystringRequired. Natural-language query to match against
top_kinteger5Maximum primary results to return
memory_typestringnullFilter by type
tagsstring[]nullReturn only memories carrying all listed tags
min_importancenumbernullExclude memories below this importance score
include_associatedbooleanfalseTraverse the knowledge graph from each result and include neighbouring memories
sincestring (ISO-8601)nullOnly return memories created at or after this timestamp
untilstring (ISO-8601)nullOnly return memories created at or before this timestamp

dakera_batch_recall parameters

Filter-based bulk recall — no embedding required. All fields are optional and ANDed together; at least one must be set.

ParameterTypeDescription
agent_idstringRequired. Agent namespace to recall from
tagsstring[]Return only memories with all listed tags
min_importancenumberMinimum importance score (0.0–1.0)
max_importancenumberMaximum importance score (0.0–1.0)
created_afterintegerUnix timestamp lower bound (inclusive)
created_beforeintegerUnix timestamp upper bound (inclusive)
memory_typestringFilter by type: episodic, semantic, procedural, or working
session_idstringFilter to memories from a specific session

dakera_search parameters

Tag and type filters are applied before ranking (not as a soft signal), and defaults to top_k=10.

ParameterTypeRequiredDefaultDescription
agent_idstringYesAgent namespace to search
querystringYesSemantic search query
top_kintegerNo10Number of results to return
tagsstring[]No[]Pre-filter: only search memories with all these tags
memory_typestringNonullPre-filter by memory type

dakera_memory_get / dakera_memory_update / dakera_forget

ToolParameters
dakera_memory_getmemory_id (required), agent_id (required) — returns full memory object
dakera_memory_updatememory_id, agent_id (both required) + optional content, importance, tags — re-embeds on content change
dakera_forgetagent_id (required) + memory_ids (string[]) or tags (string[]) — at least one filter required
dakera_consolidateagent_id, memory_ids (both required, min 2 IDs) — returns new summary memory; source memories are kept
dakera_memory_importanceagent_id (required), updates (required) — array of { memory_id, importance } pairs

Session tools (5)

ToolDescription
dakera_session_startStart a new session — returns session object with id
dakera_session_endEnd a session with optional summary — auto-consolidates near-duplicate memories
dakera_session_listList sessions for an agent, optionally active-only
dakera_session_getGet session details including metadata and summary
dakera_session_memoriesList all memories associated with a session
ToolRequired paramsOptional params
dakera_session_startagent_idmetadata (object)
dakera_session_endsession_idsummary (string)
dakera_session_listagent_idactive_only (boolean, default false)
dakera_session_getsession_id
dakera_session_memoriessession_id
// Start → store → end pattern
{ "agent_id": "my-agent", "metadata": { "task": "customer-support" } }  // session_start
{ "session_id": "sess_01abc", "summary": "Resolved billing question" }       // session_end

Agent tools (3)

ToolRequired paramsReturns
dakera_agent_statsagent_idmemory_count, session_count, storage_bytes, top_tags
dakera_agent_memoriesagent_idPaginated list of memories (limit, offset optional)
dakera_agent_sessionsagent_idAll sessions for the agent

Knowledge tools (4)

ToolDescription
dakera_knowledge_graphBuild a graph from a seed memory via embedding similarity — returns nodes and similarity edges
dakera_knowledge_summarizeMerge a list of memories into one summary memory (source memories kept)
dakera_knowledge_deduplicateFind and optionally merge duplicate memories by cosine similarity threshold
dakera_knowledge_network_cross_agentCross-agent memory similarity network — requires Admin scope
ToolKey parameters
dakera_knowledge_graphagent_id, memory_id (required); depth (default 2), min_similarity (default 0.7)
dakera_knowledge_summarizeagent_id, memory_ids (required, min 2); target_type (default semantic)
dakera_knowledge_deduplicateagent_id (required); threshold (default 0.9), dry_run (default true) — always run dry_run first
dakera_knowledge_network_cross_agentagent_ids, min_similarity (default 0.3), max_nodes_per_agent (default 50)

Namespace tools (9)

ToolDescription
dakera_namespace_listList all namespaces — no parameters required
dakera_namespace_getGet namespace details: dimensions, distance, vector count, index stats
dakera_namespace_createCreate a new namespace — fails if it already exists
dakera_namespace_configureCreate-or-update (idempotent) — use for application boot and CI pipelines
dakera_namespace_deleteDelete namespace and all its vectors — irreversible, requires Admin scope
dakera_namespace_key_createCreate an API key scoped to a namespace (read/write/admin)
dakera_namespace_key_listList namespace-scoped keys (metadata only — not raw key values)
dakera_namespace_key_deleteRevoke a namespace key by ID
dakera_namespace_key_usageGet request counts and last-used timestamp for a key
ToolRequiredOptional
dakera_namespace_createname, dimensiondistance (cosine/euclidean/dot, default cosine)
dakera_namespace_configurenamespace, dimensiondistance — same as create but idempotent
dakera_namespace_key_createnamespace, name, scopeextra_namespaces, expires_in_days

Vector tools (14)

ToolDescription
dakera_vector_upsertUpsert vectors: { id, values, metadata? }[]
dakera_vector_upsert_columnsColumn-format bulk upsert — more efficient for large batches
dakera_vector_queryANN similarity search by vector
dakera_vector_batch_queryRun multiple similarity searches in one request
dakera_vector_multi_searchPositive/negative vector search with optional MMR diversity
dakera_vector_unified_queryFlexible hybrid ranking: ANN, BM25, attribute, composite
dakera_vector_deleteDelete vectors by ID list
dakera_vector_bulk_updateUpdate metadata on all vectors matching a filter
dakera_vector_bulk_deleteDelete all vectors matching a filter — requires Admin scope
dakera_vector_countCount vectors in a namespace with optional filter
dakera_vector_exportPaginated export of vectors
dakera_vector_aggregateCompute Count/Sum/Avg/Min/Max with optional grouping
dakera_vector_explainExplain a query execution plan with cost estimates
dakera_vector_warmPre-load vectors into cache for faster queries
ToolRequired paramsKey optional params
dakera_vector_upsertnamespace, vectors (array of {id, values, metadata?})
dakera_vector_querynamespace, vectortop_k (default 10), filter
dakera_vector_batch_querynamespace, queries (array of {vector, top_k?, filter?})
dakera_vector_multi_searchnamespace, positive_vectorsnegative_vectors, enable_mmr (default false), mmr_lambda (default 0.5), score_threshold
dakera_vector_unified_querynamespace, rank_bytop_k, filter — rank_by forms: ["vector","ANN",[...]], ["text","BM25","query"], ["Sum",[...]]
dakera_vector_bulk_updatenamespace, filter, update
dakera_vector_bulk_deletenamespace, filter— (Admin scope required)
dakera_vector_upsert_columnsnamespace, ids, vectorsattributes (column metadata object)

Full-text & Inference tools (8)

ToolDescription
dakera_fulltext_indexIndex a document for full-text search
dakera_fulltext_searchBM25 full-text search across indexed documents
dakera_fulltext_statsFull-text index statistics (document count, token count)
dakera_fulltext_deleteRemove a document from the full-text index
dakera_upsert_textEmbed text server-side and upsert into a namespace
dakera_text_queryEmbed a query server-side and search — no client-side embedding required
dakera_batch_query_textBatch text queries with server-side embedding
dakera_hybrid_searchHybrid vector + BM25 search — semantic + keyword in one call

The Inference tools (dakera_upsert_text, dakera_text_query, dakera_batch_query_text, dakera_hybrid_search) embed on the server — you never need to compute vectors client-side. Use these for text-first workflows.

Entity Extraction tools (8)

ToolDescriptionAdded
dakera_extract_entitiesExtract named entities from text using GLiNER (local, no external API)CE-4
dakera_auto_tagAuto-tag a memory with extracted entity labelsCE-4
dakera_memory_entitiesGet entities extracted from a specific memoryCE-4
dakera_entity_types_getGet configured entity type labels for a namespace
dakera_entity_types_setSet entity type labels for a namespace
dakera_extractExtract entities/topics/keyphrases/summary via pluggable provider (OpenAI, Anthropic, Ollama, GLiNER)EXT-1
dakera_extractor_getRead the extraction provider config for a namespaceEXT-1
dakera_extractor_setSet the extraction provider for a namespaceEXT-1

dakera_extract vs dakera_auto_tag: auto_tag uses GLiNER locally and returns entity labels only. dakera_extract supports pluggable backends (OpenAI, Anthropic, Ollama) and returns richer output: entities, topics, key phrases, and a summary.

Decay & AutoPilot tools (5)

ToolRequired paramsDescription
dakera_decay_config_getagent_idRead decay policy for an agent (half-life, floor importance, access boost)
dakera_decay_config_setagent_id + policy fieldsUpdate decay policy — half-life controls how fast unaccessed memories fade
dakera_decay_statsagent_idDecay engine statistics: memories decayed, average importance drift
dakera_autopilot_triggeragent_idManually trigger an AutoPilot run (consolidation + deduplication)
dakera_autopilot_statusagent_idGet AutoPilot run status: last run time, memories consolidated, duplicates removed

Memory Feedback tools (3)

ToolRequired paramsDescription
dakera_memory_feedbackmemory_id, signalSubmit a feedback signal (positive/negative/neutral) — adjusts importance score
dakera_memory_feedback_getmemory_idGet feedback history for a memory
dakera_agent_feedback_summaryagent_idFeedback health summary for all of an agent's memories

Knowledge Graph tools (7)

ToolRequired paramsDescription
dakera_graph_link_memorysource_id, target_id, weightCreate a directed edge between two memories
dakera_graph_traversememory_id, agent_idTraverse the KG from a start node
dakera_graph_pathsource_id, target_id, agent_idFind shortest path between two memory nodes
dakera_graph_exportagent_idExport the full KG for an agent as nodes + edges
dakera_kg_queryagent_id, querySemantic search over KG nodes
dakera_kg_traverseagent_id, start_idBFS/DFS traversal of the KG
dakera_kg_exportagent_idExport KG in JSON or DOT graph format

Admin & Audit tools (7)

ToolRequired paramsDescription
dakera_audit_queryagent_idQuery the audit log — who accessed what, when. Requires Admin scope
dakera_memory_exportagent_idExport all memories for an agent as JSON
dakera_memory_importagent_id, memoriesBulk-import memories from a JSON export
dakera_encryption_rotate_keynamespaceRotate the encryption key for a namespace. Requires Admin scope
dakera_memory_policy_getagent_idGet retention and access policy for an agent
dakera_memory_policy_setagent_id + policy fieldsSet retention policy: max_memories, max_age_days, auto_purge
dakera_namespace_configureSee Namespaces sectionIdempotent namespace creation/configuration
Need cloud hosting with zero setup? Join the waitlist →

CLI Reference

v0.5.5

The dk binary lets you manage agent memory, vector operations, namespaces, and sessions from the terminal.

Installation

cargo install dakera-cli

Or download pre-built binaries from GitHub Releases.

Setup wizard

dk init

Prompts for server URL, tests connectivity, sets default namespace, and writes ~/.config/dakera/config.toml.

Global flags

FlagShortDefaultDescription
--url-uhttp://localhost:3300Server URL (overrides config and DAKERA_URL)
--format-ftableOutput format: table, json, compact
--verbose-vEnable verbose output
--api-keyenv DAKERA_API_KEYAPI key (overrides config)

Memory commands

# Store a memory
dk memory store --agent my-agent --content "User prefers dark mode" --importance 0.8

# Recall memories (semantic search)
dk memory recall --agent my-agent --query "UI preferences"

# Batch recall (filter-based)
dk memory recall --agent my-agent --tags preference --min-importance 0.7

# Forget a memory
dk memory forget mem-abc123

# List all memories for an agent
dk memory list --agent my-agent

Session commands

# Start a session
dk session start my-agent

# End a session
dk session end sess-abc123 --summary "Completed code review"

# List sessions for an agent
dk session list my-agent

Namespace commands

# Create a namespace
dk namespace create my-namespace --embedding-model MiniLML6V2

# List all namespaces
dk namespace list

# Delete a namespace
dk namespace delete my-namespace

Vector commands

# Upsert vectors from a JSON file
dk vector upsert my-namespace --file vectors.json

# Query nearest neighbors
dk vector query my-namespace --vector "[0.1,0.2,0.3]" --top-k 10

# Hybrid search
dk vector hybrid my-namespace --query "agent task completion" --top-k 5

Exit codes

CodeMeaning
0Success
2Connection error (server unreachable)
3Not found (namespace, vector, memory)
4Permission denied / authentication failure
5Invalid input / validation error
6Server-side error (5xx)

Python SDK

v0.11.54 · Python 3.10+

PyPI · GitHub · Changelog

pip install dakera              # core (sync client)
pip install dakera[async]       # include async client
pip show dakera                 # verify installed version

Client setup

Point the client at your Dakera server. Use env vars to keep the URL and key out of source code:

import os
from dakera import DakeraClient

# Recommended: configure via env vars
# export DAKERA_URL=http://<YOUR_SERVER_IP>:3300
# export DAKERA_API_KEY=your-api-key

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

Memory operations

# Store
client.memories.store(
    agent_id="my-agent",
    content="User is learning Rust",
    importance=0.8,
    tags=["learning", "programming"]
)

# Recall — semantic search over stored memories
memories = client.memories.recall(
    agent_id="my-agent",
    query="programming languages the user knows",
    top_k=10
)

# Batch recall — filter-based, no semantic search
memories = client.memories.batch_recall(
    agent_id="my-agent",
    tags=["learning"],
    min_importance=0.6
)

# Forget a specific memory
client.memories.forget(memory_id="mem-abc123")

# Update importance
client.memories.set_importance(memory_id="mem-abc123", importance=0.9)

# Get a memory by ID
memory = client.memories.get(memory_id="mem-abc123")

Sessions

# Start a session
session = client.sessions.start(
    agent_id="my-agent",
    metadata={"task": "code review", "user": "alice"}
)

# Store memory linked to the session
client.memories.store(
    agent_id="my-agent",
    content="Reviewed auth module — found 2 security issues",
    session_id=session.id
)

# End session — auto-generates a summary
result = client.sessions.end(
    session_id=session.id,
    summary="Code review complete. 2 issues logged."
)

# List sessions for an agent
sessions = client.sessions.list(agent_id="my-agent")

# Get memories from a session
session_mems = client.sessions.memories(session_id=session.id)

Vector operations

# Upsert raw vectors
client.vectors.upsert(
    namespace="my-ns",
    vectors=[
        {"id": "v1", "values": [0.1, 0.2, 0.3], "metadata": {"label": "a"}},
    ]
)

# Query nearest neighbors
results = client.vectors.query(
    namespace="my-ns",
    vector=[0.1, 0.2, 0.3],
    top_k=10,
    include_metadata=True
)

# Hybrid search (vector + BM25)
results = client.vectors.hybrid_search(
    namespace="my-ns",
    query="agent task completion",
    top_k=10
)

# Full-text search
results = client.fulltext.search(
    namespace="my-ns",
    query="authentication issues",
    top_k=5
)

Namespaces

# Create an isolated namespace for your project
client.namespaces.create(namespace="project-alpha", embedding_model="MiniLML6V2")

# Upsert vectors into a namespace
client.vectors.upsert(
    namespace="project-alpha",
    vectors=[{"id": "doc-1", "values": [0.1, 0.2, 0.3], "metadata": {"title": "intro"}}]
)

# Hybrid search across that namespace
results = client.vectors.hybrid_search(
    namespace="project-alpha",
    query="project goals and milestones",
    top_k=10
)

# List all namespaces
ns_list = client.namespaces.list()

# Delete a namespace (irreversible)
client.namespaces.delete(namespace="project-alpha")

Error handling

from dakera import DakeraClient, DakeraError, AuthorizationError, NotFoundError

try:
    client.memories.get(memory_id="mem-does-not-exist")
except NotFoundError:
    print("Memory not found")
except AuthorizationError:
    print("Invalid API key — check DAKERA_API_KEY")
except DakeraError as e:
    print(f"Dakera error: {e.error_code}{e.message}")

Async client

import os, asyncio
from dakera import AsyncDakeraClient

async def main():
    async with AsyncDakeraClient(
        base_url=os.getenv("DAKERA_URL", "http://localhost:3300"),
        api_key=os.getenv("DAKERA_API_KEY")
    ) as client:
        await client.memories.store(agent_id="agent", content="async example")
        memories = await client.memories.recall(agent_id="agent", query="async")
        print(memories)

asyncio.run(main())

TypeScript SDK

v0.11.54 · Node 20+ · TypeScript 5.0+

npm · GitHub · Changelog

npm install dakera
# yarn add dakera | pnpm add dakera | bun add dakera

Client setup

import { DakeraClient } from 'dakera';

// Recommended: set via env vars
// DAKERA_URL=http://<YOUR_SERVER_IP>:3300
// DAKERA_API_KEY=your-api-key

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

Memory operations

// Store
await client.memories.store({
  agentId: 'my-agent',
  content: 'User is learning Rust',
  importance: 0.8,
  tags: ['learning', 'programming'],
});

// Recall — semantic search
const memories = await client.memories.recall({
  agentId: 'my-agent',
  query: 'programming languages the user knows',
  topK: 10,
});

// Batch recall — filter-based
const filtered = await client.memories.batchRecall({
  agentId: 'my-agent',
  tags: ['learning'],
  minImportance: 0.6,
});

// Forget
await client.memories.forget({ memoryId: 'mem-abc123' });

// Update importance
await client.memories.setImportance({ memoryId: 'mem-abc123', importance: 0.9 });

Sessions

// Start session
const session = await client.sessions.start({
  agentId: 'my-agent',
  metadata: { task: 'code review' },
});

// Store memory linked to session
await client.memories.store({
  agentId: 'my-agent',
  content: 'Reviewed auth module',
  sessionId: session.id,
});

// End session
const result = await client.sessions.end({
  sessionId: session.id,
  summary: 'Code review complete',
});

// List sessions
const sessions = await client.sessions.list({ agentId: 'my-agent' });

TypeScript types

import type {
  MemoryRecord,       // { id, agentId, content, importance, tags, createdAt, sessionId? }
  RecallResult,       // extends MemoryRecord with score: number
  StoreMemoryRequest, // { agentId, content, importance?, tags?, sessionId? }
  RecallRequest,      // { agentId, query, topK? }
  Session,            // { id, agentId, startedAt, endedAt?, memoryCount, summary? }
  DakeraClient,
} from 'dakera';

Namespaces & vector operations

// Create a namespace
await client.namespaces.create({ namespace: 'project-alpha' });

// Upsert vectors
await client.vectors.upsert({
  namespace: 'project-alpha',
  vectors: [{ id: 'doc-1', values: [0.1, 0.2, 0.3], metadata: { title: 'intro' } }],
});

// Hybrid search (vector + BM25)
const results = await client.vectors.hybridSearch({
  namespace: 'project-alpha',
  query: 'project goals',
  topK: 10,
});

Error handling

import { DakeraError, AuthorizationError, NotFoundError } from 'dakera';

try {
  await client.memories.get({ memoryId: 'mem-does-not-exist' });
} catch (err) {
  if (err instanceof NotFoundError) {
    console.error('Memory not found');
  } else if (err instanceof AuthorizationError) {
    console.error('Invalid API key — check DAKERA_API_KEY');
  } else if (err instanceof DakeraError) {
    console.error(`${err.errorCode}: ${err.message}`);
  }
}

Go SDK

v0.11.54 · Go 1.21+

pkg.go.dev · GitHub

go get github.com/dakera-ai/dakera-go@latest

Client setup

import (
    dakera "github.com/dakera-ai/dakera-go"
    "os"
    "time"
)

// Recommended: configure via env vars
// DAKERA_URL=http://<YOUR_SERVER_IP>:3300
// DAKERA_API_KEY=your-api-key

serverURL := os.Getenv("DAKERA_URL")
if serverURL == "" { serverURL = "http://localhost:3300" }

client := dakera.NewClientWithOptions(dakera.ClientOptions{
    BaseURL: serverURL,
    APIKey:  os.Getenv("DAKERA_API_KEY"),
    Timeout: 30 * time.Second,
})

Memory operations

// Store
_, err := client.Memories.Store(ctx, &dakera.StoreRequest{
    AgentID:    "my-agent",
    Content:    "User is learning Rust",
    Importance: 0.8,
    Tags:       []string{"learning"},
})

// Recall
memories, err := client.Memories.Recall(ctx, &dakera.RecallRequest{
    AgentID: "my-agent",
    Query:   "programming languages",
    TopK:    10,
})

// Batch recall
memories, err := client.Memories.BatchRecall(ctx, &dakera.BatchRecallRequest{
    AgentID:       "my-agent",
    Tags:          []string{"learning"},
    MinImportance: 0.6,
})

// Forget
err = client.Memories.Forget(ctx, "mem-abc123")

Sessions

session, err := client.Sessions.Start(ctx, &dakera.StartSessionRequest{
    AgentID:  "my-agent",
    Metadata: map[string]interface{}{"task": "review"},
})

result, err := client.Sessions.End(ctx, &dakera.EndSessionRequest{
    SessionID: session.ID,
    Summary:   "Review complete",
})

Vector operations

// Upsert
_, err = client.Upsert(ctx, "my-ns", []dakera.VectorInput{
    {ID: "v1", Values: []float32{0.1, 0.2, 0.3}, Metadata: map[string]interface{}{"label": "a"}},
})

// Hybrid search (vector + BM25)
results, err := client.HybridSearch(ctx, "my-ns", &dakera.HybridSearchRequest{
    Query: "agent task completion",
    TopK:  10,
})

// ANN vector query
results, err := client.Query(ctx, "my-ns", []float32{0.1, 0.2, 0.3}, &dakera.QueryOptions{
    TopK: 10, IncludeMetadata: true,
})

Error handling

import (
    dakera "github.com/dakera-ai/dakera-go"
    "errors"
    "log"
)

memories, err := client.Memories.Recall(ctx, &dakera.RecallRequest{
    AgentID: "my-agent",
    Query:   "important decisions",
    TopK:    10,
})
if err != nil {
    var authErr *dakera.AuthorizationError
    var notFoundErr *dakera.NotFoundError
    var dakeraErr *dakera.DakeraError

    switch {
    case errors.As(err, &authErr):
        log.Fatalf("authentication failed — check DAKERA_API_KEY: %v", authErr)
    case errors.As(err, &notFoundErr):
        log.Printf("agent or memory not found: %v", notFoundErr)
    case errors.As(err, &dakeraErr):
        log.Printf("dakera error %d: %s", dakeraErr.ErrorCode, dakeraErr.Message)
    default:
        log.Printf("network or serialisation error: %v", err)
    }
}

Rust SDK

v0.11.54 · Rust 1.70+ · Tokio

crates.io · docs.rs · GitHub

# Cargo.toml
[dependencies]
dakera-client = "0.11"
tokio = { version = "1", features = ["full"] }

Client setup

use dakera_client::{DakeraClient, Config};

// Recommended: configure via env vars
// DAKERA_URL=http://<YOUR_SERVER_IP>:3300
// DAKERA_API_KEY=your-api-key

let client = DakeraClient::new(Config {
    base_url: std::env::var("DAKERA_URL")
        .unwrap_or_else(|_| "http://localhost:3300".into()),
    api_key: std::env::var("DAKERA_API_KEY").ok(),
    ..Default::default()
})?;

Memory operations

use dakera_client::memory::{StoreRequest, RecallRequest};

// Store
client.memories().store(StoreRequest {
    agent_id: "my-agent".into(),
    content: "User is learning Rust".into(),
    importance: Some(0.8),
    tags: vec!["learning".into()],
    ..Default::default()
}).await?;

// Recall
let memories = client.memories().recall(RecallRequest {
    agent_id: "my-agent".into(),
    query: "programming languages".into(),
    top_k: Some(10),
    ..Default::default()
}).await?;

// Sessions
let session = client.sessions().start(StartRequest {
    agent_id: "my-agent".into(),
    ..Default::default()
}).await?;

gRPC transport

# Enable in Cargo.toml
dakera-client = { version = "0.11", features = ["grpc"] }
let client = DakeraClient::grpc(GrpcConfig {
    endpoint: "http://localhost:50051".into(),
    ..Default::default()
})?;

Error handling

use dakera_client::error::{DakeraError, ErrorKind};

match client.memories().recall(RecallRequest {
    agent_id: "my-agent".into(),
    query: "important decisions".into(),
    ..Default::default()
}).await {
    Ok(memories) => {
        for m in &memories { println!("{}: {}", m.id, m.content); }
    }
    Err(DakeraError { kind: ErrorKind::Unauthorized, .. }) => {
        eprintln!("Invalid API key — check DAKERA_API_KEY");
    }
    Err(DakeraError { kind: ErrorKind::NotFound, message, .. }) => {
        eprintln!("Not found: {message}");
    }
    Err(DakeraError { kind: ErrorKind::RateLimited, .. }) => {
        eprintln!("Rate limit hit — back off and retry");
    }
    Err(e) => {
        eprintln!("Dakera error [{:?}]: {}", e.kind, e.message);
    }
}

REST API Reference

All endpoints require Authorization: Bearer <key> when authentication is enabled.

Base URL — Replace localhost:3300 with your server's address (e.g. http://<YOUR_SERVER_IP>:3300). All routes versioned under /v1/.

Health

MethodPathAuthDescription
GET/healthNoReturns server status and version
GET/metricsNoPrometheus metrics

Memory

MethodPathDescription
POST/v1/memory/storeStore a memory
POST/v1/memory/recallSemantic recall
POST/v1/memories/recall/batchFilter-based batch recall
GET/v1/memory/get/{id}Get memory by ID
PUT/v1/memory/update/{id}Update memory content, importance, or tags
POST/v1/memory/forgetDelete (forget) a memory

Store memory — request body

{
  "agent_id": "my-agent",                  // required
  "content": "User prefers dark mode",       // required
  "importance": 0.8,                         // optional, 0.0–1.0, default 0.5
  "tags": ["preference", "ui"],             // optional
  "session_id": "sess-abc123",              // optional
  "memory_type": "episodic"                  // episodic | semantic | procedural | working
}

Recall — request body

{
  "agent_id": "my-agent",                  // required
  "query": "UI preferences",                // required
  "top_k": 10,                               // optional, default 10
  "min_importance": 0.5,                    // optional filter
  "tags": ["preference"],                    // optional filter
  "session_id": "sess-abc123"               // optional: scope to session
}

Sessions

MethodPathDescription
POST/v1/sessions/startStart a session
GET/v1/sessions/:idGet session by ID
POST/v1/sessions/{id}/endEnd a session
GET/v1/sessions/:id/memoriesGet all memories from a session
GET/v1/agents/:id/sessionsList all sessions for an agent

Vectors (namespaces)

MethodPathDescription
POST/v1/namespaces/:ns/vectorsUpsert vectors
POST/v1/namespaces/:ns/queryANN vector search
POST/v1/namespaces/:ns/hybrid-searchVector + BM25 hybrid
POST/v1/namespaces/:ns/fulltext/indexIndex documents for BM25
POST/v1/namespaces/:ns/fulltext/searchFull-text search
DELETE/v1/namespaces/:ns/vectors/:idDelete a vector
GET/v1/namespacesList all namespaces
POST/v1/namespacesCreate a namespace
PUT/v1/namespaces/:nsConfigure a namespace
DELETE/v1/namespaces/:nsDelete a namespace

Configuration

All configuration via environment variables. No config file required.

Server

VariableTypeDefaultDescription
DAKERA_ROOT_API_KEYstringBootstrap root API key (super_admin scope). If unset, auth is disabled.
DAKERA_HOSTstring0.0.0.0Bind address
DAKERA_PORTu163300REST API port
DAKERA_GRPC_PORTu1650051gRPC port
RUST_LOGstringinfoLog level: trace/debug/info/warn/error

Storage

VariableDefaultDescription
DAKERA_STORAGEmemoryBackend: memory, filesystem, s3, minio
DAKERA_STORAGE_PATH./dataData directory for filesystem storage
DAKERA_S3_BUCKETS3 bucket name (3–63 chars)
DAKERA_S3_REGIONS3 region (e.g. us-east-1)
DAKERA_S3_ENDPOINTS3-compatible endpoint URL (MinIO)
DAKERA_S3_MAX_RETRIES3Max retry attempts on transient S3 errors
AWS_ACCESS_KEY_IDAWS / MinIO access key
AWS_SECRET_ACCESS_KEYAWS / MinIO secret key

Embeddings

VariableDefaultDescription
DAKERA_EMBEDDING_MODELMiniLML6V2ONNX model: MiniLML6V2, BGESmallENV15, E5SmallV2
DAKERA_INFERENCE_DEVICEcpucpu or cuda

Memory & decay

VariableDefaultDescription
DAKERA_DECAY_ENABLEDtrueEnable memory importance decay over time
DAKERA_DECAY_HALF_LIFE_SECS604800Half-life for decay (default: 7 days)
DAKERA_AUTOPILOT_ENABLEDfalseEnable AutoPilot memory lifecycle management

Retrieval tuning

VariableDefaultDescription
DAKERA_RRF_K60Reciprocal Rank Fusion k-parameter. Lower = boosts top ranks more aggressively.
DAKERA_NAME_BOOST0.3Score boost for memories matching proper nouns in the query. Range [0.0, 1.0].
DAKERA_ML_CLASSIFIERfalseEnable ML-based query classifier (embedding centroid cosine similarity).
DAKERA_TEMPORAL_INFERENCEtrueEnable per-query temporal boost for Cat3 inference queries (requires ML_CLASSIFIER).
DAKERA_INFERENCE_TEMPORAL_MULT_BETA0.65Multiplicative temporal scaling β. Formula: score *= (1 + β × (proximity − 0.5)). Raised from 0.5 to 0.65 in v0.11.54 (CE-115) for stronger temporal tilt. (v0.11.52+) Supersedes DAKERA_ML_TEMPORAL_BOOST.
DAKERA_ML_TEMPORAL_BOOST0.3Deprecated (v0.11.45–v0.11.54). ML-driven additive temporal boost weight. Superseded by DAKERA_INFERENCE_TEMPORAL_MULT_BETA in v0.11.54 — recalibrate custom values against the new multiplicative formula.
DAKERA_ENTITY_VECTOR_SEARCHtrueEnable entity-filtered second HNSW pass merged via RRF. (v0.11.47+)
DAKERA_HNSW_CACHE_MAX50Max HNSW indexes in LRU cache. Increase for many-namespace deployments.

Rate limiting & auth

VariableDefaultDescription
RATE_LIMIT_RPS100Requests per second
RATE_LIMIT_BURST50Burst capacity
DAKERA_AUTH_ENABLEDtrueEnable/disable API key authentication
DAKERA_CORS_ORIGINS*Allowed CORS origins (comma-separated)

Observability

VariableDefaultDescription
DAKERA_TRACING_ENABLEDfalseEnable OpenTelemetry tracing
OTEL_EXPORTER_OTLP_ENDPOINThttp://localhost:4317OTLP collector endpoint
OTEL_SERVICE_NAMEdakeraService name in traces
SLOW_QUERY_THRESHOLD_MS100Log queries slower than this (ms)

Audit logging

VariableDefaultDescription
DAKERA_AUDIT_LOGfalseEnable audit logging — records every API request with agent ID, operation, and timestamp
DAKERA_AUDIT_LOG_PATH./audit.logPath for audit log output (JSON format, one record per line)

Example production .env

# Server
DAKERA_ROOT_API_KEY=your-strong-secret-here  # openssl rand -hex 32
DAKERA_PORT=3300
RUST_LOG=info

# Storage (filesystem — single node)
DAKERA_STORAGE=filesystem
DAKERA_STORAGE_PATH=/var/dakera/data

# Embeddings
DAKERA_EMBEDDING_MODEL=MiniLML6V2

# Decay
DAKERA_DECAY_ENABLED=true
DAKERA_DECAY_HALF_LIFE_SECS=604800  # 7 days

# Retrieval — enables ML classifier + temporal scoring (87.6% LoCoMo)
DAKERA_ML_CLASSIFIER=true
DAKERA_TEMPORAL_INFERENCE=true
DAKERA_INFERENCE_TEMPORAL_MULT_BETA=0.65

# Observability
DAKERA_AUDIT_LOG=true
DAKERA_AUDIT_LOG_PATH=/var/dakera/audit.log

Deployment

Docker images

All images are published to GitHub Container Registry (ghcr.io/dakera-ai/). No Docker Hub account required — public pull, no authentication needed.

ImageArchitecturesDescription
ghcr.io/dakera-ai/dakera:latestlinux/amd64, linux/arm64Dakera memory server — latest stable release
ghcr.io/dakera-ai/dakera:v0.11.55linux/amd64, linux/arm64Pinned version (recommended for production)
ghcr.io/dakera-ai/dakera-dashboard:latestlinux/amd64, linux/arm64Web UI dashboard
ghcr.io/dakera-ai/dakera-mcp:latestlinux/amd64, linux/arm64MCP server (for containerised deployments)
# Pull all images
docker pull ghcr.io/dakera-ai/dakera:latest
docker pull ghcr.io/dakera-ai/dakera-dashboard:latest
docker pull ghcr.io/dakera-ai/dakera-mcp:latest

# Inspect available tags
docker run --rm ghcr.io/dakera-ai/dakera:latest --version

Docker (single node)

docker run -d \
  --name dakera \
  --restart unless-stopped \
  -p 3300:3300 \
  -e DAKERA_PORT=3300 \
  -e DAKERA_ROOT_API_KEY=your-secret \
  -e DAKERA_STORAGE=filesystem \
  -e DAKERA_STORAGE_PATH=/data \
  -v dakera-data:/data \
  ghcr.io/dakera-ai/dakera:latest

After starting, point your SDK clients and MCP binary at http://<SERVER_IP>:3300.

Docker Compose (recommended)

Copy the two files below into a working directory (e.g. ~/dakera/) and run docker compose up -d. The minio-setup service creates the storage bucket automatically — Dakera will not start until the bucket exists.

docker-compose.yml

# docker-compose.yml — production-grade single-node stack
# Usage:
#   docker compose up -d                       # server + MinIO
#   docker compose --profile dashboard up -d   # + Dashboard UI
#   docker compose --profile monitoring up -d  # + Prometheus + Grafana
#   docker compose --profile full up -d        # all services

name: dakera

services:

  dakera:
    image: ${DAKERA_IMAGE:-ghcr.io/dakera-ai/dakera:latest}
    container_name: dakera
    restart: unless-stopped
    ports:
      - "${DAKERA_PORT:-3300}:3300"
      - "${DAKERA_GRPC_PORT:-50051}:50051"
    environment:
      RUST_LOG: ${RUST_LOG:-info}
      DAKERA_HOST: 0.0.0.0
      DAKERA_PORT: 3300
      DAKERA_GRPC_PORT: 50051
      DAKERA_AUTH_ENABLED: ${DAKERA_AUTH_ENABLED:-true}
      DAKERA_ROOT_API_KEY: ${DAKERA_ROOT_API_KEY:?Set DAKERA_ROOT_API_KEY in .env}
      DAKERA_STORAGE: s3
      DAKERA_S3_ENDPOINT: http://minio:9000
      DAKERA_S3_BUCKET: dakera
      DAKERA_S3_REGION: us-east-1
      DAKERA_S3_MAX_RETRIES: 3
      AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}
      AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?Set MINIO_ROOT_PASSWORD in .env}
      DAKERA_L1_CACHE_SIZE: 536870912
      DAKERA_L2_CACHE_PATH: /data/rocksdb
      DAKERA_TIERED_STORAGE: true
      DAKERA_HOT_TO_WARM_SECS: 3600
      DAKERA_WARM_TO_COLD_SECS: 86400
      DAKERA_ML_CLASSIFIER: true
      DAKERA_TEMPORAL_INFERENCE: true
    volumes:
      - dakera-cache:/data/cache
      - dakera-rocksdb:/data/rocksdb
    depends_on:
      minio-setup:
        condition: service_completed_successfully
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:3300/health"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 15s
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: "2.0"
        reservations:
          memory: 512M
    networks:
      - dakera-net

  minio:
    image: minio/minio:latest
    container_name: dakera-minio
    restart: unless-stopped
    command: server /data --console-address ":9001"
    ports:
      - "${MINIO_API_PORT:-9000}:9000"
      - "${MINIO_CONSOLE_PORT:-9001}:9001"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?Set MINIO_ROOT_PASSWORD in .env}
      MINIO_API_REQUESTS_MAX: 6000
    volumes:
      - minio-data:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - dakera-net

  # IMPORTANT: creates the MinIO bucket before Dakera starts.
  # Without this, Dakera will start but all writes will fail.
  minio-setup:
    image: minio/mc:latest
    container_name: dakera-minio-setup
    depends_on:
      minio:
        condition: service_healthy
    entrypoint: >
      /bin/sh -c "
      mc alias set local http://minio:9000 $${MINIO_ROOT_USER:-minioadmin} $${MINIO_ROOT_PASSWORD};
      mc mb local/dakera --ignore-existing;
      echo 'Bucket ready.';
      "
    networks:
      - dakera-net

  # Dashboard UI (optional — enable with --profile dashboard)
  dashboard:
    image: ${DASHBOARD_IMAGE:-ghcr.io/dakera-ai/dakera-dashboard:latest}
    container_name: dakera-dashboard
    profiles: ["dashboard", "full"]
    restart: unless-stopped
    ports:
      - "${DASHBOARD_PORT:-3002}:3000"
    environment:
      DAKERA_API_UPSTREAM: http://dakera:3300
      DAKERA_API_KEY: ${DAKERA_ROOT_API_KEY}
    depends_on:
      dakera:
        condition: service_healthy
    networks:
      - dakera-net

  # Prometheus + Grafana (optional — enable with --profile monitoring)
  prometheus:
    image: prom/prometheus:v3.2.0
    container_name: dakera-prometheus
    profiles: ["monitoring", "full"]
    ports:
      - "${PROMETHEUS_PORT:-9090}:9090"
    volumes:
      - prometheus-data:/prometheus
    command:
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=15d"
      - "--web.enable-lifecycle"
    restart: unless-stopped
    networks:
      - dakera-net

  grafana:
    image: grafana/grafana:11.4.0
    container_name: dakera-grafana
    profiles: ["monitoring", "full"]
    ports:
      - "${GRAFANA_PORT:-3003}:3000"
    environment:
      GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin}
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-dakera}
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on: [prometheus]
    restart: unless-stopped
    networks:
      - dakera-net

volumes:
  dakera-cache:
  dakera-rocksdb:
  minio-data:
  prometheus-data:
  grafana-data:

networks:
  dakera-net:
    driver: bridge

.env template

Place alongside docker-compose.yml. Never commit .env to version control.

# .env — fill in REQUIRED values before first start

# REQUIRED — root API key (grants full access)
DAKERA_ROOT_API_KEY=

# REQUIRED — MinIO credentials
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=

# Optional port overrides (defaults shown)
# DAKERA_PORT=3300
# DAKERA_GRPC_PORT=50051
# MINIO_API_PORT=9000
# MINIO_CONSOLE_PORT=9001
# DASHBOARD_PORT=3002

# Optional image pins
# DAKERA_IMAGE=ghcr.io/dakera-ai/dakera:v0.11.55
# DASHBOARD_IMAGE=ghcr.io/dakera-ai/dakera-dashboard:latest

Generate fresh secrets in one command:

printf "DAKERA_ROOT_API_KEY=%s
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=%s
"   "$(openssl rand -hex 32)" "$(openssl rand -hex 16)" > .env

Startup sequence

# Start core stack (Dakera + MinIO + bucket init)
docker compose up -d

# Wait ~30s, then verify all services are healthy
docker compose ps

# Confirm the API is accepting requests
curl -s http://localhost:3300/health
# → {"service":"dakera","status":"healthy","version":"0.11.55"}

# Optional: launch Dashboard UI at http://localhost:3002
docker compose --profile dashboard up -d

# Optional: launch Prometheus (port 9090) + Grafana (port 3003)
docker compose --profile monitoring up -d

Kubernetes — Kustomize

The dakera-deploy repo ships a production-ready kustomize stack. Zero extra tools required — just kubectl ≥ 1.21.

# Clone the deploy repo
git clone https://github.com/dakera-ai/dakera-deploy
cd dakera-deploy

# 1. Create secrets (gitignored — never commit)
cp k8s/secret.example.yaml k8s/secret.yaml
# Edit k8s/secret.yaml — set base64-encoded values:
#   DAKERA_ROOT_API_KEY: $(echo -n "$(openssl rand -hex 32)" | base64)

# 2. Apply the full stack (namespace, MinIO, server, dashboard, MCP, ingress)
kubectl apply -f k8s/secret.yaml
kubectl apply -k k8s/

# 3. Verify pods are running
kubectl get pods -n dakera

Kubernetes — Helm

The official Helm chart lives in the dedicated dakera-helm repository and deploys all components: server, dashboard, MCP, MinIO, and optional monitoring. Requires Helm ≥ 3.8.

Install from OCI registry (recommended)

# No extra repo config needed — pulls directly from GHCR
helm install dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera \
  --namespace dakera --create-namespace \
  --set dakera.rootApiKey="$(openssl rand -hex 32)" \
  --set minio.rootPassword="$(openssl rand -hex 16)"

# Pin a specific version
helm install dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera \
  --version 0.11.55 \
  --namespace dakera --create-namespace \
  --set dakera.rootApiKey="$(openssl rand -hex 32)" \
  --set minio.rootPassword="$(openssl rand -hex 16)"

# Upgrade an existing release
helm upgrade dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera \
  --namespace dakera \
  --set dakera.rootApiKey="<existing-key>" \
  --set minio.rootPassword="<existing-password>"

# Check release status
helm status dakera -n dakera

Install from Helm repository (ArtifactHub)

helm repo add dakera https://dakera-ai.github.io/dakera-helm
helm repo update

helm install dakera dakera/dakera \
  --namespace dakera --create-namespace \
  --set dakera.rootApiKey="$(openssl rand -hex 32)" \
  --set minio.rootPassword="$(openssl rand -hex 16)"

Install from chart source

git clone https://github.com/dakera-ai/dakera-helm
cd dakera-helm

# Dry-run to preview rendered manifests
helm install dakera ./charts/dakera --dry-run --debug

# Install
helm install dakera ./charts/dakera \
  --namespace dakera --create-namespace \
  --set dakera.rootApiKey="$(openssl rand -hex 32)" \
  --set minio.rootPassword="$(openssl rand -hex 16)"

Complete values.yaml reference

Override any value with --set key=value or a custom values file (-f my-values.yaml). Full defaults in charts/dakera/values.yaml.

Dakera server

KeyDefaultDescription
dakera.image.repositoryghcr.io/dakera-ai/dakeraServer container image repository
dakera.image.tagchart appVersionImage tag — pin this in production
dakera.image.pullPolicyIfNotPresentPull policy: Always / IfNotPresent / Never
dakera.replicaCount1Server replicas (use HPA for auto-scaling)
dakera.rootApiKeyrequiredRoot API key — set via --set or external secret
dakera.config.port3000REST API port inside the pod
dakera.config.grpcPort50051gRPC port inside the pod
dakera.config.storages3Storage backend: memory, filesystem, s3
dakera.config.s3BucketdakeraMinIO / S3 bucket name
dakera.config.s3Regionus-east-1Region (any string for self-hosted MinIO)
dakera.config.l1CacheSize1073741824In-memory L1 cache in bytes (default 1 GB)
dakera.config.tieredStoragetrueEnable hot → RocksDB → S3 tiering
dakera.config.hotToWarmSecs3600Seconds before L1 moves to RocksDB
dakera.config.warmToColdSecs86400Seconds before RocksDB moves to S3
dakera.config.authEnabledtrueEnforce API key auth on all requests
dakera.persistence.enabledtrueMount a PVC for the RocksDB L2 cache
dakera.persistence.size20GiRocksDB PVC size
dakera.persistence.storageClasscluster defaultStorageClass (empty = cluster default)
dakera.resources.requests.cpu500mCPU request
dakera.resources.requests.memory512MiMemory request
dakera.resources.limits.cpu2CPU limit
dakera.resources.limits.memory4GiMemory limit — increase for >1M memories
dakera.service.typeClusterIPService type (ClusterIP / NodePort / LoadBalancer)

Autoscaling (HPA)

KeyDefaultDescription
dakera.autoscaling.enabledtrueEnable Horizontal Pod Autoscaler
dakera.autoscaling.minReplicas1Minimum replicas
dakera.autoscaling.maxReplicas5Maximum replicas
dakera.autoscaling.targetCPUUtilizationPercentage70Scale-up CPU threshold (%)
dakera.autoscaling.targetMemoryUtilizationPercentage80Scale-up memory threshold (%)

Dashboard, MCP, MinIO

KeyDefaultDescription
dashboard.enabledtrueDeploy the Dashboard UI
dashboard.replicaCount1Dashboard replicas
dashboard.resources.limits.cpu500mDashboard CPU limit
dashboard.resources.limits.memory256MiDashboard memory limit
mcp.enabledtrueDeploy the MCP server sidecar
mcp.config.port3001MCP server listen port
mcp.resources.limits.memory256MiMCP memory limit
minio.enabledtrueDeploy built-in MinIO — set false for external S3
minio.rootUserminioadminMinIO root username — change in production
minio.rootPasswordrequiredMinIO root password — set via --set
minio.persistence.size50GiMinIO data PVC size
minio.persistence.storageClasscluster defaultStorageClass for MinIO PVC
minio.resources.limits.memory2GiMinIO memory limit

Ingress

KeyDefaultDescription
ingress.enabledfalseEnable nginx Ingress
ingress.classNamenginxIngress class (nginx / traefik)
ingress.apiHostHostname for the Dakera REST API
ingress.dashboardHostHostname for the Dashboard UI
ingress.mcpHostHostname for the MCP server
ingress.annotations{}Ingress annotations (e.g. cert-manager issuer)

Monitoring

KeyDefaultDescription
monitoring.enabledfalseDeploy Prometheus + Grafana (auto-scrapes /metrics)
monitoring.prometheus.retention15dPrometheus data retention
monitoring.prometheus.persistence.size10GiPrometheus PVC size
monitoring.grafana.adminUseradminGrafana admin username
monitoring.grafana.adminPasswordauto-generatedGrafana admin password (random if empty)
monitoring.grafana.persistence.size5GiGrafana PVC size

Enable ingress with TLS

# production-values.yaml
ingress:
  enabled: true
  className: nginx
  apiHost: api.dakera.example.com
  dashboardHost: dashboard.dakera.example.com
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  tls:
    - secretName: dakera-tls
      hosts:
        - api.dakera.example.com
        - dashboard.dakera.example.com
helm upgrade dakera oci://ghcr.io/dakera-ai/dakera-helm/dakera -f production-values.yaml

Use external S3 instead of MinIO

# external-s3-values.yaml
minio:
  enabled: false
dakera:
  config:
    s3Endpoint: https://s3.amazonaws.com
    s3Bucket: my-dakera-bucket
    s3Region: us-east-1

Verify your deployment

# All pods should reach Running
kubectl get pods -n dakera

# Port-forward and smoke-test
kubectl port-forward svc/dakera 3300:3300 -n dakera &
curl -s http://localhost:3300/health
# {"status":"ok"}

# View recent logs
kubectl logs -l app.kubernetes.io/name=dakera -n dakera --tail=50

# Describe a pod for events
kubectl describe pod -l app.kubernetes.io/name=dakera -n dakera

Cloud deployment

AWS ECS / EKS

Use ECR for the container image. For EKS, add the AWS Load Balancer Controller for Ingress and IRSA for S3 access without static credentials.

GCP GKE

Build via gcloud builds submit, push to GCR/Artifact Registry, and apply kustomize. Use Workload Identity for GCS bucket access.

Azure AKS

Build via Azure Container Registry. Use AKS with Azure Blob Storage backend, enabling minio.enabled=false in the Helm values.

Bare metal / VM

Single binary, no runtime deps. Run under systemd with Restart=always. See the Docker Compose files for a production-hardened stack.

Self-host on a VPS

Five steps to run Dakera on a fresh Ubuntu/Debian VPS or bare metal server. Requires Docker ≥ 24 and Docker Compose ≥ 2.20.

1

Install Docker

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
2

Create a working directory

mkdir -p ~/dakera && cd ~/dakera
3

Generate secrets

# Creates .env with fresh random credentials
cat > .env << EOF
DAKERA_API_KEY=$(openssl rand -hex 32)
MINIO_USER=minioadmin
MINIO_PASSWORD=$(openssl rand -hex 16)
EOF
Keep .env private. It holds your root API key — the only credential that can create namespaces and rotate keys. Never commit it to git.
4

Copy the docker-compose.yml

Save the Docker Compose (recommended) snippet from above as ~/dakera/docker-compose.yml. The compose file reads credentials from .env automatically.

5

Start the stack

docker compose up -d

The first start pulls images and initialises MinIO storage. Allow 20–30 seconds for all health checks to pass.

Startup verification

Run these checks after docker compose up -d to confirm the stack is healthy before routing traffic.

# All services should show "Up (healthy)"
docker compose ps

# REST API health — expects {"status":"ok","version":"0.11.55"}
curl -s http://localhost:3300/health

# Confirm authentication is enforced — expects 401
curl -s -o /dev/null -w "%{http_code}" http://localhost:3300/v1/memories

# Smoke-test write path with your API key
curl -s -X POST http://localhost:3300/v1/memories \
  -H "Authorization: Bearer $DAKERA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id":"smoke-test","content":"startup check","importance":0.5}'
# Expected: {"id":"mem_...","agent_id":"smoke-test",...}

# Tail logs for any startup errors
docker compose logs -f dakera --tail=50
All checks pass? Point your SDK clients and MCP binary at http://<SERVER_IP>:3300 with your DAKERA_API_KEY.

Upgrading Dakera

Minor and patch upgrades are data-safe — RocksDB and S3 data survive image replacements. No migration scripts are needed unless the release notes say otherwise.

# Pull the latest image (or pin a specific tag in docker-compose.yml first)
docker compose pull dakera

# Restart only the Dakera container — MinIO keeps running
docker compose up -d --no-deps dakera

# Confirm the new version is live
curl -s http://localhost:3300/health | grep version

# Watch logs for any startup errors
docker compose logs -f dakera --tail=100
Before upgrading: Check the CHANGELOG for breaking configuration changes. Major version bumps (e.g. 0.x → 1.0) may include data migration steps listed in the release notes.

Environment variable reference

Pass variables via an .env file (co-located with docker-compose.yml) or set them directly in the environment: block. Variables marked required must be set before starting.

Core

VariableDefaultDescription
DAKERA_ROOT_API_KEYrequiredRoot API key — grants full admin access. Generate: openssl rand -hex 32.
DAKERA_AUTH_ENABLEDtrueEnforce API key authentication on all requests. Set false only for local dev.
DAKERA_HOST0.0.0.0Bind address for the REST API.
DAKERA_PORT3300REST API listen port.
DAKERA_GRPC_PORT50051gRPC listen port.
RUST_LOGinfoLog verbosity: error | warn | info | debug. Avoid debug in production.
DAKERA_ML_CLASSIFIERfalseEnable ML-based query classification for improved recall across diverse query types. Recommended in production.

Storage

VariableDefaultDescription
DAKERA_STORAGEmemoryStorage backend: memory (non-persistent), filesystem, or s3. Use s3 with MinIO for production.
DAKERA_STORAGE_PATH/dataRoot path for filesystem storage and cache. Mount a persistent volume here.
DAKERA_L2_CACHE_PATH/data/rocksdbRocksDB L2 cache path. SSD-backed storage improves recall latency.
DAKERA_L1_CACHE_SIZE536870912In-memory L1 cache size in bytes (default 512 MB). Increase for high-throughput deployments.
DAKERA_TIERED_STORAGEtrueEnable automatic hot → RocksDB → S3 tiering.
DAKERA_HOT_TO_WARM_SECS3600Seconds before L1 memories are promoted to RocksDB (L2).
DAKERA_WARM_TO_COLD_SECS86400Seconds before RocksDB memories are promoted to S3 cold storage.

S3 / MinIO

Required when DAKERA_STORAGE=s3.

VariableDefaultDescription
DAKERA_S3_ENDPOINTS3-compatible endpoint URL. For self-hosted MinIO: http://minio:9000. Omit for AWS S3.
DAKERA_S3_BUCKETTarget bucket name. The bucket must exist before Dakera starts.
DAKERA_S3_REGIONus-east-1S3 region. For self-hosted MinIO this can be any non-empty string.
DAKERA_S3_MAX_RETRIES3Retry count on transient S3 errors.
AWS_ACCESS_KEY_IDS3 / MinIO access key ID.
AWS_SECRET_ACCESS_KEYS3 / MinIO secret access key.

Request handling

VariableDefaultDescription
DAKERA_MAX_BODY_SIZE524288000Max HTTP request body in bytes (default 500 MB). Reduce if not using bulk import.
DAKERA_REQUEST_TIMEOUT120HTTP request timeout in seconds.

Cluster (HA mode only)

VariableDefaultDescription
DAKERA_CLUSTER_MODEfalseEnable multi-node cluster. See the High Availability section for the full setup guide.
DAKERA_NODE_IDUnique node identifier within the cluster (e.g. node-1).
DAKERA_CLUSTER_SEEDSComma-separated gossip bootstrap addresses: dakera-2:7946,dakera-3:7946.
DAKERA_GOSSIP_PORT7946SWIM-style cluster gossip port. Must be open between nodes.
DAKERA_REDIS_URLRedis connection URL for distributed L2 cache in cluster mode (e.g. redis://redis:6379).

Production checklist

ItemNotes
✓ Set DAKERA_ROOT_API_KEYUse a cryptographically random 32+ char secret
✓ Mount persistent volume for DAKERA_STORAGE_PATHUse SSD for best performance
✓ Enable S3 storage for critical dataMinIO works well for self-hosted
✓ Scrape /metrics with Prometheus13 built-in metrics including per-operation counters
✓ Set resource limits1–2 CPU, 2–4 GB RAM for ≤1M memories
✓ Enable DAKERA_ML_CLASSIFIER=trueImproves recall quality for diverse query types
✓ Set RUST_LOG=infoAvoid debug in production (too verbose)

Deployment resources

dakera-deploy repo ↗ Helm chart (ArtifactHub) ↗ High Availability → Troubleshooting →

Architecture

Five Rust crates compiled into one binary. No runtime dependencies, no sidecars.

System overview

Dakera — System Architecture
API Layer crates/api
REST API
Axum
gRPC API
Tonic
Prometheus
/metrics
Middleware — Rate Limiting · Distributed Tracing · Auth
Engine Layer crates/engine
HNSW / IVF
ANN search
BM25
Full-text
Hybrid RRF + Rerank
Temporal scoring
Storage Layer crates/storage
Moka LRU
Hot cache
RocksDB
Warm store
S3 / MinIO
Cold / archival
Inference Layer crates/inference
ONNX Runtime — MiniLM / BGE / E5 loaded eagerly at startup  ·  on-device embeddings, zero external API calls

Design principles

Single binary

All five crates compile to one statically-linked binary. No Node.js, no Python runtime, no sidecar containers required.

Async-first

Every I/O path is async via Tokio. REST, gRPC, storage reads/writes, and embedding inference never block threads.

SIMD-accelerated distances

Cosine similarity, Euclidean distance, and dot product use vectorized instructions. Nearest-neighbor search stays fast at millions of vectors.

Pluggable storage

The VectorStorage trait abstracts over in-memory, RocksDB, and S3 backends. Swap storage tiers without changing application code.

Crate structure

CrateResponsibility
crates/api/Axum HTTP server — all routes, middleware, rate limiting, authentication
crates/engine/Recall pipeline — hybrid retrieval, reranking, temporal scoring, decay
crates/storage/RocksDB + OpenDAL tiered storage; Moka LRU cache; HNSW/IVF/SPFresh indexes
crates/inference/ONNX embedding inference — MiniLM, BGE, E5 loaded eagerly at startup
crates/common/Shared types — MemoryRecord, ImportanceFilter, SessionId, FilterExpression

Storage tiers

TierTechnologyCharacteristics
HotMoka in-memory LRUSub-millisecond access, bounded by RAM, auto-eviction
WarmRocksDB (WAL-backed)Persistent, low-latency, survives restarts
ColdS3 / MinIO (OpenDAL)Durable, scalable, archival snapshots

Vector indexes

AlgorithmBest forTrade-offs
HNSWGeneral-purpose ANN, <10M vectorsBest recall/speed; higher memory
IVFLarge collections, 10M+ vectorsLower memory overhead; slightly lower recall
SPFreshHigh-frequency streaming insertsUpdates without full rebuild; good for append-heavy workloads
Flat (exact)Ground-truth benchmarking, small datasets100% recall; O(n) query time

Recall pipeline

Every POST /v1/memory/recall passes through 6 stages:

1

Embed

Input query encoded to a dense vector using the configured ONNX model (on-device, zero API calls).

2

Hybrid retrieve

Vector ANN search + BM25 full-text search run in parallel. Results fused via Reciprocal Rank Fusion (RRF, k=60 default).

3

ML classify

Optional ML classifier (embedding centroid cosine similarity) assigns query category: Cat1 (factual), Cat2 (multi-hop), Cat3 (temporal inference), Cat4 (comparison).

4

Temporal scoring

For Cat3 queries: multiplicative tilt toward temporally-relevant memories. Formula: score *= (1 + β × (proximity − 0.5)).

5

Rerank

Cross-encoder or score-based rerank on top-K candidates. Entity name boost applied post-fusion.

6

Decay & return

Importance decay applied. Recalled memories get access-count boost. Top-N returned with scores, metadata, and session context.

Memory store flow

POST /v1/memory/store
1
Auth & rate-limit
API key validation, scope check, per-agent rate limiting
2
Embed content
ONNX model, on-device — no external API calls
3
Compute initial importance
User-supplied 0.0–1.0 stored; decay engine tracks access patterns over time
4
Write to storage tiers
RocksDB (warm) + S3 / MinIO (cold archival) if configured
5
Index for search
HNSW vector index + BM25 inverted index updated atomically
{"id": "mem_…", "ok": true}

Filter expressions

Metadata filters can be applied to any recall, vector query, or batch operation. Filters compose with $and / $or operators.

# Find memories tagged as important, created after a timestamp
{
  "filter": {
    "$and": [
      { "importance": { "$gt": 0.7 } },
      { "tags": { "$in": ["decision", "blocker"] } }
    ]
  }
}
OperatorTypeExample
$eqEquality{"agent_id": {"$eq": "my-agent"}}
$gt / $ltNumeric range{"importance": {"$gt": 0.5}}
$gte / $lteInclusive range{"score": {"$gte": 0.8}}
$inArray membership{"tags": {"$in": ["prod","alert"]}}
$andLogical ANDCombine multiple conditions
$orLogical ORMatch any condition

Security Guide

Comprehensive security documentation for deploying and operating Dakera securely in production.

Security Layers

LayerProtectionConfiguration
API AuthenticationAPI key validation with scopesDAKERA_ROOT_API_KEY
Rate LimitingDoS protectionRATE_LIMIT_RPS, RATE_LIMIT_BURST
Security HeadersXSS, clickjacking, MIME sniffingEnabled by default
Audit LoggingRequest tracking and forensicsDAKERA_AUDIT_*
Input ValidationInjection preventionBuilt-in validation layer

API Key Scopes

ScopePermissionsUse Case
readQuery vectors, get namespace infoRead-only clients
writeUpsert/delete vectors (includes read)Applications writing data
adminNamespace management (includes write)Administrative tools
super_adminKey management, cluster opsOperators only

Bootstrap Root Key

# Generate a secure random key (256-bit entropy)
export DAKERA_ROOT_API_KEY=$(openssl rand -hex 32)
./dakera
Best practice: Use the root key only to create scoped application keys, then store it securely. Rotate every 90 days. Never commit to version control.

Creating Application Keys

# Create a read-only key
curl -X POST http://localhost:3300/admin/keys \
  -H "Authorization: Bearer $DAKERA_ROOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"query-service","scope":"read","expires_in_days":90}'

Network Security

  • Bind to 127.0.0.1 or a private network interface — never expose port 3300 publicly without a reverse proxy
  • Use TLS termination at your load balancer (nginx, Caddy, Traefik)
  • Rate limiting is enabled by default — tune RATE_LIMIT_RPS for your workload
  • Security headers (HSTS, CSP, X-Frame-Options) are sent on all responses

Audit Logging

Every API request is logged with agent ID, operation, and timestamp when DAKERA_AUDIT_LOG=true. Audit logs are written to DAKERA_AUDIT_LOG_PATH (default: ./audit.log) in JSON format.

Production Security Checklist

ItemStatus
Root API key generated with ≥256-bit entropyRequired
Application keys use minimum required scopeRequired
TLS enabled on all external-facing endpointsRequired
Server not directly accessible from the internet (reverse proxy)Required
Rate limiting configured for expected trafficRecommended
Audit logging enabledRecommended
API key rotation schedule (90 days)Recommended

Kubernetes secrets

Store the root API key in a Kubernetes Secret rather than in a ConfigMap or environment literal.

# Create the secret from a generated key
kubectl create secret generic dakera-secret \
  --namespace dakera \
  --from-literal=api-key="$(openssl rand -hex 32)"

# Reference in your Pod spec
env:
- name: DAKERA_ROOT_API_KEY
  valueFrom:
    secretKeyRef:
      name: dakera-secret
      key: api-key
External Secrets Operator: For production, sync from HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault using the External Secrets Operator. Avoid storing secrets in-cluster long-term.

TLS configuration

Terminate TLS at your reverse proxy or ingress controller. Dakera does not natively terminate TLS — this is by design (separation of concerns, simpler rotation).

# nginx reverse proxy — TLS termination
server {
  listen 443 ssl;
  ssl_certificate     /etc/ssl/dakera.crt;
  ssl_certificate_key /etc/ssl/dakera.key;
  ssl_protocols       TLSv1.2 TLSv1.3;
  ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;

  location / {
    proxy_pass         http://127.0.0.1:3300;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto https;
  }
}

High Availability

Dakera ships a 3-node HA cluster via docker-compose.ha.yml in the dakera-deploy repo. Traffic is load-balanced by Traefik; shared state is stored on MinIO. Nodes discover each other via a SWIM-style gossip protocol.

Cluster topology

Traefik LB :3100 HTTP · :50151 gRPC Dakera Node 1 primary Dakera Node 2 replica Dakera Node 3 replica SWIM gossip · port 7946 MinIO shared S3 · :9100

Quick start

# Start the full HA stack
cd dakera-deploy
docker-compose -f docker-compose.ha.yml up -d

# Verify all services are healthy
docker-compose -f docker-compose.ha.yml ps

Expected: dakera-lb, dakera-1, dakera-2, dakera-3, dakera-ha-minio all in running (healthy) state.

Key ports

ServiceDefault portOverride env var
Dakera REST API (via LB)3100HA_LB_HTTP_PORT
Dakera gRPC (via LB)50151HA_LB_GRPC_PORT
Gossip / cluster membership7946HA_GOSSIP_PORT
MinIO S3 API9100HA_MINIO_PORT
MinIO console9101HA_MINIO_CONSOLE_PORT

Smoke-test the cluster

# Health check (via load balancer)
curl http://localhost:3100/health

# Cluster node status
curl -H "Authorization: Bearer $DAKERA_ROOT_API_KEY" \
  http://localhost:3100/admin/cluster/status

# List all nodes
curl -H "Authorization: Bearer $DAKERA_ROOT_API_KEY" \
  http://localhost:3100/admin/cluster/nodes

Failover behaviour

Traefik health-checks each node via /health every 10 s. If a node fails its checks, Traefik stops routing traffic to it within one check interval. The gossip protocol detects the departure and removes the node from cluster membership. When the node recovers it rejoins automatically.

# Simulate node failure (test failover)
docker stop dakera-2

# Verify the cluster still responds
curl http://localhost:3100/health  # should still return {"status":"ok"}

# Restore the node
docker start dakera-2

Scaling

To add nodes, extend docker-compose.ha.yml with additional service blocks using the same gossip seed address (DAKERA_GOSSIP_SEED=dakera-1:7946). For Kubernetes, increase dakera.replicaCount in the Helm values — the HPA handles autoscaling up to 5 replicas at 70% CPU utilisation by default.

HA key environment variables

VariableDescription
DAKERA_CLUSTER_MODE=haEnable HA mode (gossip + shared state)
DAKERA_GOSSIP_SEEDBootstrap peer address (host:port)
DAKERA_NODE_IDUnique identifier for this node
DAKERA_STORAGE=s3All nodes must share an S3-compatible backend
DAKERA_S3_BUCKETShared bucket for indexes and metadata

Production considerations

  • Use a dedicated MinIO cluster (or managed S3) for the shared storage tier — avoid single-point-of-failure on the storage node.
  • Place the load balancer (Traefik / nginx / AWS ALB) outside the Dakera node pool to ensure it survives individual node failures.
  • Enable Prometheus scraping on all nodes — the cluster health dashboard aggregates per-node metrics automatically.
  • Run odd replica counts (3, 5) to maintain quorum during leader election.

Related

Deployment → Troubleshooting → dakera-deploy repo ↗

How Memory Works

Before writing your first memory, it helps to understand Dakera's core primitives. Once you understand agents, importance, and retrieval, the API will make intuitive sense.

Core primitives

Agents

An agent is a named memory namespace identified by a string you choose. All memories belong to an agent. Agents are isolated by default — a recall call on agent-A never returns memories from agent-B.

You can have as many agents as you need — one per user, one per pipeline stage, one per AI persona. There's no registration step; Dakera creates the namespace automatically the first time you store a memory for it.

Multi-agent access — To share memory across agents, use the cross-agent knowledge network API (/v1/knowledge/network/cross-agent). See Patterns & Recipes →

Memory types

Every memory has a memory_type that controls how it is used and how quickly it decays:

TypeUse forDecay rate
episodicSpecific events, user actions, conversation historyNormal (default)
semanticFacts, knowledge, learned patterns — more durableSlow
proceduralInstructions, skills, how-to knowledgeSlow
workingShort-term scratchpad, current task contextFast

If you omit memory_type, it defaults to episodic.

Importance scoring

Every memory has an importance score from 0.0 to 1.0. Importance affects:

  • Recall ranking — higher-importance memories score better in retrieval, all else equal
  • Decay resistance — memories with high importance fade more slowly over time
  • Batch filtering — use min_importance to exclude low-signal memories

Rough guide: 0.9+ for critical facts, 0.7–0.8 for important context, 0.5 for routine observations (the default), 0.3 for ephemeral state. When a recalled memory is accessed, Dakera automatically boosts its importance slightly — frequently-retrieved memories stay relevant longer.

Memory decay

Memories decay over time when not accessed. Rarely-recalled information fades; frequently-retrieved knowledge stays sharp. Decay rate is governed by memory_type and importance. Configure the half-life via DAKERA_DECAY_HALF_LIFE_SECS (default 7 days) — see Configuration →

To expire a memory after a known deadline, set expires_at to a Unix timestamp at store time. The decay engine hard-deletes expired memories automatically.

Sessions

A session groups related memories under a single ID. Sessions are optional but useful for:

  • Scoping recall to a single conversation or task
  • Retrieving all memories from a specific interaction via /v1/sessions/{id}/memories
  • Per-session deduplication and auto-generated summaries

Start a session with POST /v1/sessions/start, pass the returned session_id to /v1/memory/store, then close it with POST /v1/sessions/{id}/end.

Namespaces

Namespaces are the low-level isolation unit for vector data. Each namespace has its own HNSW index, BM25 index, and embedding configuration. The memory API routes to namespaces automatically via agent IDs — you only interact with namespaces directly when using the low-level vector search API (/v1/namespaces/) for RAG or custom search use cases.

The retrieval pipeline

When you call recall, Dakera runs a three-stage pipeline:

1

Embed

Your query is embedded using the configured ONNX model (default: MiniLM-L6-v2). Embedding runs on-device — no external API call, no latency added by network hops.

2

Retrieve

Vector ANN search (HNSW) and BM25 full-text search run in parallel. Results are merged using Reciprocal Rank Fusion (RRF). The ML routing classifier selects the optimal retrieval mode based on query characteristics.

3

Rank

Results are re-ranked combining semantic relevance score with importance and recency. Memories above the min_importance threshold are returned in ranked order.

What's next?

API Reference → Patterns & Recipes → Architecture deep-dive →

Patterns & Recipes

Common patterns for building production-grade agent memory systems.

Multi-agent memory sharing

By default, agents are isolated. To share knowledge across agents, use the cross-agent knowledge network endpoint. Useful for supervisor/worker pipelines where a parent agent needs context from sub-agents:

# Query memory across multiple agents
curl -X POST http://localhost:3300/v1/knowledge/network/cross-agent \
  -H "Authorization: Bearer $DAKERA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_ids": ["agent-a", "agent-b", "supervisor"],
    "query": "user preferences",
    "top_k": 5
  }'

Importance scoring guidelines

ScoreUse forExamples
0.9 – 1.0Critical, must-not-forget factsUser name, critical config, key decisions
0.7 – 0.8Important context and decisionsUser preferences, completed tasks, key findings
0.5Routine observations (default)Conversational notes, intermediate results
0.3Ephemeral / will decay fastTemporary state, telemetry markers

Memory decay & TTL

If memories are disappearing too quickly, raise their importance at store time (importance ≥ 0.8). To hard-expire a memory after a task, set expires_at to a Unix timestamp:

{
  "agent_id": "task-agent",
  "content": "Working on PR #123",
  "importance": 0.3,
  "expires_at": 1778800000  // Unix timestamp — memory hard-deleted after this
}

Session-scoped memory

For conversational agents, wrap each conversation in a session to isolate context and enable session-level retrieval:

# Start session
session = client.sessions.start(agent_id="my-agent")

# Store memories scoped to this session
client.memories.store(
    agent_id="my-agent",
    content="User asked about pricing",
    session_id=session.id
)

# End session
client.sessions.end(session_id=session.id)
const session = await client.sessions.start({ agentId: 'my-agent' });

await client.memories.store({
  agentId: 'my-agent',
  content: 'User asked about pricing',
  sessionId: session.id,
});

await client.sessions.end({ sessionId: session.id });

Batch recall with filters

Use batch_recall for filter-based lookups without a semantic query — useful for fetching all memories with specific tags, above an importance threshold, or within a time range:

POST /v1/memories/recall/batch
{
  "agent_id": "my-agent",
  "tags": ["preference", "critical"],
  "min_importance": 0.7,
  "created_after": 1778000000
}

Related docs

API Reference → How Memory Works → Troubleshooting →

Troubleshooting

Common issues and how to fix them. Always start with the health endpoint:

curl http://localhost:3300/health
# {"service":"dakera","status":"healthy","version":"0.11.55"}

Server not starting

Check container logs first: docker logs dakera --tail 50. Common causes:

  • Port conflict — Change DAKERA_PORT and the -p mapping in your Docker command
  • Volume permission error — Ensure the data directory is writable by the container user
  • Missing API key — Set DAKERA_ROOT_API_KEY in your environment

Authentication errors (401)

All authenticated requests need: Authorization: Bearer <your-api-key>

In SDKs, pass via environment variable (DAKERA_API_KEY=your-key) or the api_key / apiKey constructor parameter. Verify the key matches DAKERA_ROOT_API_KEY on the server.

No memories returned from recall

  • Wrong agent_id — Recall is scoped to a single agent. Verify it exactly matches what you stored with.
  • Nothing stored yet — Confirm with GET /v1/agents/{id}/sessions.
  • min_importance filter too high — Lower or remove the filter.
  • Query too different from stored content — Try a query closer to the stored text to verify retrieval is working, then refine.

Slow queries

  • First request after startup — Dakera loads ONNX models on first use; expect 1–2 s cold start. Subsequent calls are fast.
  • Large HNSW index — Above 1M vectors, consider tuning DAKERA_HNSW_CACHE_MAX and ensuring SSD-backed storage for faster I/O.
  • Slow storage backend — Use SSD-backed volumes. S3 storage adds latency — use filesystem mode for low-latency workloads.

Connection refused

  • Verify the server is running: docker ps | grep dakera
  • Use the server's public IP, not localhost, when the server is on a remote VM
  • Check firewall rules allow inbound traffic on port 3300 (or your configured port)

MCP server not connecting to Claude

  • Use an absolute path to the MCP binary in .mcp.json and ensure the file is executable
  • Verify DAKERA_URL in the MCP env config points to your running server
  • After editing .mcp.json, fully restart Claude Desktop / Claude Code
  • Run the MCP binary directly in a terminal to see startup errors

Related

Deployment → Configuration → Security → dakera-deploy repo ↗

Changelog

Recent Dakera releases. Full history at GitHub Releases and Docker Hub tags.

VersionDateHighlights
v0.11.55 LATEST May 2026 CE-118 temporal hybrid retrieval. Cat2 gate achieved (86.3%). 87.6% LoCoMo overall.
v0.11.54 May 2026 MCP: 83 tools. DAKERA_ENTITY_VECTOR_SEARCH enabled by default. Cross-encoder pipeline.
v0.11.45 Apr 2026 CE-71: ML routing classifier on by default. TEMPORAL_INFERENCE enabled. 87.1% LoCoMo.
v0.11.27 Apr 2026 HA cluster gossip stability improvements. MinIO throttle tuning.
v0.10.2 Apr 2026 Full stack release: server + py + js + rs + go SDKs simultaneously.
SDK versions — SDKs track the server minor version. Current: Python / JS / Go / Rust at v0.11.54, server at v0.11.55. See the Introduction → for the full packages table.

Release cadence

Dakera releases frequently — typically multiple versions per week during active development. All releases follow semantic versioning. Patch versions (0.x.y → 0.x.(y+1)) are always safe to upgrade to in-place.

Release artifacts

GitHub Releases ↗ Docker Hub ↗ PyPI ↗ Helm (ArtifactHub) ↗