dakera-go
Official Go client SDK for the Dakera self-hosted agent memory server, providing typed interfaces for memory store/recall, session management, namespace operations, and decay configuration
About dakera-go
Why Dakera?
| Dakera | Others | |
|---|---|---|
| LoCoMo Recall@20 | 88.2% (1,536 Q, LLM-judged retrieval recall) | not directly comparable |
| Deployment | Single binary, Docker one-liner | External vector DB + embedding service required |
| Embeddings | Built-in — no OpenAI key needed | Requires external embedding API |
| Search modes | Vector · BM25 · Hybrid · Knowledge Graph | Usually one or two |
| Dependencies | stdlib net/http only | Often pulls in gRPC or third-party HTTP clients |
→ Try the playground · Full benchmark results · dakera.ai
Run Dakera
docker run -d \
--name dakera \
-p 3000:3000 \
-e DAKERA_ROOT_API_KEY=dk-mykey \
ghcr.io/dakera-ai/dakera:latest
curl http://localhost:3000/health # → {"status":"ok"}
For persistent storage with Docker Compose:
curl -sSfL https://raw.githubusercontent.com/Dakera-AI/dakera-deploy/main/docker/docker-compose.yml \
-o docker-compose.yml
DAKERA_API_KEY=dk-mykey docker compose up -d
Full deployment guide (Docker Compose, Kubernetes, Helm): dakera-deploy
Install
go get github.com/dakera-ai/dakera-go@latest
Requires Go 1.21+. Uses only the standard library — no external runtime dependencies.
Quick Start
client := dakera.NewClientWithOptions(dakera.ClientOptions{BaseURL: "http://localhost:3000", APIKey: "dk-mykey"})
imp := float32(0.9)
client.StoreMemory(context.Background(), "my-agent", dakera.StoreMemoryRequest{Content: "User prefers brevity", Importance: &imp})
Full example — store, recall, upsert, and hybrid search:
package main
import (
"context"
"fmt"
dakera "github.com/dakera-ai/dakera-go"
)
func main() {
client := dakera.NewClientWithOptions(dakera.ClientOptions{
BaseURL: "http://localhost:3000",
APIKey: "dk-mykey",
})
ctx := context.Background()
// Store an agent memory
imp := float32(0.9)
mem, _ := client.StoreMemory(ctx, "my-agent", dakera.StoreMemoryRequest{
Content: "User prefers concise responses with code examples",
Importance: &imp,
})
fmt.Println("Stored:", mem.Memory.ID)
// Recall memories (semantic search)
resp, _ := client.Recall(ctx, "my-agent", dakera.RecallRequest{
Query: "what does the user prefer?",
TopK: 5,
})
for _, m := range resp.Memories {
fmt.Printf("[%.2f] %s\n", m.Score, m.Content)
}
// Upsert vectors
client.Upsert(ctx, "my-namespace", []dakera.VectorInput{
{ID: "vec1", Values: []float32{0.1, 0.2, 0.3}},
})
// Hybrid search (vector + BM25)
results, _ := client.HybridSearch(ctx, "my-namespace", nil, "completed task", &dakera.HybridSearchOptions{
TopK: 5,
VectorWeight: 0.7,
})
for _, r := range results {
fmt.Println(r.ID, r.Score)
}
}
Context-based cancellation
All methods accept a context.Context — use it for timeouts, deadlines, or cancellation:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err := client.Recall(ctx, "my-agent", dakera.RecallRequest{Query: "preferences", TopK: 3})
Text auto-embedding
Send raw text without pre-computing embeddings — Dakera embeds server-side:
client.UpsertText(ctx, "my-namespace", []dakera.TextInput{
{ID: "doc1", Text: "Agent completed onboarding flow successfully"},
})
Features
- Agent Memory — store, recall, search, and forget memories with importance scoring
- Sessions — group memories by conversation with auto-consolidation on session end
- Knowledge Graph — traverse memory relationships, find paths, export graphs
- Vector Search — ANN queries with metadata filters and batch operations
- Full-Text Search — BM25 ranking with stemming and stop-word filtering
- Hybrid Search — combine vector similarity with keyword matching
- Text Auto-Embedding — server-side embedding generation (no local model needed)
- Namespaces — isolated vector stores per project, tenant, or use case
- Feedback Loop — upvote/downvote/flag memories to improve recall quality
- T-I-F Reliability —
TifScorestruct andEvaluateTif()for Truth-Indeterminacy-Falsity scoring of memory reliability - Entity Extraction — GLiNER NER for automatic entity detection
- SSE Streaming — Server-sent event subscriptions for real-time memory updates
- Typed Filters —
Eq(),Gt(),Contains(),ArrayContains()and more - Context-Based — all methods accept
context.Contextfor cancellation and timeouts - Retry & Rate Limiting — built-in exponential backoff and rate-limit header tracking
- Zero Dependencies — standard library
net/httpclient, no external runtime deps
Connect to Dakera
// Self-hosted
client := dakera.NewClientWithOptions(dakera.ClientOptions{
BaseURL: "http://your-server:3000",
APIKey: "your-key",
})
// Cloud (early access)
client := dakera.NewClientWithOptions(dakera.ClientOptions{
BaseURL: "http://<your-server-ip>:3000",
APIKey: "your-key",
})
// With custom retry config
client := dakera.NewClientWithOptions(dakera.ClientOptions{
BaseURL: "http://localhost:3000",
APIKey: "your-key",
RetryBackoff: &dakera.RetryConfig{MaxRetries: 5, BaseDelay: 200 * time.Millisecond, MaxDelay: 30 * time.Second, Jitter: true},
})
What's new in v0.12.2
SDK v0.12.2 targets Dakera server v0.12.2 and stays compatible with v0.12.0 and v0.12.1
servers: new request fields are omitted unless you set them, new response fields are optional
(nil / empty on an older server), and the new routes answer 404 there. Check
caps.Auth, caps.Sessions (or SupportsKeyUpdate(), SupportsSessionTouch()) to see what the
connected server has.
| Feature | API |
|---|---|
| Create an agent before its first memory | CreateAgent(ctx, "mlx-dev") (Created is false for an existing agent) |
| Edit a key's name or namespaces | UpdateKey, UpdateNamespaceKey with UpdateKeyRequest{Namespaces: dakera.GrantNamespaces("team-*")} (nil = unchanged, GrantAllNamespaces() = null, GrantNamespaces() = []) |
| Rotate with a grace period | RotateKeyWithOptions(ctx, id, &dakera.RotateKeyOptions{GraceSecs: &grace}) → OldKeyID, OldKeyExpiresAt |
| Who am I | Whoami(ctx) — scope, grants, Unrestricted, GrantsVersion, InertNamespaces |
| Namespace kinds | ListNamespacesWithKinds, NamespaceInfo.Kind |
| Session idle lifecycle | StartSessionRequest.IdleTimeoutSecs, TouchSession, Session.EndedReason / LastActivityAt / IdleSince, StoreMemoryResponse.SessionState, BatchStoreMemoryResponse.EndedSessions, SetSessionIdleTimeout |
| Derived records | IncludeDerived on AgentMemoriesOptions and WakeUpOptions; AdminDerivationStatus, AdminDrainDerivations |
| Content previews | ContentPreviewChars on AgentMemoriesOptions, SessionMemoriesOptions, FullKnowledgeGraphRequest, CrossAgentNetworkRequest → ContentLen, ContentTruncated |
// A developer key that may create and use its own agents (prefix grant).
key, _ := client.CreateKey(ctx, dakera.CreateKeyRequest{
Name: "dev", Scope: dakera.KeyScopeWrite,
Namespaces: dakera.GrantNamespaces("_dakera_agent_mlx-*"),
})
_ = key // key.Key is shown once: store it in your secret manager, never in code
// A session the server never ends for inactivity.
zero := 0
sess, _ := client.StartSession(ctx, dakera.StartSessionRequest{AgentID: "mlx-dev", IdleTimeoutSecs: &zero})
// A list view: 200-character previews, full text only when needed.
preview := 200
mems, _ := client.AgentMemories(ctx, "mlx-dev", &dakera.AgentMemoriesOptions{ContentPreviewChars: &preview})
for _, m := range mems {
if m.ContentTruncated != nil && *m.ContentTruncated {
full, _ := client.GetMemory(ctx, "mlx-dev", m.ID)
_ = full
}
}
_ = sess
Behaviour changes in server v0.12.2 that clients can hit:
- Sessions end after 4 hours without activity by default (
DAKERA_SESSION_IDLE_TIMEOUT_SECS). Activity is a memory stored, batch-stored, imported or updated with the session, a session-scoped recall or search, orTouchSession. Storing into an ended session still succeeds: checkStoreMemoryResponse.SessionState/BatchStoreMemoryResponse.EndedSessionsand start a new session when it saysended. - Sessions are authorized by their agent: keys no longer need a
_dakera_sessionsgrant (it is accepted and inert), a key without grants lists no sessions, andEndSessionwith a Read key gets403. - Stricter validation (400, the field named in the message): invalid key grants (
a**b, blank entries, internal namespaces), a client-setdakera-curatedtag,_dakera_*metadata keys other than_dakera_content_date/_dakera_lang, ids of the formmem_s+ 24 hex, agent ids over 241 bytes, TTLs over 100 years. - The content limit is in bytes (UTF-8,
DAKERA_MAX_MEMORY_CONTENT_BYTES, 100000 by default) andUpdateMemoryenforces it too. - Listings exclude derived records:
AgentMemoriesandGetWakeUpContextleave CE-31 sentence sub-memories out unlessIncludeDerivedis set. - Legacy
foo*grants stay inert on keys created before v0.12.2 (GrantsVersion0,InertNamespaces) until the key's namespaces are saved again withUpdateKey.
What's new in v0.12.0
SDK v0.12.0 targets Dakera server v0.12.0 and is compatible with both v0.11.108 and
v0.12.0 servers: every new request field is omitted from the wire unless you set it, and the
new routes only exist on a v0.12 server (see the table below). Operator guide for the server
side: docs/v0.12/UPGRADE.md in the server release, and the release notes in the
Dakera changelog.
| Feature | API | Needs |
|---|---|---|
| What the server supports | client.Capabilities(ctx) — models, index kinds, rabitq, records, attachments, vision, scoring, QueryLanguages | v0.12 (404 on v0.11) |
| Readiness | HealthReady, IsReady, WaitUntilReady (a 503 is "not ready", never healthy) | any |
Retry-After | honoured on 429 and 503 (capped at RetryConfig.MaxDelay); ServerError.RetryAfter | any |
| Errors | PayloadTooLargeError (IsQuota() tells a full namespace from an oversize request), FeatureDisabledError / NotImplementedError (501), ConflictError (409); DakeraError.Details / .Resource | any |
| Attachments | UploadAttachment, ListAttachments, DownloadAttachment, DeleteAttachment, StoreMemoryRequest.AttachmentRef | DAKERA_ATTACHMENTS |
| Transcription / image index jobs | TranscribeAttachment, IndexAttachmentImage, Get*Job, WaitFor* | DAKERA_ATTACHMENTS (+ DAKERA_VISION) |
| Records | UpsertRecords, GetRecord — one vector plus named representations (dense, token_multivector, patch_multivector; f32/f16/i8) | DAKERA_RECORDS |
| Per-request language | Lang on store, batch store, update, recall, search and ExtractMemoryEntities | v0.12 |
| New values | models bge-m3, colbert-small; index kind ivfpq; search mode rabitq (server-wide, DAKERA_SEARCH_MODE) | v0.12 |
| Clearing entity types | PutNamespaceEntityConfig (PUT) and PatchNamespaceEntityConfig (merge); ConfigureNamespaceNer clears with PUT | v0.12 for PUT |
// Wait for a starting server, then check what it can do.
if _, err := client.WaitUntilReady(ctx, dakera.ReadyWaitOptions{Timeout: 2 * time.Minute}); err != nil {
log.Fatal(err)
}
caps, _ := client.Capabilities(ctx)
if caps.SupportsAttachments() {
up, _ := client.UploadAttachment(ctx, dakera.AgentMemoryNamespace("my-agent"), wavBytes, "audio/wav")
job, _ := client.TranscribeAttachment(ctx, dakera.AgentMemoryNamespace("my-agent"), up.AttachmentRef,
dakera.TranscribeRequest{AgentID: "my-agent", Lang: "en"})
_, err = client.WaitForTranscription(ctx, dakera.AgentMemoryNamespace("my-agent"), up.AttachmentRef, job.JobID,
dakera.JobWaitOptions{Timeout: 5 * time.Minute})
}
Things to know when upgrading a server:
- Health checks: v0.12 binds its port while models load.
/healthanswers503withRetry-Afteruntil then; use/health/ready(HealthReady/WaitUntilReady). - Clearing
entity_types: on a v0.12 serverPATCH /v1/namespaces/{ns}/configmerges and an empty list is omitted from JSON, so a PATCH cannot clear it. UsePutNamespaceEntityConfig(orConfigureNamespaceNerwith no entity types, which uses PUT and falls back to PATCH on a v0.11 server). - Errors are JSON everywhere; every
503carriesRetry-After; over-size bodies are413; configuration errors are501. UpsertResponse/DeleteResponsenow decode the server's realupserted_count/deleted_countfields (earlier versions read camelCase names the server never sent and so reported0).- The Go SDK does not use gRPC; gRPC clients written against v0.12 must send the API key in call
metadata (
x-api-keyorauthorization: Bearer).
Examples
See the examples/ directory:
basic/— vectors, namespaces, queries, filtersmemory/— store/recall memories, sessions, agent statsadvanced/— text embedding, full-text, hybrid search, analytics
Resources
| Documentation | Full API reference and guides |
| Go SDK docs | pkg.go.dev reference |
| Benchmark | LoCoMo evaluation results |
| dakera.ai | Website and early access |
| GitHub Org | All public repos |
| dakera-deploy | Self-hosting guide |
Other SDKs
| SDK | Package |
|---|---|
| dakera-py | dakera (PyPI) |
| dakera-js | @dakera-ai/dakera (npm) |
| dakera-rs | dakera-client (crates.io) |
| dakera-cli | CLI tool |
| dakera-mcp | MCP server for Claude/Cursor |
Frequently Asked Questions
What is dakera-go?
dakera-go is a Artificial Intelligence library for the Go programming language. Official Go client SDK for the Dakera self-hosted agent memory server, providing typed interfaces for memory store/recall, session management, namespace operations, and decay configuration
How do I install dakera-go?
Install dakera-go with the Go module system using `go get dakera-ai/dakera-go`. Check the repository for the current installation instructions.
What category does dakera-go belong to?
dakera-go is listed under Artificial Intelligence, specifically Artificial Intelligence.