Dakera now plugs into Strands Agents

A new open-source integration — strands-dakera — adds persistent, decay-weighted memory to Strands Agents, with no change to your model or provider code.

Dakera now plugs into Strands Agents

Agents that forget everything between sessions aren't agents — they're stateless functions with a chat UI. A new open-source integration wires Strands Agents into a self-hosted Dakera memory server, so recall persists across sessions and is ranked by importance × recency × semantic relevance — not just vector distance.


The problem with a raw context window

Strands gives you a clean, model-driven agent loop — but the model still walks into every session with an empty context window. It knows nothing about the user it helped an hour ago, nothing about the decision it made last week, nothing that isn't in the current prompt. The workarounds are all leaky. Replaying the entire transcript into the prompt gets expensive and noisy fast, and it hits a ceiling the moment the history outgrows the context window. A fixed-TTL cache is worse: it hoards stale facts until they expire on a blind timer, then drops them whether or not they still mattered. Neither approach knows which memories are worth surfacing for the turn in front of it.

That's the gap strands-dakera closes. Instead of re-stuffing the whole transcript or expiring context on a clock, it connects the Strands loop to a self-hosted Dakera memory server that scores every memory by importance × recency × semantic relevance and surfaces only the handful that matter right now — across turns, sessions and separate processes.

Two ways to wire it in — strands-dakera

strands-dakera v0.2.0 (Apache-2.0, Python ≥ 3.10, on PyPI) is deliberately small and ships two integration points so you pick the level of control you want. Both talk to the same self-hosted Dakera server through a shared DakeraServiceClient, and both scope memory to an agent_id namespace — so you can mix them freely without migrating data. A single from strands_dakera import … gives you dakera_memory, TOOL_SPEC, DakeraServiceClient, DakeraMemoryStore and DakeraMemoryStoreConfig.

Integration pointHow it hooks inWho drives memory
dakera_memoryA native Strands tool on Agent(tools=[…])The model (deliberate, auditable)
DakeraMemoryStoreA MemoryStore plugged into MemoryManagerThe framework (transparent)

1. The dakera_memory tool — explicit control

Add the tool to your agent and the model calls memory operations itself. A single action parameter routes to five operations, and the tool returns a Strands ToolResult with status="success" and JSON content, or status="error" with a message:

ActionRequiredWhat it does
storeagent_id, contentSave a fact — importance (0–1), memory_type, metadata optional
retrieveagent_id, queryDecay-weighted semantic recall (top_k, default 5)
getagent_id, memory_idFetch a specific memory by ID
updateagent_id, memory_idEdit content, type or metadata of an existing memory
deleteagent_id, memory_idDelete a memory by ID
from strands import Agent
from strands_dakera import dakera_memory

agent = Agent(tools=[dakera_memory])

# Store a fact with an importance weight and a type
agent.tool.dakera_memory(
    action="store",
    agent_id="alex",
    content="Alex prefers dark-mode dashboards and async standups.",
    importance=0.8,
    memory_type="semantic",
    metadata={"category": "preferences"},
)

# Decay-weighted semantic recall
agent.tool.dakera_memory(
    action="retrieve",
    agent_id="alex",
    query="how does alex like to work?",
    top_k=5,
)

Mutating actions (store, update, delete) prompt for confirmation and show a content preview before executing, unless you set BYPASS_TOOL_CONSENT=true. Read actions (retrieve, get) never ask. That gate is a safety default that matters when the model, not you, is driving the writes — an over-eager agent can't silently rewrite or drop memories until you deliberately turn confirmation off for headless or CI runs.

2. DakeraMemoryStore — automatic recall

Plug the store into the Strands MemoryManager (Strands ≥ 1.45.0) and memory becomes invisible: the manager searches it to recall context — injected into the prompt automatically — and, when writable=True (the default), writes new memories back. The class conforms to the Strands MemoryStore protocol, implementing search() and add(). With extraction=True it hands off to the manager's ModelExtractor, which distils durable facts from the conversation before they're stored instead of dumping raw turns.

from strands import Agent
from strands.memory import MemoryManager
from strands_dakera import DakeraMemoryStore

store = DakeraMemoryStore(agent_id="alex", writable=True, extraction=True)
agent = Agent(memory_manager=MemoryManager(stores=[store]))

agent("Remember that I prefer dark-mode dashboards.")
agent("How do I like my dashboards?")  # recalls the stored preference

The store takes a required, positional agent_id plus keyword-only options. Set writable=False for read-only recall, cap results with max_search_results (falls back to 5 when unset), or pin a default importance and memory_type for everything the store writes. Point it at a server with base_url/api_key, or inject a pre-built client to share one connection.

OptionDefaultWhat it does
agent_idNamespace that owns the memories (required, positional)
writableTrueWhether the agent loop writes memories back via add()
extractionNoneFact-extraction config handed to the manager's ModelExtractor
max_search_resultsNoneCap on memories per recall; falls back to 5
importanceNoneDefault importance (0.0–1.0) applied to writes
memory_type"episodic"episodic · semantic · procedural · working
base_url / api_key$DAKERA_BASE_URL / $DAKERA_API_KEYExplicit connection config
# Read-only recall — surface memories, never write back
recall_only = DakeraMemoryStore(agent_id="alex", writable=False, max_search_results=8)

# Write with a fixed importance and a procedural type
proc = DakeraMemoryStore(agent_id="alex", importance=0.6, memory_type="procedural")

There's also a DakeraMemoryStoreConfig dataclass — extending the Strands MemoryStoreConfig — carrying the same Dakera-specific fields for programmatic configuration. Read the Strands integration guide → for the full options table and worked examples.

Self-hosted, no cloud key. The integration runs against a local Dakera server — git clone dakera-deploy && docker compose up -d brings up the server plus MinIO object storage on port 3000. Your memory data never leaves your infrastructure.

How recall and extraction flow

On each turn the MemoryManager calls search(query, options) on the store, which performs decay-weighted, access-aware recall favouring important, recently accessed memories. Results come back as MemoryEntry objects — each carrying the content plus a metadata dict with id, score, importance, memory_type, created_at and any custom fields — and the manager threads them into the prompt.

Write-back is where the split of responsibilities matters. The store implements add(content, metadata) — not add_messages() — so extraction stays the manager's job while the store handles persistence with at-least-once semantics and server-side deduplication. When extraction is enabled, the ModelExtractor distils durable facts from the conversation before anything is written, so you persist "Alex ships on Fridays," not a verbatim dump of the last ten turns.

Importance-typed, decay-weighted recall

Every memory carries an importance (0.0–1.0) and one of four types. Typing memories keeps recall coherent — a durable preference and a one-off event don't compete as if they were the same class of fact:

TypeWhat it holdsExample
episodicSpecific events, tied to a moment"Alex asked for a refund on July 30."
semanticDurable facts and preferences"Alex prefers dark-mode dashboards."
proceduralHow-to knowledge and repeatable steps"Deploy runs on Wednesdays via the release script."
workingShort-lived context for the current task"Currently debugging the checkout flow."

On recall, Dakera ranks by importance × recency × semantic relevance, so the most contextually useful memories surface first and old context stops competing with fresh, relevant facts. This is not a toy heuristic. It's the same recall engine that scores 88.2% Recall@20 on the 1,540-question LoCoMo long-conversation benchmark — the measure of how reliably the right memory resurfaces after hundreds of intervening turns. In a Strands agent that translates directly into fewer "wait, who are you again?" moments and less prompt bloat spent re-explaining context the agent should already hold.

Both patterns, one server — a worked example

The two integration points aren't mutually exclusive. Both talk to the same Dakera server and the same agent_id namespace, so you can lean on the store for effortless continuity and reach for the tool when the model should curate memory explicitly — no data migration, no second connection.

import os
from strands import Agent
from strands.memory import MemoryManager
from strands_dakera import dakera_memory, DakeraMemoryStore

os.environ["DAKERA_BASE_URL"] = "http://localhost:3000"
os.environ["BYPASS_TOOL_CONSENT"] = "true"  # headless

store = DakeraMemoryStore(agent_id="alex", writable=True, extraction=True)
agent = Agent(
    tools=[dakera_memory],
    memory_manager=MemoryManager(stores=[store]),
)

# Session 1 — the store quietly captures the preference
agent("I'm Alex. I like concise answers and I ship on Fridays.")

# Later session, new process — recall persists
agent("What do you know about how I work?")

# The model can also curate memory explicitly
agent.tool.dakera_memory(
    action="store",
    agent_id="alex",
    content="Alex's release day moved from Friday to Wednesday.",
    importance=0.9,
    memory_type="semantic",
)

Need several stores to share one connection? Build a DakeraServiceClient once and inject it with client=. Both patterns use that client under the hood — its store_memory, get_memory, search_memories, update_memory and delete_memory calls are exactly where tool calls and store writes land, so they never diverge.

Which pattern should you use?

Reach for the tool when you want the model to decide, out loud, what's worth remembering — agentic workflows where explicit, auditable memory calls in the trace improve traceability and you want fine-grained control over importance and type per write. Reach for the store when you want continuity to just happen with zero prompt or logic changes, letting the framework distil and store facts for you.

Because both share the agent_id namespace, you can start with the store and add the tool later without migrating anything — or run a fleet of agents on one server, each scoping its own memory by id so a support bot and a sales bot never cross wires.

Strands joins the existing lineup — LangChain, LlamaIndex, CrewAI, AutoGen, LangChain.js, the Vercel AI SDK, PraisonAI, Agent Squad, Dify, and the MCP server for Claude, Cursor, and Windsurf. See them all on the integrations page →

Get started. pip install strands-dakera (Python ≥ 3.10; pulls in strands-agents ≥ 1.45.0 and the dakera SDK), bring up the server with docker compose up -d, and add either the tool or the store to your agent. Full options tables and worked examples live in the Strands integration guide →, or grab the source on GitHub. It's self-hosted and free — your memory data never leaves your infrastructure.

Build with Dakera

Give your AI agents persistent memory — self-hosted, production-ready, zero dependencies.

Stay sharp on agent memory
Benchmark releases, engineering deep-dives, and product updates. Once a week max, no fluff.
✓ Subscribed. Thanks!