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

Rust SDK

dakera-client v0.12.3 · async (Tokio)

dakera-client is the official Rust client for the Dakera REST API, with an optional gRPC transport. This page shows how to install it, connect to a server, and call the memory, session, search, knowledge-graph and admin APIs from async Rust; it is written for Rust developers building agents or services on Dakera.

crates.io · docs.rs · GitHub · Changelog

Current releasedakera-client 0.12.3released 2026-10-22 · release train 0.12.3

  • import_document(), import_attachment_document(), wait_for_document_job(), list_documents(), get_document(), delete_document().
  • NeighborhoodMode and with_include_summaries() on recall, context_memories on the response, matched_text on results.
  • The API key is redacted from Debug output.

cargo add dakera-client@0.12.3 What changed → All current versions →

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

The latest release is 0.12.3 (edition 2021, stable Rust). The crate declares no minimum supported Rust version; build with a current stable toolchain.

Using it with a v0.12.0 server — dakera-client 0.12.1 is the release aligned with Dakera v0.12.0 (it also works against v0.11.108). Three things to know:
  • While a v0.12.0 server starts (models loading), GET /health answers 503. client.health() no longer reports that as healthy; gate traffic on client.ready() (GET /health/ready) or client.wait_until_ready(timeout).
  • With authentication on (the default), v0.12.0 requires an API key on gRPC calls. Set it with GrpcClientConfig::with_api_key (or DAKERA_API_KEY); the client sends it as x-api-key.
  • MemoryPolicy::default() still carries consolidated_count: Some(0), a read-only field that v0.12.0 refuses to change. Read the current policy, edit it and write it back (see Memory policy).
See Upgrading to v0.12.

Client setup

use dakera_client::DakeraClient;

// Keep the URL and key out of source code, for example:
// export DAKERA_URL=http://<YOUR_SERVER_IP>:3000
// export DAKERA_API_KEY=your-api-key
let client = DakeraClient::builder(
    std::env::var("DAKERA_URL").unwrap_or_else(|_| "http://localhost:3000".into()),
)
.api_key(std::env::var("DAKERA_API_KEY").unwrap_or_default())
.build()?;

// Wait for readiness before the first request
let ready = client.ready().await?;
assert!(ready.ready);

DakeraClient::new(url) builds a client without a key, for servers with authentication off. Every method is async and returns dakera_client::Result<T>.

Memory operations

use dakera_client::{BatchForgetRequest, BatchMemoryFilter, BatchRecallRequest,
    ForgetRequest, RecallRequest, StoreMemoryRequest};

// Store
let stored = client.store_memory(
    StoreMemoryRequest::new("my-agent", "User is learning Rust")
        .with_importance(0.8)
        .with_tags(vec!["learning".into()]),
).await?;
println!("stored {}", stored.memory_id);

// Recall (semantic search)
let response = client.recall(
    RecallRequest::new("my-agent", "which programming language is the user learning?").with_top_k(10),
).await?;
for m in &response.memories {
    println!("{} (score: {:.2})", m.content, m.score);
}

// Get, then forget by ID
let memory = client.get_memory("my-agent", &stored.memory_id).await?;
client.forget(ForgetRequest::by_ids("my-agent", vec![memory.id.clone()])).await?;

// Filter-based recall and delete (no embedding)
let tagged = client.batch_recall(
    BatchRecallRequest::new("my-agent")
        .with_filter(BatchMemoryFilter::default().with_tags(vec!["learning".into()]))
        .with_limit(50),
).await?;
let deleted = client.batch_forget(BatchForgetRequest::new(
    "my-agent",
    BatchMemoryFilter::default().with_tags(vec!["obsolete".into()]),
)).await?;
println!("{} listed, {} deleted", tagged.memories.len(), deleted.deleted_count);

Each recall result's score is the server's ranking score (smart_score). Scores are not comparable with v0.11 scores; re-check any absolute cut-off after upgrading.

Sessions

let session = client.start_session("my-agent").await?;

client.store_memory(
    StoreMemoryRequest::new("my-agent", "Found 2 issues in the review")
        .with_session(session.id.clone()),
).await?;

let ended = client.end_session(&session.id, Some("Review complete".to_string())).await?;
println!("{} memories in the session", ended.memory_count);

let sessions = client.list_sessions("my-agent").await?;

start_session_with_metadata(agent_id, json) attaches metadata to the session.

ChatMemorySession

ChatMemorySession wraps a session for LLM chat loops: it opens a session on create, stores each turn with its role as a tag, and ends the session on close().

use std::sync::Arc;
use dakera_client::{ChatMemorySession, DakeraClient};

let client = Arc::new(DakeraClient::builder("http://localhost:3000")
    .api_key("my-key")
    .build()?);

let session = ChatMemorySession::create(Arc::clone(&client), "chat-agent").await?;
session.store("user", "What is the capital of France?").await?;
session.store("assistant", "The capital of France is Paris.").await?;
let memories = session.recall("capital cities").await?;
session.close().await?;

These methods work on a namespace of documents that the server embeds for you.

use dakera_client::{FullTextSearchRequest, HybridSearchRequest, QueryTextRequest,
    TextDocument, UpsertTextRequest};

// Upsert documents (embedded server-side)
client.upsert_text("docs", UpsertTextRequest::new(vec![
    TextDocument::new("doc-001", "Quarterly revenue report Q1 2026"),
])).await?;

// Semantic query
let results = client.query_text("docs", QueryTextRequest::new("revenue trends", 5)).await?;

// BM25 full-text search
let hits = client.fulltext_search("docs", FullTextSearchRequest::new("quarterly report", 5)).await?;

// Hybrid search: pass a query vector, or use text_only for BM25 alone
let hybrid = client.hybrid_search("docs", HybridSearchRequest::text_only("revenue", 10)).await?;

Raw vectors use upsert, query, delete, bulk_update_vectors, bulk_delete_vectors and count_vectors; index statistics use fulltext_stats and get_index_stats.

Namespaces

use dakera_client::CreateNamespaceRequest;

client.create_namespace("production", CreateNamespaceRequest::new()
    .with_dimensions(1024)
    .with_index_type("hnsw")).await?;

let names = client.list_namespaces().await?;
client.delete_namespace("old-namespace").await?;

Memory policy

// Read, edit and write back the namespace's lifecycle policy
let mut policy = client.get_memory_policy("production").await?;
policy.episodic_ttl_seconds = Some(604_800);
policy.working_ttl_seconds = Some(3_600);
client.set_memory_policy("production", policy).await?;

The write replaces the stored policy. Starting from get_memory_policy keeps the fields you do not change, including the read-only consolidated_count.

Knowledge graph

use dakera_client::{DeduplicateRequest, KnowledgeGraphRequest};

// Graph around a seed memory
let graph = client.knowledge_graph(KnowledgeGraphRequest {
    agent_id: "my-agent".into(),
    memory_id: Some("mem-abc".into()),
    depth: Some(2),
    min_similarity: None,
}).await?;

// Find near-duplicates without deleting (dry run)
let dupes = client.deduplicate(DeduplicateRequest {
    agent_id: "my-agent".into(),
    threshold: Some(0.93),
    memory_type: None,
    dry_run: true,
}).await?;
println!("{} duplicates found", dupes.duplicates_found);

Also available: full_knowledge_graph, summarize, memory_path, knowledge_query, knowledge_export and cross_agent_network (the last needs an admin key with no namespace restriction on v0.12.0).

Entities, feedback and import/export

use dakera_client::FeedbackSignal;

// Extract entities from text
let entities = client.extract_entities("Alice met Bob at Google HQ", None).await?;

// Feedback on a recalled memory
client.feedback_memory("mem-abc", "my-agent", FeedbackSignal::Upvote).await?;
client.patch_memory_importance("mem-abc", "my-agent", 0.9).await?;
let summary = client.get_agent_feedback_summary("my-agent").await?;

// Export an agent's memories as JSONL
let export = client.export_memories("jsonl", Some("my-agent"), None, None).await?;

import_memories(data, format, agent_id, namespace) imports Mem0, Zep, JSONL or CSV data.

Event streaming

// Server-sent memory events (needs an admin key with no namespace restriction)
let mut events = client.stream_memory_events().await?;
while let Some(event) = events.recv().await {
    let event = event?;
    println!("{} {}", event.event_type, event.agent_id);
}

Admin and operations

Admin methods need an admin key with no namespace restriction on v0.12.0; key management and backup restore, upload and download need super_admin.

use dakera_client::{AutoPilotConfigRequest, AutoPilotTriggerAction, CompactionRequest,
    DecayConfigUpdateRequest};

let cluster = client.cluster_status().await?;
let backups = client.list_backups().await?;
let diag = client.ops_diagnostics().await?;
let jobs = client.ops_list_jobs().await?;
client.ops_compact(CompactionRequest { namespace: Some("production".into()), force: false }).await?;

// AutoPilot (background dedup and consolidation)
let status = client.autopilot_status().await?;
client.autopilot_update_config(AutoPilotConfigRequest {
    enabled: Some(true),
    dedup_threshold: Some(0.93),
    ..Default::default()
}).await?;
client.autopilot_trigger(AutoPilotTriggerAction::Dedup).await?;

// Decay engine
let decay = client.decay_config().await?;
client.decay_update_config(DecayConfigUpdateRequest {
    half_life_hours: Some(168.0),
    ..Default::default()
}).await?;

Also available: create_backup, slow_queries, ttl_stats, storage_tier_overview, memory_type_stats, admin_enable_maintenance / admin_disable_maintenance, consolidate_agent, get_consolidation_log and the API key methods (create_key, rotate_key, …). See docs.rs for every signature.

gRPC transport

# Cargo.toml
dakera-client = { version = "0.12", features = ["grpc"] }
use dakera_client::grpc::{GrpcClient, GrpcClientConfig};

let grpc = GrpcClient::connect(GrpcClientConfig::new("http://localhost:50051")).await?;
let health = grpc.health().await?;

The gRPC client covers vector operations (upsert, query, delete_vectors, namespaces, health) with connection pooling (GrpcConnectionPool). Against a v0.12.0 server with authentication on, configure the key with GrpcClientConfig::with_api_key.

Timeouts and retries

use std::time::Duration;
use dakera_client::{DakeraClient, RetryConfig};

let client = DakeraClient::builder("http://localhost:3000")
    .api_key("your-key")
    .timeout(Duration::from_secs(30))
    .retry_config(RetryConfig {
        max_retries: 3,
        base_delay: Duration::from_millis(500),
        max_delay: Duration::from_secs(10),
        jitter: true,
    })
    .build()?;

Error handling

use dakera_client::ClientError;

match client.get_memory("my-agent", "mem-abc").await {
    Ok(memory) => println!("{}", memory.content),
    Err(ClientError::Server { status: 404, .. }) => println!("not found"),
    Err(ClientError::RateLimitExceeded { retry_after }) => println!("retry after {retry_after:?} s"),
    Err(ClientError::Authorization { status, message, .. }) => eprintln!("{status}: {message}"),
    Err(e) => eprintln!("error: {e}"),
}

ClientError variants: Http, Json, Server (status, message, typed code), Authorization, Config, NamespaceNotFound, VectorNotFound, InvalidUrl, Connection, Timeout, RateLimitExceeded, and Grpc with the grpc feature. 401 is reported as Server and 403 as Authorization. Connection errors, timeouts, rate limits and 5xx / 408 responses count as retryable.

See also: REST API reference · Quickstart · Why Rust for AI memory · Go SDK · Python SDK

Rust agent with native memory

cargo add dakera-client adds an async Rust client built on Tokio, with typed requests and responses and a typed error enum. A good fit for latency-sensitive agent loops written in Rust.

Get Started → Why Rust for Memory →
Stay sharp on agent memory
Benchmark results, SDK releases, and production patterns. Under 500 words per issue.
✓ You're in. First issue lands soon — watch for Dakera in your inbox.