Dakera ships as a release train: the Engine, Dashboard, Helm chart, the Python, TypeScript, Go and Rust SDKs, the CLI and the MCP server are released together and tested against each other. Each release below lists every component's version, what changed in it and what needs attention before you upgrade. Pick a component to see only its changes. The engine's full notes follow the trains.
Current versions
Release train 0.12.3. Each component works with the Engine versions its notes name; the SDKs, CLI and MCP server released with 0.12.3 also work against 0.12.0, 0.12.1 and 0.12.2 servers.
Current versions — release train 0.12.3 (Oct 22, 2026)
Release 0.12.3Documents become memory; recall you can sort on
Patch trainCurrent
Every component ships together. Engine 0.12.3 upgrades in place from 0.12.2, 0.12.1, 0.12.0 and 0.11.108: back up, then replace the image or binary. Agents can now import whole documents and cite them, recall gets a ranking field and a stable order, ingest and reranked recall run faster with less memory, and the images are signed and smaller. The Dashboard, SDKs, CLI and MCP server add document import and the new recall options and keep working against 0.12.0 to 0.12.2 servers, where the 0.12.3-only features fall back or stay hidden.
Engine0.12.3
Dashboard0.5.2
Helm chart0.12.3
Python SDK0.14.1
TypeScript SDK0.12.3
Go SDKv0.12.3
Rust SDK0.12.3
CLI0.8.2
MCP server0.12.3
Document import: PDF, DOCX, HTML, Markdown and plain text become searchable, citable memory chunks with heading breadcrumbs and page ranges.
Recall results carry rank_score, which follows their order; asking for more results never reorders the first ten; neighborhood_mode puts session context inline, in its own list or nowhere.
event_time on stores: imported and replayed histories reason about time from their own dates.
Faster ingest and reranked recall with lower peak memory: one model worker per physical core, an exact rerank score cache and a fair rerank queue.
A busy server answers 429 with Retry-After instead of 503, and the REST port reports progress during crash recovery.
Signed images with SBOM and provenance, a smaller CPU image without curl (new dakera healthcheck) and a non-root GPU image on CUDA 13.
!Breaking / needs attention before upgrading
The images no longer contain curl. A health check that runs curl inside the container must use ["CMD", "dakera", "healthcheck", "/health/ready"] instead. Kubernetes httpGet probes are not affected.
AutoPilot deduplication is off by default. Set DAKERA_AUTOPILOT_DEDUP_MODE=merge to keep merging duplicates (it no longer merges across sessions) or report to only report them. Memories removed by deduplication or consolidation can be restored for 7 days (GET /v1/memory/deduplicated).
Authentication off, reached by a dotted host name? List the name in DAKERA_ALLOWED_HOSTS (or *), or every request except /health* is refused with 421.
Admin requests are strict:POST /ops/shutdown needs a global super_admin key, and creating keys, backups and encryption key rotations answer 422 to a field they do not know.
Behind a proxy or load balancer: idle keep-alive connections close after 30 s (DAKERA_HTTP_HEADER_READ_TIMEOUT_SECS); keep the proxy's upstream idle timeout below it.
GPU image: CUDA 13, running as a non-root user; it needs an NVIDIA driver R580 or later.
Document import: POST /v1/memory/documents and POST /v1/namespaces/{ns}/attachments/{ref}/document, with jobs, listing and delete; structure-aware chunking, parsing in a sandboxed child process.
neighborhood_mode, include_summaries and rank_score on recall; a stable head ranking; optional collapse of sentence sub-memories into their source.
event_time on store and batch store; recall and search for an agent with nothing stored answer 200 with no memories.
Model pools sized to physical cores and measured at startup, exact rerank score cache, default rerank candidate cap, searches keep CPU during ingest, parallel startup reads, memory returned to the OS after bursts.
Soft deletes with a restore window for deduplication and consolidation; every deletion audited; ignored request fields reported as warnings.
Overload answers 429 + Retry-After; header-read and HTTP/2 idle timeouts, a connection cap, a bounded shutdown and DNS-rebinding protection with authentication off.
Documents page: paste text, Markdown or HTML or upload a PDF or DOCX, follow each import, browse a document's chunks with pages and headings.
Recall lab: results ranked by the engine's rank score, citations for document chunks, session context listed in its own section.
Runs unprivileged (uid/gid 10001) and works with a read-only root filesystem; the sign-in throttle counts the real client behind a proxy (DAKERA_TRUSTED_PROXIES).
Works with Engine 0.12.0 to 0.12.2 too; 0.12.3-only features fall back or stay hidden.
!Needs attention: The image has no curl: point external probes at /_session/healthz over HTTP, or rely on the image's own health check.
New optional values for the 0.12.3 settings (httpHeaderReadTimeoutSecs, neighborhoodMode, allowedHosts and more), checked by values.schema.json; dakera.existingSecret for a Secret you manage.
Hardened defaults: a read-only root filesystem for the server and a network policy that lets only Dakera reach the built-in MinIO.
!Needs attention:dakera.readOnlyRootFilesystem is now true; set it to false to keep the previous behaviour. Anything else that reads the built-in MinIO goes in minio.networkPolicy.additionalFrom.
dk document import|job|list|show|delete: import a file and follow the job, list documents, show a document's chunks.
dk memory recall shows at most --top-k ranked results, session context in its own section and a SOURCE column for document chunks; --neighborhood and --include-summaries.
A hint names the field when an admin request is refused for an unknown field.
!Needs attention:dk --format json memory recall prints one object, {"memories": [...], "context_memories": [...]}, instead of an array: read the results from .memories.
New tools: dakera_import_document, dakera_document_status, dakera_list_documents, dakera_delete_document; recall results that are document chunks carry a citation.
dakera_recall and dakera_recall_associated return at most top_k ranked results, with session context listed apart (neighborhood_mode).
Profiles: all 106 tools, power 86, core 14, admin 34. The API key never reaches the logs.
Release 0.12.2Scoped keys, server-side agents and sessions that close themselves
Patch train
Every component ships together. Engine 0.12.2 upgrades in place from 0.12.1, 0.12.0 and 0.11.108: back up, then replace the image or binary. The Dashboard, SDKs, CLI and MCP server add the new routes and keep working against 0.12.0 and 0.12.1 servers, where the 0.12.2-only features fall back or stay hidden.
Engine0.12.2
Dashboard0.5.1
Helm chart0.12.2
Python SDK0.14.0
TypeScript SDK0.12.2
Go SDKv0.12.2
Rust SDK0.12.2
CLI0.8.1
MCP server0.12.2
Updates no longer fail with 503 "changed during each of 5 attempts": every JSON store returns records bit-for-bit as written.
Key grants take prefix patterns (team-*), keys are edited in place (PATCH), rotation has a grace period, and GET /v1/auth/whoami shows what a key can reach.
POST /v1/agents creates an agent before its first memory.
Idle sessions end after 4 h by default; POST /v1/sessions/{id}/touch keeps a quiet one open.
Graph View and memory lists serve an opt-in content preview (content_preview_chars).
!Breaking / needs attention before upgrading
Sessions end after 4 hours without activity by default. Set DAKERA_SESSION_IDLE_TIMEOUT_SECS=0 (Helm: dakera.config.sessionIdleTimeoutSecs: "0") or start sessions with idle_timeout_secs: 0 to keep the old behaviour. Orphan sessions open longer than the timeout are closed, with their summaries, on the first passes after the upgrade.
Stricter validation (400): memory metadata, the content limit (now UTF-8 bytes, DAKERA_MAX_MEMORY_CONTENT_BYTES, also on update), reserved markers and ids, key namespace lists and imports; raw vector routes no longer write memory records into agent namespaces.
Authorization tightened: sessions are authorized by their agent (no _dakera_sessions grant), ending a session with a Read key is 403, open event streams re-check scope, agent ids are at most 241 bytes. A foo* entry on a key created before 0.12.2 stays inert until the key's namespaces are saved again.
Listings leave derived records out:include_derived=true restores sentence sub-memories on agent memories and wake-up. The MCP listing tools now return 500-character previews by default (content_preview_chars: 0 for full content).
Rollback to v0.11.108 needs dakera downgrade run with the 0.12.2 image (it rewrites the new binary hot-tier records as JSON first). Going back to 0.12.1 or 0.12.0 needs nothing.
Fixed: namespace-key responses no longer raise KeyError; async list_namespaces() and session_memories() match the sync client.
!Needs attention:create_key() and create_namespace_key() now send scope (keyword, default "read"); the server requires it, so calls without it used to fail with 422.
The Python SDK is numbered ahead of the server; 0.14.0 is the release for Engine 0.12.2.
!Needs attention: Source-breaking for struct literals: FullKnowledgeGraphRequest, CrossAgentNetworkRequest and SessionStartRequest gain fields (use ..Default::default()); CreateNamespaceKeyRequest needs a scope.
New tools: dakera_session_touch, dakera_agent_create, dakera_whoami.
idle_timeout_secs on session start; include_derived on memories and wake-up; field-named hints on 400 answers.
Profiles: all 102 tools, power 82, core 14, admin 34.
!Needs attention: Memory listing tools return 500-character previews by default (content_preview_chars; 0 returns full content). dakera_memory_get and recall still return full memories.
Release 0.12.1Upgrades need fewer steps; the Dashboard signs operators in
Patch train
Engine 0.12.1 makes keyword search and model changes work after an upgrade without operator steps, and fixes the figures the Dashboard shows. The Helm chart stops handing the Dashboard the root API key. The SDKs and CLI from the 0.12.0 train are unchanged (Python had a 0.13.2 fix on 2026-10-02).
Engine0.12.1
Dashboard0.5.0
Helm chart0.12.1
Python SDK0.13.2
TypeScript SDK0.12.1
Go SDKv0.12.1
Rust SDK0.12.1
CLI0.8.0
MCP server0.12.0
Full-text indexes built by v0.11 answer keyword queries again, re-analysed in the background.
Changing DAKERA_MODEL re-embeds the store by itself while recall stays correct.
Memory, session and agent counts agree across endpoints and no longer read every record.
Dashboard 0.5.0: six-area navigation, an Operations hub, analytics and metrics; the Helm chart now deploys it with sign-in instead of handing it the root key.
!Breaking / needs attention before upgrading
Clusters need DAKERA_CLUSTER_SECRET on every node, upgraded or not; a cluster node without it refuses to start. Set the same secret everywhere and upgrade the nodes in one window. Single-node deployments are not affected.
Memory totals count memories, not stored records: memory counts drop and session counts include ended sessions. Re-base dashboards and alerts.
Helm: rotate dakera.rootApiKey if the old Dashboard (0.3.x, which embedded the root key in its pages) was reachable by anyone who should not hold it.
Release 0.12.0Multilingual, multimodal and multi-vector memory
Minor train
The v0.12 line. Every new engine feature is opt-in and an unchanged v0.11.108 deployment upgrades in place; dakera downgrade goes back. The Dashboard, SDKs, CLI and MCP server add v0.12 support and keep working against v0.11.108.
Engine0.12.0
Dashboard0.4.0
Helm chart0.12.0
Python SDK0.13.1
TypeScript SDK0.12.1
Go SDKv0.12.1
Rust SDK0.12.1
CLI0.8.0
MCP server0.11.0
Opt-in multilingual search (bge-m3, per-language stemming, dates in seven query languages) and multimodal memory (attachments, speech to text, image indexing, records).
Reranked recall at top_k 16: 11.5 s → 6.2 s, container memory 4.98 GB → 0.65 GB (4 CPU / 8 GiB).
gRPC requires an API key; encrypted data is bound to its record; cluster traffic is authenticated.
dakera downgrade converts a stopped deployment back to what v0.11.108 reads.
!Breaking / needs attention before upgrading
gRPC clients need an API key when authentication is on; keys pinned to namespaces get 403 on node-wide routes; backup download, upload and restore need super_admin.
Namespace quotas are enforced (413 over a hard quota); smart_score changes scale.
Health checks: point readiness at /health/ready and liveness at /health/live; run dakera --check-config with the new image first.
Helm: remove dakera.config.l2CachePath (v0.12 no longer reads DAKERA_L2_CACHE_PATH).
Everything that changed in the server, release by release, for operators planning an upgrade and developers tracking API changes: highlights, behavior changes with what to do, new features, measured performance, security, fixes and removals. A container image is published for every release to GHCR; self-host deploy bundles are on GitHub Releases.
Engine v0.12.3 2026-10-22CURRENT
v0.12.3 upgrades in place from v0.12.2, v0.12.1, v0.12.0 and v0.11.108: back up, then replace the image or binary. Nothing is migrated by hand, and the stored formats are those of v0.12.2, so going back to v0.12.2 needs nothing. Agents can now import whole documents and cite them, recall gains a ranking field that follows result order and a ranking that no longer shifts with top_k, ingest and reranked recall run faster with less memory, and the images are signed and smaller. Four changes need attention before the upgrade: the images no longer contain curl, AutoPilot deduplication is off by default, deployments with authentication off accept only known host names, and admin requests are stricter.
Documents become memory. PDF, DOCX, HTML, Markdown and plain text are imported as searchable chunk memories of an agent. Chunking follows the document's structure (sections at headings, then paragraphs and sentences; code blocks and table rows kept whole while they fit), stays within the embedding model's token budget, and every chunk carries its heading breadcrumb, page range and position, so an agent can cite what it recalls. Re-importing a document keeps unchanged chunks; a failed import leaves the earlier version as it was. PDF and DOCX are parsed in a sandboxed child process with time, memory and file limits, so a malformed file fails its import and never the server.
Recall you can sort on. Every result carries rank_score, the score the results are ordered by, which never rises down the list (score keeps its meaning). The first ten results of a recall no longer change when you ask for more, so paging and evaluation see one stable ranking.
Session context where you want it.neighborhood_mode on recall puts the neighbouring memories of a session inline after the ranked results (the default, as before, now marked retrieval: "neighborhood"), in their own context_memories list with context_of, or nowhere. A document chunk's context is the chunk before and after it.
History on its own clock.event_time on store and batch store records when the event happened. Recency, time windows, supersession and the order of events read it, so an imported or replayed history reasons about time from its own dates instead of the moment it was ingested.
Faster ingest and reranked recall, lower peak memory. The embedder and reranker run one worker per physical core in a layout measured at startup; identical reranker inputs are scored once from an exact cache; the reranker queue serves every recall fairly and has a default candidate cap; searches keep a share of the CPU while ingest runs; entity extraction runs on a small session pool; batch stores extract entities like single stores.
Lighter on memory and quicker to start. Startup reads namespaces in parallel, the vector index cache is sized by memory instead of a fixed count, freed memory goes back to the operating system after a burst, model conversion on a first start runs in a child process, unchanged stores are not checkpointed again, and the open-files limit is raised at startup.
Calmer under pressure. A busy server answers 429 with Retry-After instead of 503 (the SDKs, MCP server and Dashboard already retry it; the CLI exits with code 6 and prints the Retry-After hint). If storage stops accepting writes, the server recovers in process; /health reports it and clears on recovery. During crash recovery the REST port answers, with its progress in /health.
Safer with your data. Memories removed by deduplication or consolidation can be restored for 7 days, and every such deletion is in the audit log. Store and recall report request fields they ignored as warnings, so a misspelled field no longer goes unnoticed. Recall and search for an agent that has stored nothing answer 200 with no memories.
Hardened images and connections. Release images are signed (keyless, Sigstore) with an SBOM and provenance; the CPU image is distroless, with no curl and no package manager; the GPU image runs as a non-root user on CUDA 13. The REST port has a request-header read timeout, closes idle HTTP/2 connections, caps concurrent connections and bounds the graceful shutdown.
Breaking or behavior changes
No curl in the images. The server image probes itself with dakera healthcheck [PATH] (default /health; exit 0 only on 200). What to do: change any health check that runs curl inside the container to ["CMD", "dakera", "healthcheck", "/health/ready"]. Kubernetes httpGet probes and checks from outside the container are not affected.
AutoPilot deduplication is off by default. New DAKERA_AUTOPILOT_DEDUP_MODE: off (default), report (find duplicate groups and report them in GET /admin/autopilot/status, change nothing) or merge (the previous default). In merge mode memories of two different sessions are no longer merged (DAKERA_AUTOPILOT_DEDUP_CROSS_SESSION=true allows it), and consolidation groups one session's memories by default (DAKERA_AUTOPILOT_CONSOLIDATE_CROSS_SESSION). What to do: set DAKERA_AUTOPILOT_DEDUP_MODE=merge to keep merging duplicates automatically.
DNS rebinding protection with authentication off. A request whose Host is a dotted name that is not listed in the new DAKERA_ALLOWED_HOSTS (comma-separated, * = any) is refused with 421 HOST_NOT_ALLOWED. localhost, IP addresses, single-label names (a Compose service), private names such as *.internal and *.local, and /health* are always served. Authentication on: unchanged. What to do: an auth-off deployment reached by a dotted host name lists it in DAKERA_ALLOWED_HOSTS.
Stricter admin requests.POST /ops/shutdown needs a global super_admin key (a global admin key gets 403). POST /admin/keys, POST /v1/namespaces/{ns}/keys, POST /admin/backups and POST /admin/encryption/rotate-key answer 422 to a field they do not know instead of ignoring it. Data-plane requests stay lenient.
Overload is 429. A store, batch store or recall that waits longer than DAKERA_ADMISSION_WAIT_SECS (default 20 s) for capacity answers 429 with Retry-After: 5 and code RATE_LIMIT_EXCEEDED, instead of 503. A server that is shutting down still answers 503.
Connections. An idle keep-alive or HTTP/2 connection is closed after DAKERA_HTTP_HEADER_READ_TIMEOUT_SECS (default 30 s), at most DAKERA_MAX_CONNECTIONS (default 10000) connections are served at once, and the shutdown drain waits at most DAKERA_SHUTDOWN_DRAIN_SECS (default 8 s). What to do: behind a proxy or load balancer, keep its upstream idle timeout below 30 s or raise the server's.
GPU image on CUDA 13. It runs as user 1000:1000, like the CPU image, and needs an NVIDIA driver R580 or later.
Rerank candidates are capped by default. Unset, DAKERA_RERANK_MAX_CANDIDATES now caps the reranker at the pool a top_k 10 recall builds, so a large top_k no longer sends hundreds of pairs to the reranker; 0 removes the cap. rerank_candidates: 0 is a 400 (omit the field or send rerank: false), and rerank_report.capped says when the cap applied.
New
Document import: POST /v1/memory/documents (text, Markdown or HTML sent as JSON) and POST /v1/namespaces/{ns}/attachments/{ref}/document (an uploaded PDF, DOCX or text attachment) answer 202 with a job; GET /v1/memory/documents/jobs/{job_id}, GET /v1/memory/documents, and GET / DELETE /v1/memory/documents/{document_id} follow, list, inspect and delete documents. Chunks carry _dakera_document (document id, title, pages, heading path, chunk index and count). On by default (DAKERA_DOCUMENTS); GET /v1/capabilities reports documents.
Recall: neighborhood_mode (inline, separate, off; server default DAKERA_NEIGHBORHOOD_MODE), include_summaries, and on results rank_score, retrieval and context_of. With DAKERA_RECALL_COLLAPSE_DERIVED=1 a sentence sub-memory and its source share one result, which carries matched_text and matched_ids.
event_time on POST /v1/memory/store and each item of POST /v1/memories/store/batch: Unix seconds or an RFC 3339 timestamp. created_at stays the ingest time.
Restorable deletions: GET /v1/memory/deduplicated?agent_id= lists memories removed by deduplication or consolidation and POST /v1/memory/deduplicated/{id}/restore?agent_id= puts one back, for DAKERA_AUTOPILOT_TRASH_RETENTION_HOURS (default 168). Each deletion and restore is an audit event.
warnings on store, batch store, recall and batch recall responses (and an X-Dakera-Ignored-Fields header) name request fields the server ignored.
dakera healthcheck [PATH]: the container health probe, built into the server binary.
GET /v1/memory/get/{id} works without agent_id, searching the agents the key may read; session ids may contain : (user:42).
Configuration: document import limits (DAKERA_DOCUMENT_*), DAKERA_ADMISSION_WAIT_SECS, DAKERA_INTERACTIVE_MIN_CORES, DAKERA_RERANK_CACHE_ENTRIES, DAKERA_HNSW_CACHE_BYTES, DAKERA_AUDIT_SAMPLE_RATE and the settings above; see Configuration.
Fixes
A superseded fact no longer comes back as neighbourhood context, and a dated history imported in one burst marks its outdated facts.
Neighbourhood context obeys the request: its filters, time window and memory expiry.
Entity extraction no longer tags pronouns, single characters or numbers as people, organisations or places, and drops punctuation picked up at the edges of a name.
Session summaries are dated by their session's last memory and no longer add duplicate sentence sub-memories.
A reranker that fails to load comes back by itself instead of failing every request.
Snapshot restore is all or nothing: every namespace is checked before the first write.
Text longer than the embedding model reads is reported instead of being cut without a word.
Batch queries are bounded, POST /v1/import is rate-limited like a batch store, a namespace key never outlives the key that minted it, and attachment downloads are always served as downloads.
Upgrade
From v0.12.2, v0.12.1 or v0.12.0: take a backup (POST /admin/backups), move health checks off curl, give tooling that calls POST /ops/shutdown a super_admin key, then start ghcr.io/dakera-ai/dakera:0.12.3 on the same data (Upgrading from v0.12.2 to v0.12.3). From v0.12.1 or v0.12.0, also follow the earlier sections of that guide.
From v0.11.108: follow Upgrading to v0.12, then the v0.12.3 checks above.
Back: to v0.12.2, start the older image; the stored formats are unchanged. To v0.11.108, Rolling back to v0.11.
Dashboard:Dashboard 0.5.2 is released with v0.12.3 and adds the Documents page and the new recall views; it also works with v0.12.0 to v0.12.2.
Engine v0.12.2 2026-10-08
v0.12.2 upgrades in place from v0.12.1, v0.12.0 and v0.11.108: back up, then replace the image or binary. Nothing is migrated by hand. It fixes updates that failed with 503, makes scoped keys fit how teams work, lets the server create agents and end idle sessions, and keeps the Graph View and memory lists light. Four changes need attention before the upgrade: sessions end after 4 hours of inactivity by default, validation is stricter on every write path, session and key authorization is tightened, and agent listings leave derived records out.
Updates no longer fail with 503 "changed during each of 5 attempts" (#305). Records read back from every JSON store are now bit-for-bit what was written (about 10% of numbers, such as importance 0.11, came back one unit in the last place off), every store keeps ttl_seconds, and conditional writes compare a node-local write revision instead of the whole record. No data migration.
Scoped keys fit how teams work (#303): prefix patterns in key grants (team-*, _dakera_agent_mlx-*), editing a key in place (PATCH), a rotation grace period so live clients keep working, and GET /v1/auth/whoami.
Agents are a server concept (#304): POST /v1/agents creates an agent before its first memory, and namespaces report their kind (agent, data, system).
Sessions close themselves. An idle session is ended after DAKERA_SESSION_IDLE_TIMEOUT_SECS (default 4 h) exactly as a client end would, with ended_reason: "idle". POST /v1/sessions/{id}/touch keeps a quiet session open, and a session can set its own timeout (0 = never).
Graph View and memory lists stay light. The knowledge graph and the memory listings serve an opt-in content preview (content_preview_chars), and the server reads only the graph nodes it serves: a 200-node graph of 90 KB memories with a 200-character preview is under 200 KB.
Derived data is durable. Sentence sub-memories, graph edges and full-text entries are no longer left stale or dropped under load, a background reconciler repairs what a crash left owed, and sub-memories no longer show up in agent listings or wake-up.
Node-wide endpoints answer within 2 s even when one namespace cannot be read, and say which one (unavailable).
RocksDB hot tier writes binary records: embeddings stored as raw floats take about a third of the bytes and decode several times faster.
Recall check: on the full LoCoMo run (1,540 questions, 1,536 scored) with the production configuration, v0.12.2 scores 89.5% Recall@10 overall (Cat1 89.7%, Cat2 88.2%, Cat3 73.9%, Cat4 91.7%), and every release gate passed. This is retrieval recall (Recall@10), not judged answer accuracy, and it is a different measurement from the evidence-match Recall@20 (v0.11.107) on the Benchmark page.
Breaking or behavior changes
Sessions end after 4 hours without activity by default. New DAKERA_SESSION_IDLE_TIMEOUT_SECS (default 14400; 0 = the server ends no session that did not set its own timeout; at most 30 days). The server ends an idle session with exactly what a client end does (memory count, auto-summary memory when it holds more than 3 memories, session-end consolidation) and records ended_reason: "idle" and idle_since. Activity is a memory stored, batch-stored, imported or updated with the session, a session-scoped recall or search, or POST /v1/sessions/{id}/touch. Sessions already open longer than the timeout (orphans of crashed agents) are closed, with their summaries, on the first passes after the upgrade. Storing into an ended session still answers 200, with session_state: "ended". What to do: to keep the old behavior set DAKERA_SESSION_IDLE_TIMEOUT_SECS=0, or start sessions with idle_timeout_secs: 0; an agent that keeps a session open while idle sends touch.
Stricter validation on every write path (400, and the message names the field and the rule):
The memory content limit is in UTF-8 bytes and configurable: DAKERA_MAX_MEMORY_CONTENT_BYTES (default 100000). PUT /v1/memory/update/{id} now enforces it too (a memory already above it may be updated to content no larger than it is now), as do session-end summaries and consolidated or summarized output.
User metadata is checked on store, batch, update, import, transcribe and index: a JSON object (or null) of at most 100 top-level fields, keys of 1 to 256 bytes, no larger than the content limit serialized.
Reserved markers are refused from clients: the dakera-curated tag, and _dakera_* metadata keys other than _dakera_content_date (an integer, unix seconds) and _dakera_lang (a supported language). Caller ids of the form mem_s + 24 hex characters are reserved. ttl_seconds is at most 100 years.
The raw vector routes of an agent namespace (/v1/namespaces/_dakera_agent_*/vectors, upsert-columns, records, upsert-text, bulk-update and gRPC Upsert) no longer write or replace memory records; use /v1/memory/*. Plain vectors are unaffected.
POST /v1/import validates each item as a new memory and skips refused items with their reason in the job's errors; an imported attachment_ref must resolve.
Key namespace lists are validated on create, PATCH and extra_namespaces: junk entries ("a**b?", blank, "*" mixed with names), internal namespaces and patterns that could cover them are refused. [] still means no namespace.
Agent ids are at most 241 bytes (was 256). _dakera_embedding_models is reserved.
Authorization tightened. Sessions are authorized by their agent only: keys no longer need a _dakera_sessions grant (such an entry is accepted and grants nothing), and a key without grants lists no sessions. POST /v1/sessions/{id}/end checks Write scope first (a Read key gets 403), and ending a session of an agent the key cannot reach returns the same idempotent 200 as an unknown session and writes nothing. Open event streams re-check scope and namespaces every 15 s. Key deactivation can no longer be undone by a concurrent edit or a late replicated add.
Existing foo* key entries stay inert. A key created before v0.12.2 keeps reading foo* as a literal name that grants nothing, across restarts, renames and rotations, until its namespaces are saved again with PATCH. An upgrade never widens a key's access.
Listings leave derived records out.GET /v1/agents/{id}/memories and GET /v1/agents/{id}/wake-up no longer include sentence sub-memories (include_derived=true restores them); wake-up total_available counts memories only. GET /v1/agentsvector_count no longer counts the namespace seed. New sentence sub-memories get deterministic ids (mem_s + 24 hex).
Merges are validated. Consolidation (manual and AutoPilot) and POST /v1/knowledge/summarize refuse a merge with more than 50 tags or text over the content limit (400, nothing written); POST /v1/knowledge/deduplicate caps the merged tags at 50 (the rest stay in the duplicate's provenance record); POST /v1/agents/{id}/compress skips a summary it cannot store (new summaries_skipped) and no longer deprecates that cluster's originals.
Storage. The RocksDB hot tier writes binary records (DAKERA_ROCKSDB_RECORD_FORMAT=binary; json restores the previous writer, and both are always read). Rolling back to v0.12.0 or v0.12.1 needs nothing; before starting v0.11.108 on this data, run dakera downgrade, which now rewrites binary records as JSON first. Metadata null is stored as no metadata everywhere. Namespaces and record ids longer than 200 bytes, now storable on filesystem and S3, cannot be addressed by v0.11.108.
New
Key grants with prefix patterns: p* (one trailing star). Patterns are strict (team-* reaches team-a, not team or team-) and never reach a server-internal namespace. ["_dakera_agent_mlx-*"] lets a developer key create and use its own agents.
PATCH /admin/keys/{key_id} (super_admin) renames a key or replaces its namespaces; PATCH /v1/namespaces/{ns}/keys/{key_id} does the same for namespace admins, within their own grants. scope cannot be changed.
Rotation grace period: POST /admin/keys/{key_id}/rotate accepts {"grace_secs": N} (up to 604800, 7 days); the old key keeps working until then, and the response adds old_key_id and old_key_expires_at. An empty body behaves as before.
GET /v1/auth/whoami: the key a request authenticates with, as the server reads it (scope, namespaces, unrestricted, expires_at, grants_version, inert_namespaces, auth_enabled). Key details gain grants_version and inert_namespaces.
POST /v1/agents {"agent_id"} creates an agent before its first memory: 201 when created, 200 with created: false for an existing agent, which is not modified. Needs Write on the agent's namespace.
Session lifecycle: POST /v1/sessions/{id}/touch; idle_timeout_secs on POST /v1/sessions/start; last_activity_at, ended_reason (client | idle), idle_since and idle_timeout_secs on sessions; session_idle_timeout_secs in GET/PUT /admin/config; a reason on session_ended events; the batch store response lists ended_sessions.
Content preview: content_preview_chars (1 to 10000) on POST /v1/knowledge/graph/full, POST /v1/knowledge/network/cross-agent, GET /v1/agents/{id}/memories and GET /v1/sessions/{id}/memories cuts each memory's content (never mid-character) and adds content_len and content_truncated. Without it responses are unchanged.
kind on namespace details and GET /admin/namespaces, a kinds map on GET /v1/namespaces; GET /v1/capabilities is capabilities_version: 2 with auth, naming and sessions blocks.
GET /admin/derivations/status and POST /admin/derivations/drain (global admin) for the derivation reconciler; unavailable on node-wide endpoints; duplicates_skipped_changed on deduplicate.
Configuration: DAKERA_SESSION_IDLE_TIMEOUT_SECS, DAKERA_MAX_MEMORY_CONTENT_BYTES, DAKERA_ROCKSDB_RECORD_FORMAT and DAKERA_VECTOR_CACHE_BYTES (the in-process vector cache, default 128 MB). Metrics: dakera_sessions_auto_ended_total, dakera_conditional_write_conflicts_total, dakera_conditional_write_exhausted_total, dakera_namespace_unavailable_total.
Fixes
ttl_seconds is kept by every store: filesystem and S3 records, warm and cold tier copies, WAL replay, snapshot restore and export/import returned null, which made every TTL memory un-updatable there.
Long namespaces and record ids (over 200 bytes, such as an agent id of 241 bytes) can be stored on filesystem, S3 and tiered storage instead of failing with "File name too long". Shorter names keep their paths.
Stale sentence sub-memories no longer survive updates. An update is a diff: sub-memories of removed sentences are deleted before the write returns, kept ones are not re-embedded, and sentences refused under backpressure are retried instead of dropped. An update that does not change the text re-embeds nothing.
Graph edges and full-text entries lost in a crash are rebuilt, and sub-memories orphaned by expiry or decay are deleted, by the background reconciler.
The ODE webhook is no longer lost after four attempts: delivery goes through a persisted outbox.
Graph API sized to the graph: the full graph and the cross-agent network read only the nodes they serve, sub-memories and the namespace seed are never nodes, and stats.total_memories matches GET /v1/agentsmemory_count.
Node-wide endpoints no longer wait on a namespace the storage cannot list: work runs concurrently under a 2 s deadline per namespace, and a failure is reported.
Upgrade
From v0.12.1 or v0.12.0: take a backup (POST /admin/backups), then start ghcr.io/dakera-ai/dakera:0.12.2 on the same data. Check the session timeout, keys with * entries, clients that write reserved markers or over-size content, and listings that relied on sub-memories (Upgrading from v0.12.1 to v0.12.2). On the first start the reconciler heals existing sentence sub-memories in the background; GET /admin/derivations/status shows its progress.
From v0.11.108: follow Upgrading to v0.12, then the v0.12.2 checks above.
Back: to v0.12.1 or v0.12.0, start the older image (it reads binary records). To v0.11.108, Rolling back to v0.11: dakera downgrade rewrites binary hot-tier records as JSON first.
Dashboard:Dashboard 0.5.1 is released with v0.12.2 and uses its new routes (Add agent, key edits, rotation grace, session lifecycle); it also works with v0.12.0 and v0.12.1.
Engine v0.12.1 2026-10-05
v0.12.1 is a patch release on v0.12.0: stop v0.12.0 and start v0.12.1 on the same data and environment. The stored record, index and snapshot formats are those of v0.12.0, and an upgrade from v0.11.108 straight to v0.12.1 is supported. Two things need attention before the upgrade: cluster nodes need DAKERA_CLUSTER_SECRET, and memory and session totals change meaning. Single-node deployments that do not report on those totals have nothing to do.
Every cluster node requires DAKERA_CLUSTER_SECRET, upgraded or not. On v0.12.0 an upgraded cluster node without a secret started with its node-to-node routes unauthenticated, as in v0.11, and POST /internal/sync/key/add then let anyone who reached the API port mint a SuperAdmin key. A cluster node without the secret now refuses to start (exit 78) and says why; dakera --check-config reports a missing or short secret. What to do: generate one secret (at least 16 characters, for example openssl rand -hex 32), set it on every node, and upgrade the nodes in one window: nodes with and without the secret do not see each other, and v0.11 nodes send none. A cluster that already runs v0.12.0 with a secret upgrades node by node as usual. An upgraded node without DAKERA_CLUSTER_NODE_ID still starts with a stable generated id. Procedure: High availability and Upgrading to v0.12.
One definition for every total. A memory is a top-level memory an agent stored, a sub-memory is a sentence record Dakera derives from it for keyword search, and a vector is any stored record. The count endpoints used to mix them. GET /v1/agentsmemory_count is now the agent's memories (the old figure moves to the new vector_count); GET /v1/agents/{id}/statstotal_memories and GET /admin/memory-type-statstotal exclude sub-memories (new sub_memories); session totals count ended sessions too. GET /v1/ops/stats and GET /v1/analytics/overview gain total_memories and internal_vectors. What to do: expect memory counts to drop (by about the average number of sentences per memory, for agents that store multi-sentence memories) and session counts to rise on upgrade day; annotate dashboards, alerts and usage reports built on these fields. Field names and types are unchanged; storage, recall and quotas are not affected.
Changed
Changing DAKERA_MODEL re-embeds the store by itself. v0.12.0 refused to start on a store embedded with another model until DAKERA_ALLOW_MODEL_CHANGE=1 and POST /admin/namespaces/migrate-dimensions. The server now starts and re-embeds every agent namespace in the background, one at a time (leader-only in a cluster); until its turn each namespace is answered, queries and writes alike, with the model its memories are in, so recall stays correct throughout. Progress is in /healthembedding_model_change, and a restart resumes. Startup is still refused where the change cannot run in the background (DAKERA_TIERED=1, late-interaction scoring, the visual lane, or a recorded model this build does not know); there, migrate as on v0.12.0.
Fixes
Full-text indexes upgraded from v0.11 answer keyword queries again, with no operator step. An index v0.11 built without stemming was kept as built on v0.12.0, so release did not find released and keyword-routed recall could return nothing. Every full-text index built with another analyzer than the configured one is now re-analysed in the background at startup, one namespace at a time, while it keeps serving. The manual POST /admin/fulltext/reindex with {"rebuild": true} is no longer needed; if you already ran it on v0.12.0, nothing is left to do.
Statistics endpoints answer from maintained counts./admin/reembed/static-count, /admin/memory-type-stats, /admin/ttl/stats and /v1/agents/{id}/stats read every record on each call (16.6 s, 11.2 s, 6.2 s and 2.1 s on a 25k-record production store); they now add up the per-namespace memory index in memory.
Session and agent listings no longer read every session record (2.6 s, 2.4 s and 1.9 s with 5k sessions before). GET /v1/sessions?agent_id=… lists every session of the agent, not only the open ones, and GET /v1/kpissession_count_weekly counts the sessions started in the last 7 days.
GET /v1/agents lists every agent. Agents were discovered from session records only, so an agent with memories but no session was missing (41 of 84 agents on a production store).
Memory operations reach the KPI and analytics figures. Batch recall, batch store, memory search and memory updates were not counted, and every HTTP request (health probes included) fed the analytics query latency. Recalls and searches are now queries with their own latency, stores feed the store latency, and GET /v1/kpis gains a latency object that tells an idle window from a missing measurement.
Cache figures count the in-process cache, not only the Redis tier: a node without Redis showed no lookups.
Session summaries written before v0.12 read as text instead of their stored, compressed form, in responses, re-embedding and the full-text index.
Telemetry heartbeat values (when telemetry is on): the recall latency bucket covers the heartbeat's interval, namespace counts include agent namespaces, lifetime read and write counts are added, and the startup notice states that the hostname is sent.
Code audit fixes
From a code audit of 2026-10-04:
Security: a session summary holding z64: followed by multi-byte text crashed the server on read; the legacy summary reader decrypted any $enc$v1$ value a client embedded; POST /v1/memories/extract accepted any key; a rotated key with under a day left was born expired; the audit log took the client IP from X-Forwarded-For; event streams outlived their key's revocation; a PNG could inflate without bound; DAKERA_CORS_ORIGINS=* stopped the server at start.
Data: a dimension-changing re-embed deleted the namespace's attachments and could undo deletes and edits made on other nodes meanwhile; background rewrites could overwrite a user edit queued on a follower; a filter mixing a field with $or / $and dropped the field condition (bulk delete and update hit too much), $not now works and integers compare exactly; a clock step back could lose writes from WAL checkpoint snapshots, which were also built whole in memory under the write gate and not fsynced; a graceful stop syncs the WAL buffer; binary import no longer trusts its header's count; a failed atomic rename no longer falls back to a torn write.
Search:/multi-vector normalised the query under every metric (wrong Euclidean results); MMR returned a result for top_k=0 and broke ties at random; HNSW kept a stale top level after its entry point was deleted; a full-text index persisted without its total document length scored wrongly; out-of-range DAKERA_BM25_B / DAKERA_BM25_K1 gave NaN scores; decay raised importances already below its floor.
Upgrade
From v0.12.0: take a backup (POST /admin/backups), set DAKERA_CLUSTER_SECRET on every cluster node if it is not set yet, then stop v0.12.0 and start ghcr.io/dakera-ai/dakera:0.12.1 on the same data. Check that /health is ready, GET /v1/agents lists every agent and a keyword search returns hits. Going back to v0.12.0 is not part of the release checks: restore the backup if you need to.
From v0.11.108: follow Upgrading to v0.12; the full-text rebuild it used to require now happens by itself.
v0.12.0 upgrades in place from v0.11.108 and goes back with one command. Every new feature is opt-in: a v0.11.108 deployment that sets none of the new variables keeps its behavior, except for the changes listed under Breaking or behavior changes. Summary for users: What's new in v0.12. Operator guide: Upgrading to v0.12.
Multilingual search (opt-in): the bge-m3 embedding model (1024-d), full-text stemming and stop words per language, character-bigram indexing for Chinese, Japanese and Korean, dates understood in seven query languages, and a per-request lang.
Multimodal memory (opt-in): attachments referenced from memories, speech to text (five Whisper models, default whisper-base, multilingual with auto-detected language), and image indexing with visual recall over document pages (colmodernvbert).
Multi-vector records (opt-in): one indexed vector plus named extra representations, kept beside it by every storage backend, snapshots, export/import and replication.
Late interaction (opt-in): colbert-small reranks with per-token MaxSim; RaBitQ search mode, rerank controls and GET /v1/capabilities ship alongside.
Faster, leaner engine: vector search at 0.87 ms p50 / 1.17 ms p95 (recall@10 0.998, BEIR Quora 50k), reranking about 2× faster on the same CPU, and container memory after reranking from 4.98 GB to 0.65 GB (CPU-only, 4 vCPU / 8 GiB); HNSW memory per 1024-d vector is 43 % lower at the same recall@10.
Security hardening: gRPC requires an API key, encrypted values are bound to their record with keys in a replicated keyring, cluster traffic is authenticated, and namespace-pinned keys lose node-wide routes.
One-command rollback: dakera downgrade, shipped in the v0.12.0 binary, converts a stopped deployment's data back to what v0.11.108 reads. No v0.11 patch release is needed.
Breaking or behavior changes
What an existing deployment can notice after the upgrade, and what to do about each. Details: Upgrading to v0.12.
gRPC requires an API key. With authentication on (the default), every RPC except Health needs a key and is authorized per namespace like its REST twin. What to do: send the key in the call metadata (x-api-key or authorization: Bearer).
Tighter permissions. Keys pinned to namespaces get 403 on node-wide routes (/admin/* except four per-namespace routes, /ops/*, /v1/analytics/*, /v1/audit*, …); backup download, upload and restore need global super_admin (was admin). What to do: give node-wide tooling a key with no namespace restriction, and backup tooling a super_admin key.
Namespace quotas are enforced. v0.11 stored quotas but never checked them; with the default hard enforcement a write over a quota now gets 413 QUOTA_EXCEEDED. What to do: before upgrading, raise quotas you rely on not biting, or set their enforcement to soft or none.
Ranking follows the query more closely. A recall no longer raises the importance of what it returns, the access count is no longer a score term, and recency counts from created_at. smart_score changes scale: a memory earlier recalls had touched can score up to 0.27 lower. What to do: re-check absolute cuts on smart_score (DAKERA_ABSTAIN_MIN_SMART_SCORE, client-side filters).
A stored, enabled backup schedule runs at its next slot (v0.11 stored it and never ran it), and applies retention_days / max_backups to scheduled backups. What to do: to keep v0.11's behavior, send POST /admin/backups/schedule with {"enabled": false} before that slot.
The port binds before the models load./health/live answers 200 while models load; /health/ready and /health answer 503 with starting; other routes answer 503 with Retry-After: 5. What to do: point readiness at /health/ready and liveness at /health/live; clients that waited for the connection should wait for /health/ready.
Configuration is checked at startup. An upgraded deployment starts with warnings, never refusals (logged as CONFIGURATION WARNING and listed in /healthconfig_warnings); a fresh install with the same mistakes is refused (exit 78). One value refuses every deployment: DAKERA_WAL_SYNC=periodic:0. What to do: run the new image's dakera --check-config against your environment and data volume first, and fix each warning.
Stored memories are re-embedded once in the background on the document side (they were embedded with the query instruction): about 35 minutes per 10,000 memories on bge-large; recall is served throughout. What to do: nothing; watch /healthembed_migration.
Cluster upgrades. Cluster traffic can now be authenticated with DAKERA_CLUSTER_SECRET, and nodes must not share one S3 bucket. What to do: leave DAKERA_CLUSTER_SECRET unset until every node runs v0.12.0, keep the mixed period short, and give each node its own bucket. Superseded in v0.12.1: every cluster node now requires the secret; upgrade straight to v0.12.1 and set it on every node in one window.
Errors. Every error body is JSON ({error, code, status}), every 503 carries Retry-After, configuration errors are 501 (they were 503), and a body over the size limit is 413. What to do: honor Retry-After, and do not retry a 501: fix the settings it names.
Namespace config.PATCH /v1/namespaces/{ns}/config merges and answers 400 for an unknown field; PUT is a full replacement (it was a 405). What to do: clients that relied on PATCH clearing omitted fields, or on unknown fields being ignored, use PUT or send valid fields only.
Telemetry, when on, sends lifecycle events and a heartbeat every 6 hours (was 24); engine_started and the heartbeat carry the machine's hostname, and PostHog keeps the connecting IP and derives a coarse location (GeoIP). It never sends content, ids, secrets or paths. What to do: opt out with DAKERA_TELEMETRY=0 or DO_NOT_TRACK=1 (Telemetry).
POST /ops/shutdown shuts the server down. v0.11 answered it and kept running; it now starts the same graceful shutdown as SIGTERM. What to do: stop calling it from health checks or smoke tests.
Also changed:
One data root. Every local path derives from DAKERA_STORAGE_PATH; the images use /data (was /app/data). Data found at a pre-0.12 location while the new one is empty is used where it is, with a warning naming the variable that pins it. A second server on the same data root refuses to start.
Speech to text defaults to whisper-base (multilingual, language auto-detected), not English-only whisper-tiny.en. Speech is opt-in; a deployment that turns it on without DAKERA_WHISPER_MODEL transcribes with whisper-base. Set DAKERA_WHISPER_MODEL=whisper-tiny.en to keep the lightest English model.
Tiered storage keeps a RocksDB hot tier (was in memory), so a crash no longer loses acknowledged writes; it starts empty after the upgrade and reads fall through to warm and cold. DAKERA_HOT_TIER=memory keeps the old tier.
Embedding-model guard. The store records the model that produced its vectors; startup is refused when the configured model differs. To switch models, start once with DAKERA_ALLOW_MODEL_CHANGE=1, then re-embed with POST /admin/namespaces/migrate-dimensions. From v0.12.1 a model change re-embeds in the background instead, except under tiered mode, late-interaction scoring or the visual lane.
Model volumes. Do not run dakera models prune until you are staying on v0.12.0: it removes the files v0.11.108 reads.
New features
Search and ranking
Late interaction: DAKERA_SCORING_STRATEGY=late-interaction with DAKERA_MODEL=colbert-small (96-d token vectors) shortlists by a fixed-dimensional encoding (MUVERA) and reranks with MaxSim. The encoding builds in the background; until it is ready, recall uses the dense first stage and reports which stage it used. See Search and ranking.
RaBitQ search mode: DAKERA_SEARCH_MODE=rabitq with DAKERA_RABITQ_BITS (1–8), followed by an exact re-rank. A latency feature: codes sit next to the float vectors (no memory saving) and are rebuilt after a restart.
Rerank controls: rerank_candidates per request and DAKERA_RERANK_MAX_CANDIDATES server-wide cap how many candidates the cross-encoder scores; recall and /v1/memory/search answer rerank_report (applied, candidates, skipped).
GET /v1/capabilities (Read scope): models, index kinds, on-disk format version, query languages, scoring strategy, multimodal switches and reembed_pending.
Response fields: effective_top_k on /v1/memory/search, x-dakera-limit on capped listings, resource on every 404 body, cache_lookups on GET /v1/analytics/overview.
Multilingual
DAKERA_MODEL=bge-m3: 1024-d, CPU ONNX backend only; truncates at 2048 tokens by default, up to 8192 with DAKERA_MAX_SEQ_LENGTH. Use it on a fresh store, or migrate with the model-change flow.
Full-text per language: DAKERA_FULLTEXT_LANGUAGE (stemmer and stop words), DAKERA_FULLTEXT_CJK_BIGRAMS (unsegmented scripts, previously not indexed), and POST /admin/fulltext/reindex to switch an existing namespace.
Dates in seven query languages: DAKERA_QUERY_LANG (en, de, fr, es, it, pt, nl or auto).
Per-request lang on recall, store, batch store, update, search and extract; an unsupported lang is a 400. See Multilingual search.
Multimodal and records
Off by default: a server that sets none of these variables answers the routes 501 FEATURE_DISABLED and loads none of the models. See Multimodal memory and Records and multi-vector.
Attachments (DAKERA_ATTACHMENTS; DAKERA_ATTACHMENT_MAX_BYTES, default 25 MiB): content-addressed files per namespace under /v1/namespaces/{ns}/attachments, referenced from memories with attachment_ref, counted by quotas, replicated and backed up.
Speech to text (DAKERA_WHISPER_MODEL, default whisper-base): POST …/attachments/{ref}/transcribe stores a WAV recording's transcript as a memory in a background job. Five models: whisper-base (default, multilingual, recommended), whisper-tiny.en (lightest English), whisper-base.en (better English), whisper-tiny (lightest multilingual) and whisper-small (quality); a multilingual model detects the spoken language and records it as the memory's lang (an explicit lang overrides it). Models are SHA-pinned and covered by dakera models, memory admission and idle unloading.
Image indexing and visual recall (DAKERA_VISION, colmodernvbert): POST …/attachments/{ref}/index embeds a PNG page; with late interaction, recall searches the pages. Use a dedicated data root for a visual store.
Records (DAKERA_RECORDS): POST /v1/namespaces/{ns}/records stores one indexed vector plus named dense, token_multivector or patch_multivector representations as f32, f16 or i8.
Memory admission: every media job reserves its peak working memory first, waits up to 10 s, then answers 503 with Retry-After instead of risking an out-of-memory kill; idle models are unloaded.
Operations
dakera downgrade: converts a stopped deployment's data back to v0.11.108's format and prints a JSON report. See Rolling back to v0.11.
dakera --check-config: runs the startup configuration check alone and exits 0 (would start) or 78 (would refuse).
dakera models list | pull | prune: see, pre-fetch, bake into an image, or clean model files. The images ship their default models already converted, so an air-gapped start downloads nothing. Downloads honor HTTPS_PROXY, NO_PROXY, HF_ENDPOINT and HF_HUB_OFFLINE, and resume after an interruption. See Models and Docker.
Health: /health gains degraded, config_warnings and embed_migration, with gauges dakera_component_degraded and dakera_config_warnings.
Encryption key management: POST /admin/encryption/rotate-key can rotate one namespace; new GET /admin/encryption/status, POST /admin/encryption/reseal and POST /admin/encryption/keys/{key_id}/revoke-master.
Observability: Prometheus alert rules and a rebuilt Grafana dashboard, plus new metrics for model loads, backups, write-ahead log failures, storage write stalls, re-embed migration and cluster replication.
Helm chart: dakera.extraEnv, a model-pull init container with a cache volume, a pod security context (uid/gid 1000), and probes on /health/live and /health/ready behind a 10-minute startup probe.
Configuration registry: every variable the server reads is registered and checked at startup; an unknown DAKERA_* name is reported with the closest real name. DAKERA_RATE_LIMIT_RPS / DAKERA_RATE_LIMIT_BURST are the canonical rate-limit names (RATE_LIMIT_* still work, deprecated).
Storage, backups and cluster
Backups can be encrypted (encrypt, AES-256-GCM per file) and compressed (compression, zstd), carry attachments and graph edges, and restore to the exact point in time with "overwrite": true.
Versioned on-disk formats: records, snapshots, the write-ahead log, caches and imports carry or check a format version, so a record written by a newer build is refused or skipped, never misread.
Durable knowledge graph under the data root by default (it was in memory unless DAKERA_DATA_DIR was set).
Versioned cluster replication: every replicated record carries a version, deletes leave tombstones, and reconciliation merges both ways instead of overwriting followers; unacknowledged broadcasts go to a durable outbox. /admin/cluster/status reports the replication state. New variables include DAKERA_CLUSTER_SECRET, DAKERA_CLUSTER_OUTBOX_DIR, DAKERA_CLUSTER_TOMBSTONE_RETENTION_SECS (default 7 days) and DAKERA_ELECTION_LEASE_MS (default 15000). See High availability.
Performance
Measured figures only. “Before” is v0.11.108 unless noted. Methods and conditions: Performance.
Measurement
Before
v0.12.0
Reranked recall, top_k 16 †
11.5 s, 45 CPU-s
6.2 s, 24 CPU-s
Reranked recall, top_k 32 †
18.8 s
10.5 s
Two concurrent reranked recalls †
19.6 s
11.2 s
Container memory after reranking †
4.98 GB
0.65 GB, flat across top_k 1–32
Reranker load †
4.6 s
0.6 s
HNSW memory per 1024-d vector ‡
4.81 KB
2.76 KB (−43 %), recall@10 0.998 unchanged
HNSW search p50 / p95 ‡
1.07 / 1.44 ms
0.87 / 1.17 ms
HNSW build ‡
94 s
79 s
CPU Docker image (amd64)
—
783 MB; ready 4.4 s after start, no download in air-gapped or read-only starts
† CPU-only, 4 vCPU / 8 GiB container, bge-reranker-v2-m3 (568M-parameter cross-encoder), compared with v0.11.108 on the same machine; GPU or hosted rerankers are a different deployment class. ‡ BEIR Quora, 50k vectors.
ANN indexes are persisted and loaded at start instead of rebuilt; an expired memory no longer forces a full rebuild (about 2 minutes at 50k memories before).
WAL group commit: concurrent writes share one fdatasync, with durability unchanged.
One memory-mapped copy per CPU model, and a stored vector no longer depends on what else was in its batch.
Incremental full-text persistence, and no whole-namespace scans on request paths.
Security
gRPC authentication: the gRPC port had no authentication; it now requires an API key and is rate limited, time-bounded and audited like REST.
Record-bound encryption: every sealed value is written as $enc$v2$ (AES-256-GCM bound to its namespace, record id and field), so a value copied elsewhere no longer decrypts. $enc$v1$ values keep decrypting and are re-sealed in the background. Keys live in a replicated keyring; old keys are kept, so older backups still restore.
Decryption oracle closed: memory content is opened only under the namespace it was read from, and client-supplied sealed values are refused (400).
Encryption gaps: update_memory and consolidate stored content unencrypted with encryption at rest on; both now encrypt like store. Backups carry _text sealed.
Agent isolation: knowledge-graph edges are scoped by namespace (one agent could replace or delete another's edges); GET /v1/agents/{agent_id}/sessions requires access to the agent, and a session can no longer be taken over from another agent.
Cluster authentication: node-to-node routes require DAKERA_CLUSTER_SECRET (at least 16 characters, identical on every node), and gossip packets are HMAC-authenticated.
CORS: with authentication off and no DAKERA_CORS_ORIGINS, only loopback origins are allowed; DAKERA_CORS_CREDENTIALS=true is ignored with a wildcard origin.
Bounded inputs: imports, uploaded backup bundles, extractor responses, graph path searches and event streams are capped; extractor URLs stay inside the SSRF guard.
Secrets out of logs and responses: API keys in query parameters are redacted in the audit log, the S3 secret is no longer logged, and /health no longer shows filesystem paths or credential URLs.
Data lifecycle: forget removes a memory's sentence sub-memories; TTL expiry, decay and POST /admin/ttl/cleanup run the full forget clean-up; spaced-repetition TTL now reaches the sweep; memories report the TTL they were stored with; /v1/export carries plaintext and TTLs.
Dedup and consolidation: auto-pilot dedup merges only true duplicates and never folds a permanent memory into an expiring one; consolidation no longer destroys attachments, user metadata or TTLs.
Write-ahead log: write and fsync errors are returned instead of swallowed; a partial line can no longer cost the next acknowledged write at replay; one namespace's concurrent writes replay in order.
Tiered storage and caches: deleted records no longer come back from cold or from a cache backfill; deletes survive an S3 outage as durable tombstones.
Storage backends: RocksDB sweeps re-check candidates under the write lock; a locked or corrupt RocksDB store exits with REFUSING TO START instead of panicking; S3 and segmented storage fixes for late writes, namespace deletes and compaction.
Backups and restore: backups carry each record's sidecars, attachments and graph edges; a restore with overwrite is never refused by quota halfway; a restore no longer re-enables revoked API keys.
Cluster: an acknowledged write could be deleted cluster-wide, the sync outbox was lost on restart, deleted data came back, and a revoked key stayed valid on a node that missed the revocation; namespace and admin configuration now replicate instead of changing one node.
Admin and API: optimize, index rebuild and compaction endpoints did nothing and reported success; index type was reported as flat everywhere; execute on explain was ignored; cache_hit_rate was a hard-coded 0.0; PUT /admin/config settings now take effect; audit body capture and the text format now work.
Recall and search: the rerank tail keeps its retrieval order (it was scored 0.0); an ANN index can no longer serve a request with another distance metric; an omitted distance_metric resolves to the namespace's metric.
Full-text: stop lists for 11 languages that had none; long Cyrillic, Greek, Arabic and Indic words, Tamil and Devanagari combining marks, and Lao, Khmer, Myanmar and Tibetan text are indexed correctly.
Embedding: gte-modernbert-base is CLS-pooled (every vector it produced was wrong) and modernbert-embed-base applies its required prefixes; stores on either model are re-embedded in the background. Model files are SHA-256 pinned.
Removed
Variables v0.11.108 read and v0.12.0 does not. On an upgraded deployment each is a startup warning (the setting has no effect); on a fresh install it refuses the boot.
DAKERA_AUTO_INDEX_SELECTION: the automatic selector only ever built HNSW, which every namespace uses.
DAKERA_RANKER, DAKERA_RANKER_INPUT, DAKERA_RANKER_MODEL: the opt-in GBDT ranker (non-default build) is removed; the default linear ranker is the only one.
DAKERA_TOKEN_BUDGET: the CPU embedder runs one text per worker; DAKERA_MAX_SEQ_LENGTH bounds a text.
DAKERA_VOCAB_BUNDLE_REPO: build-time only.
Cluster coordinator fieldsauto_failover and min_quorum: nothing consumed them.
Names that now warn instead of being ignored silently: DAKERA_L2_CACHE_PATH (set DAKERA_DISK_CACHE_DIR), DAKERA_CACHE_REDIS_URL (DAKERA_REDIS_URL), DAKERA_S3_ACCESS_KEY / DAKERA_S3_SECRET_KEY (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY), DAKERA_LOG_LEVEL (RUST_LOG), DAKERA_STORAGE_BACKEND (DAKERA_STORAGE), DAKERA_INSTANCE_ID (DAKERA_CLUSTER_NODE_ID), and DAKERA_DEV_MODE, DAKERA_INFERENCE_ENABLED, DAKERA_DECAY_ENABLED (never read).
Upgrade and rollback
Upgrading to v0.12: the checklist, every behavior change and the cluster procedure.
Rolling back to v0.11: stop v0.12.0, run dakera downgrade once, start v0.11.108. Not possible for data on bge-m3, colbert-small or the visual lane.
Large-corpus recall — The vector index no longer caps at 50,000 elements per namespace by default. The previous default silently evicted the lowest-importance vectors once a namespace grew past 50k — the root cause of a recall drop on large single-namespace corpora. Recall on million-scale corpora now recovers to a healthy curve. The cap stays configurable via DAKERA_HNSW_MAX_ELEMENTS for memory-bounded deployments, and any eviction is now surfaced in logs and metrics instead of happening silently. Query performance — Small and mid-size corpora take an exact-search fast path (threshold configurable via DAKERA_HYBRID_MIN_VECTORS, default 100k), cutting query latency where the hybrid pre-filter does not yet pay off; warm-cache queries also skip a redundant full scan. Recall is unaffected. Correctness — Clearing the full-text index now releases all associated metadata (fixes an unbounded-memory retention and a stale-filter match on re-indexed documents); hybrid and scalar-rerank searches now always return the full requested result set at large top_k.
v0.11.107
Sep 2026
Recall quality — Temporal precision re-ranking improves accuracy on time-sensitive queries; session-cohesion scoring delivers higher precision on single-session recall. Both improvements are applied automatically — no configuration change required. API — GET /v1/memory batch responses now include a truncated: bool field, providing an explicit signal when results were capped at the configured limit (previously silent). All SDKs updated to expose this field. Reliability — Fixed a storage eviction stall that could delay memory expiry under sustained load, corrected an index eviction inconsistency, and resolved a memory leak in high-throughput multi-agent deployments. All fixes are transparent; no configuration changes required. Dependencies — Internal storage layer and runtime dependencies updated; no API or behavior change.
v0.11.106
2026-08-06
Multi-hop recall — Questions that span several memories now gather more supporting evidence (wider temporal and neighborhood windows), improving answers to multi-step and time-based questions. Applied only to multi-hop queries, so simple lookups are unaffected. Anonymous usage telemetry — Aggregate, fully anonymous deployment signals to guide roadmap priorities. Opt out any time with DAKERA_TELEMETRY=off. GPU runtime refresh — Updated CUDA execution provider for the current ONNX Runtime.
v0.11.104
2026-07-31
Complete answers for list & count questions — Retrieval now aggregates evidence across many memories, so "list all…" and "how many…" queries return the full set instead of a partial one. Deeper rank recovery — Surfaces relevant memories that previously fell just outside the top results. Sharper top results — Reranking tuned to favor more specific, on-point matches.
v0.11.103
2026-07-29
Precision reranking — Promotes relevant memories from mid-rank into the top results, closing recall gaps on hard queries. Temporal-aware reranking — Better answers to time-based questions. Multi-evidence recall for list queries — Aggregates across evidence sets for higher recall on aggregation questions. Security — POST /ops/shutdown now requires admin scope. Anonymous install telemetry introduced (opt out: DAKERA_TELEMETRY=off).
v0.11.95
Jun 2026
Multilingual reranker upgrade — Cross-encoder reranker moved to bge-reranker-v2-m3 (INT8), adding multilingual support and higher ranking precision on multi-hop and temporal queries. Entity-linked scoring boost — Optional additive boost for entity-matched candidates (off by default). Regression guards protect English stemming quality in CI.
v0.11.94
Jun 2026
Longer-context embedding model — Opt in to gte-modernbert-base (768d, 8K-token window) with DAKERA_MODEL=gte-modernbert-base. Adjustable embedding size — Truncate to 256/512d for lower memory and faster search via DAKERA_MRL_DIMENSION. Runtime fusion switch — A/B RRF vs. MinMax without a redeploy (DAKERA_FUSION_STRATEGY=rrf). Deploy time cut from 12 min to under 5 min.
v0.11.93
Jun 2026
Query decomposition — Splits complex questions into sub-queries and fuses the results, improving multi-step recall. Opt in with DAKERA_QUERY_DECOMP=1. Security — quinn-proto 0.11.14 → 0.11.15 (RUSTSEC-2026-0185, CVSS 7.5).
v0.11.92
Jun 2026
Entity extraction fix — POST /v1/extract now defaults entity_types to [person, organization, location] when none are supplied, fixing cases where the playground returned zero entities. Graceful rule-based fallback avoids cold-start errors.
v0.11.91
Jun 2026
SDK-canonical admin routes — Admin endpoints are now served at /v1/admin/* alongside the legacy /admin/*, fixing 404s from client admin calls. Tunable recall scoring — Vector, importance, and recency weights are now runtime-configurable (DAKERA_SCORE_W_VEC, DAKERA_SCORE_W_IMP, DAKERA_SCORE_W_REC, DAKERA_SCORE_RECENCY_TAU_HOURS); defaults unchanged.
v0.11.90
Jun 2026
List-aware ingest on by default — Sentence decomposition and supersession demotion are now enabled out of the box: better recall of buried list items and fewer stale, superseded results. Opt out with DAKERA_BATCH_SENTENCE_DECOMP=0 or DAKERA_SUPERSEDE_DEMOTE=0.
v0.11.89
Jun 2026
Buried list-item recall — Sentence decomposition on batch ingest recovers gold answers hidden inside long lists. Supersession demotion hardened so coherent same-session messages are no longer wrongly demoted.
v0.11.88
Jun 2026
Opt-in sentence decomposition — Available on the batch-ingest path (inert by default); enable with DAKERA_CE31_DECOMPOSE=1.
v0.11.87
Jun 2026
Fix — DAKERA_CROSS_SESSION_FETCH_MULT is now honored in the session-scoped recall path (previously ignored for session queries), with no change to default behavior.
New tuning knobs (inert by default) — DAKERA_HYBRID_FETCH_MULT (hybrid + rerank coarse pool depth) and DAKERA_CROSS_SESSION_FETCH_MULT (cross-session pool depth). Recall is byte-identical when unset.
v0.11.84
Jun 2026
Better temporal recall — Entity-filtered vector pass improves answers to time-based questions. Fix — Cross-encoder reranker queue no longer drops results under concurrent load. All static-tier memories are now upgraded to full ONNX embeddings.
v0.11.83
Jun 2026
Docker image variants — :cpu (INT8, CPU-only) and :gpu/:cuda (FP32 with CUDA base image). Deterministic index builds — DAKERA_HNSW_SEED now takes effect across restarts. Faster writes — Roughly 9× storage write throughput; removed per-batch overhead that grew with store size.
v0.11.82
Jun 2026
Static write tier in production — DAKERA_TIERED=1 delivers ~9.7× ingest throughput. New endpoint — POST /admin/reembed/drain triggers a synchronous quality upgrade without waiting for background cycles. Entity extraction restored; ONNX cold-boot now has a SHA-256 integrity check with automatic re-fetch on mismatch.
v0.11.81
Jun 2026
Out-of-memory hardening (GPU) — Bounded inference pool, serialized CUDA forward passes, and deeper OOM retry eliminate allocator fragmentation under concurrent ingest.
v0.11.80
May 2026
SIMD-accelerated vector search — 3–8× distance throughput on x86_64 and ARM. GPU stability — Serialized CUDA passes eliminate allocation failures under parallel ingest. Temporal recall improvements.
v0.11.79
May 2026
GPU stability — Global inference serialization across backends prevents VRAM fragmentation under concurrent ingest.
v0.11.78
May 2026
Faster first request — The engine pre-warms at startup, eliminating a 7–10 min first-request stall. Faster re-embedding — One index rebuild per cycle instead of per-item. GPU-free static ingest for batch writes.
v0.11.77
May 2026
Hybrid search is now the default — The tiered static→transformer pipeline is fully wired, and docker-compose.yml ships hybrid + tiered defaults out of the box.
v0.11.76
May 2026
Fix — Restored Recall@10 to ~100% in hybrid mode (binary HNSW overselect formula) and corrected the search-mode fallback for unknown values.
v0.11.75
May 2026
Pluggable inference backends — ONNX, Candle, GGUF, and Static backends behind one trait. Model2Vec static backend (~500× ingest), tiered engine, binary HNSW, and ModernBERT 768d embeddings. Batch write added to all four SDKs (Python, JS, Rust, Go).
v0.11.74
May 2026
Entity extraction redesign — Consistent lowercase entity tags, entity_types honored by every extractor, entity dedup, accurate byte-offset spans, and a guard for very long inputs.
v0.11.73
May 2026
Event-date awareness — Dates mentioned in content are extracted at store time (_dakera_content_date) and used for temporal proximity scoring. Knowledge-graph entity edges expand entity-linked recall.
v0.11.72
May 2026
Stronger temporal reranking and a span-detection fix for contractions and multi-token entity names.
v0.11.71
May 2026
GPU accuracy — FP32 model for CUDA inference. Faster session lookup — O(1) instead of a full scan. Larger default ONNX batch size for CPU deployments.
v0.11.69
May 2026
Parallel hybrid retrieval — Re-introduced with full benchmark gating after resolving an earlier tie-breaking regression.
v0.11.68
May 2026
Reverted parallel retrieval due to a tie-breaking regression under task interleaving. GPU CUDA execution provider enabled.
v0.11.67
May 2026
Overload protection — A cross-encoder concurrency gate (RERANKER_MAX_CONCURRENT=6) degrades gracefully to unranked results under saturation instead of triggering client timeout storms.
v0.11.66
May 2026
Batched cross-encoder — Mini-batching (RERANKER_ONNX_BATCH_SIZE=16) reduces memory waste and improves throughput under concurrent rerank load.
v0.11.65
May 2026
Cross-encoder session pool — Pooled sessions plus adaptive chunk splitting eliminate contention under concurrent recall and handle documents longer than the model's max sequence length.
v0.11.64
May 2026
Lower recall latency — Pipeline metrics moved off the hot path, removing per-request overhead.
v0.11.63
May 2026
Observability — Full recall-pipeline instrumentation with per-stage Prometheus histograms exposed at /metrics, at no throughput cost.
v0.11.62
May 2026
Fix — Entity extraction restored after a tensor-shape regression.
v0.11.61
May 2026
Fix — Updated the entity model path after a HuggingFace repo rename, restoring entity extraction. No HuggingFace token required.
v0.11.60
May 2026
Private model downloads — HF_TOKEN support for authenticated HuggingFace downloads, with graceful fallback to unauthenticated access for public models.
v0.11.59
May 2026
Fix — Eliminated ingest timeouts by giving each text its own ONNX call; the session pool preserves throughput.
v0.11.58
May 2026
Faster ingest — ONNX session pool plus parallel batch upserts remove the ingest throughput bottleneck.
v0.11.57
May 2026
Docker base image updated to Rust 1.95, fixing release build failures.
v0.11.56
May 2026
Full SDK parity — All four SDKs (Python, JS, Rust, Go) now cover admin (cluster, maintenance, quotas, backups), ops (diagnostics, jobs, compaction), health probes, vector bulk ops, fulltext stats, TTL, storage tiers, memory-type stats, consolidation, and namespace entity configuration.
dakera-mcp v0.10.12
Sep 2026
SDK/MCP attribution — The MCP server now sends a dakera-mcp/VERSION User-Agent on all engine API requests, enabling server-side traffic attribution without any configuration. Previous releases — v0.10.4–v0.10.11 include the reliability scoring tool (dakera_tif_evaluate), improved tool descriptions, and stability updates. See GitHub Releases for the full MCP changelog.
dk CLI v0.7.1
Sep 2026
CLI for managing and querying Dakera deployments. Available for macOS (arm64 / x86_64), Linux (x86_64), and Windows. Install via shell script, Homebrew, or package managers. See GitHub Releases for installation instructions and the full changelog.
dakera-mcp v0.10.2
May 2026
Page size increased from 20 to 100 — all profiles return results in a single page, reducing round-trips for agents with large memory stores.
dakera-mcp v0.10.0
May 2026
Profile-based tool tiering — 14 core tools by default, with power/admin/all profiles for expanded access. Meta-discovery tools (discover_tools, load_tools) and ~30K token savings vs. loading every tool.
v0.11.55
May 2026
Temporal hybrid retrieval improvements for time-scoped queries.
v0.11.54
May 2026
MCP: 14 core tools with 86+ available via profiles. Entity vector search enabled by default. Cross-encoder reranking pipeline.
v0.11.45
Apr 2026
ML query-routing classifier and temporal inference enabled by default.
v0.11.27
Apr 2026
High-availability cluster stability improvements and storage throttle tuning.
v0.10.2
Apr 2026
Full-stack release — server plus all four SDKs (Python, JS, Rust, Go) shipped together.
Current versions — see the version table at the top of this page; it is generated from the same release data as the release trains, so the two cannot disagree.
Release cadence & versioning
Dakera follows semantic versioning. Every breaking or behavior change is listed on this page with what to do, and new capabilities are opt-in through environment variables wherever possible, so an upgrade changes only what the release notes say it changes.
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.
Lock in founder pricing
Dakera Cloud — managed hosting, SLA, and team monitoring — is launching soon. Join now to secure early access pricing before public launch.
No spam. Unsubscribe anytime.
✓ You're on the list!We'll reach out when beta slots open.
Lock in founder pricing
Dakera Cloud — managed hosting, SLA, and team monitoring — is launching soon. Join the waitlist now to secure early access pricing before public launch.