Strands Agents Integration
Give Strands agents durable memory that survives across sessions. strands-dakera ships a dakera_memory tool the model can call, plus a drop-in DakeraMemoryStore for the Strands MemoryManager — recall ranked by importance × recency × semantic relevance, not just vector distance.
Overview
Strands gives you a clean, model-driven agent loop — but the model still starts every session with an empty context window. strands-dakera connects that loop to a self-hosted Dakera memory server so facts, preferences and decisions persist across turns, sessions and processes. Instead of re-stuffing the whole transcript into the prompt or expiring context on a fixed TTL, Dakera scores every memory by importance × recency × semantic relevance and surfaces the handful that actually matter for the current turn.
The package is deliberately small and offers two integration points that share one server and one agent namespace:
- The
dakera_memorytool — a native Strands tool the model invokes explicitly tostore,retrieve,get,updateanddeletememories. Best when you want the model to reason out loud about what to remember. DakeraMemoryStore— a class that conforms to the StrandsMemoryStoreprotocol and plugs intoMemoryManager. The agent recalls and writes memory automatically, with no explicit tool call and no prompt changes.
When to use which
| Use the tool when… | Use the store when… |
|---|---|
| You want explicit, auditable memory operations in the trace | You want continuity with zero prompt or logic changes |
| The model should decide what is worth remembering | Every turn should transparently recall relevant context |
| You need fine-grained control over importance and type per write | You want the framework to distil and store facts for you |
agent_id namespace, so you can start with the store for effortless continuity and add the tool later for explicit control — no data migration.Both integration points follow this loop: relevant memories are recalled and injected before the model runs, and the new exchange is written back — automatically via DakeraMemoryStore, or on the model’s command via the dakera_memory tool.
Install & Setup
Run Dakera
Dakera is a self-hosted memory server — no cloud key required. Spin it up with Docker Compose:
git clone https://github.com/dakera-ai/dakera-deploy
cd dakera-deploy && docker compose up -d
# server + MinIO object storage, listening on :3000
Install the package
pip install strands-dakera
Requirements: Python ≥ 3.10 and a running Dakera server. The package pulls in strands-agents ≥ 1.45.0 (required for the strands.memory module used by the store), the dakera ≥ 0.12.0 Python SDK, and rich ≥ 13.0.0 for consent previews.
Configure the connection
export DAKERA_BASE_URL=http://localhost:3000
export DAKERA_API_KEY=dk-your-key-here
Both patterns read these variables by default. You can also pass base_url and api_key directly to DakeraMemoryStore if you prefer explicit configuration over the environment.
from strands_dakera import … gives you dakera_memory, TOOL_SPEC, DakeraServiceClient, DakeraMemoryStore and DakeraMemoryStoreConfig. The DakeraServiceClient is the thin wrapper over the Dakera Python SDK that both patterns share.Pattern 1 — The dakera_memory tool
Add dakera_memory to your agent's tools and the model can explicitly store, retrieve, get, update and delete memories. A single action parameter routes to the five operations; the tool returns a Strands ToolResult with status="success" and JSON content, or status="error" with a message.
from strands import Agent
from strands_dakera import dakera_memory
agent = Agent(tools=[dakera_memory])
# Store a memory with an importance weight and 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,
)
Tool actions
| Action | Required fields | Optional fields | Description |
|---|---|---|---|
store | agent_id, content | importance, memory_type, metadata | Store a new memory and return its ID |
retrieve | agent_id, query | top_k (default 5) | Decay-weighted semantic search |
get | agent_id, memory_id | — | Fetch a specific memory by ID |
update | agent_id, memory_id | content, memory_type, metadata | Update content, type or metadata of an existing memory |
delete | agent_id, memory_id | — | Delete a memory by ID |
Tool parameters
| Parameter | Type | Notes |
|---|---|---|
action | str | Required. One of store · retrieve · get · update · delete |
agent_id | str | Required for every action — the namespace that owns the memories |
content | str | Memory text. Required for store; optional for update |
query | str | Natural-language query. Required for retrieve |
memory_id | str | Required for get, update, delete |
importance | float | 0.0–1.0 weight applied on store |
memory_type | str | episodic · semantic · procedural · working (default episodic) |
metadata | dict | Arbitrary structured metadata stored alongside the memory |
top_k | int | Number of results for retrieve (default 5) |
Consent on writes
The mutating actions — store, update and delete — prompt for confirmation and show a content preview before executing. Read actions (retrieve, get) never require confirmation. Set BYPASS_TOOL_CONSENT=true to skip the prompt in automated or non-interactive runs.
# Skip write confirmations (CI, servers, headless agents)
export BYPASS_TOOL_CONSENT=true
Pattern 2 — DakeraMemoryStore (automatic)
Plug DakeraMemoryStore into the Strands MemoryManager and memory becomes invisible: the manager searches the store to recall context — injected into the prompt automatically — and, when writable, writes new memories back through it. The class conforms to the Strands MemoryStore protocol, implementing search() and add().
from strands import Agent
from strands.memory import MemoryManager
from strands_dakera import DakeraMemoryStore
# Recall + write, distilling durable facts from the conversation.
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
DakeraMemoryStore options
| Parameter | Type | Default | Description |
|---|---|---|---|
agent_id | str | — | Agent namespace that owns the memories (required, positional) |
name | str | "dakera" | Store name within the MemoryManager |
description | str · None | "Persistent, decay-weighted long-term memory backed by Dakera." | Human-readable store description |
max_search_results | int · None | None | Cap on memories per recall. When unset, falls back to 5 |
writable | bool | True | Whether the agent loop writes memories back via add() |
extraction | Any | None | Fact-extraction config handed to the manager's ModelExtractor |
importance | float · None | None | Default importance (0.0–1.0) applied to writes |
memory_type | str | "episodic" | episodic · semantic · procedural · working |
base_url | str · None | $DAKERA_BASE_URL or http://localhost:3000 | Dakera server URL |
api_key | str · None | $DAKERA_API_KEY | API key for the Dakera server |
client | DakeraServiceClient · None | None | Inject a pre-built client instead of constructing one from base_url/api_key |
All keyword options after agent_id are keyword-only. The store also exports a DakeraMemoryStoreConfig dataclass (extending the Strands MemoryStoreConfig) carrying the same Dakera-specific fields — agent_id, importance, memory_type, base_url, api_key — for programmatic configuration.
How recall & 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 with content plus a metadata dict containing id, score, importance, memory_type, created_at and any custom metadata — and the manager injects them into the prompt.
When extraction is enabled, the manager's ModelExtractor distils durable facts from the conversation before they are written, rather than dumping raw turns. The store implements add(content, metadata) — not add_messages() — so extraction stays the manager's responsibility while the store handles persistence with at-least-once semantics and server-side deduplication.
# Read-only recall: surface memories but 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",
writable=True,
importance=0.6,
memory_type="procedural",
)
Worked example — a memory-backed assistant
Combine both patterns: the store gives effortless cross-session continuity, while the tool lets the model curate memory explicitly when it matters.
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",
)
Environment variables
| Variable | Default | Description |
|---|---|---|
DAKERA_BASE_URL | http://localhost:3000 | Dakera server URL (used by both patterns) |
DAKERA_API_KEY | — | API key for the Dakera server (dk-…) |
BYPASS_TOOL_CONSENT | — | Set true to skip confirmation on mutating tool actions |
retrieve and search return memories ranked by importance × recency × semantic relevance — so the most contextually useful memories surface first and stale facts stop competing with fresh ones. That's the same engine that scores 88.2% Recall@20 on the 1,540-question LoCoMo benchmark.Memory types
Both patterns accept a memory_type that tags each memory with the kind of knowledge it holds. The store defaults to episodic; the tool defaults to episodic when the model omits it. 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.
| Type | What it holds | Example |
|---|---|---|
episodic | Specific events and interactions, tied to a moment | "Alex asked for a refund on July 30." |
semantic | Durable facts and preferences that stay true over time | "Alex prefers dark-mode dashboards." |
procedural | How-to knowledge and repeatable steps | "Deploy runs on Wednesdays via the release script." |
working | Short-lived context relevant to the current task | "Currently debugging the checkout flow." |
Advanced — sharing one client
Both patterns construct a DakeraServiceClient from DAKERA_BASE_URL and DAKERA_API_KEY. For multiple stores — or to reuse a single connection across an app — build the client once and inject it with the client= parameter:
from strands_dakera import DakeraServiceClient, DakeraMemoryStore
client = DakeraServiceClient(
base_url="http://localhost:3000",
api_key="dk-your-key-here",
)
# Two stores, one connection, different write policies
prefs = DakeraMemoryStore(agent_id="alex", client=client, memory_type="semantic")
events = DakeraMemoryStore(agent_id="alex", client=client, memory_type="episodic")
The client wraps the dakera Python SDK and exposes the same operations the tool uses under the hood — store_memory, get_memory, search_memories, update_memory and delete_memory — so tool calls and store writes land in exactly the same place.
Troubleshooting
| Symptom | Likely cause & fix |
|---|---|
| Connection refused / timeout | The Dakera server isn't running or DAKERA_BASE_URL is wrong. Confirm docker compose up -d is healthy and the port is 3000. |
| Tool stalls waiting on input | A mutating action is asking for consent. In headless runs set BYPASS_TOOL_CONSENT=true. |
| Store never recalls anything | Check the agent_id matches what was written, and that memories exist for that namespace. Recall is scoped per agent_id. |
ImportError on strands.memory | The MemoryStore path needs strands-agents ≥ 1.45.0. Upgrade Strands. |
| 401 / auth errors | Set DAKERA_API_KEY (or pass api_key=) to match the server's configured key. |
Related integrations
Links
- GitHub — strands-dakera
- PyPI — strands-dakera
- Strands Agents
- Dakera deploy — Docker Compose setup
- All integrations
Frequently Asked Questions
How do I add persistent memory to Strands Agents?
Install strands-dakera, run a self-hosted Dakera server, then either add the dakera_memory tool to your agent or plug DakeraMemoryStore into the Strands MemoryManager for automatic recall and write-back.
Does Strands work with Dakera?
Yes. strands-dakera (v0.2.0, Apache-2.0) is a community Strands Agents integration that exposes both a model-callable dakera_memory tool and a native DakeraMemoryStore, backed by a self-hosted Dakera memory server.
What versions of Strands and Python does it need?
Python ≥ 3.10 and strands-agents ≥ 1.45.0 — the 1.45 requirement comes from the strands.memory module the DakeraMemoryStore plugs into. The tool pattern works on the same version.
What is the difference between the tool and the MemoryStore?
The dakera_memory tool is called explicitly by the model for auditable, out-loud memory operations. DakeraMemoryStore plugs into the MemoryManager and recalls or writes memory automatically with no prompt changes. Both share one server and one agent_id namespace.
What does Dakera add to Strands?
Decay-weighted recall ranked by importance × recency × semantic relevance, importance-typed storage (episodic / semantic / procedural / working), and self-hosted operation with no cloud key.
Ready to ship?
Deploy Dakera in minutes — self-hosted and free. Cloud managed hosting coming soon.
Give your AI agents persistent memory
Self-host free today — or join the Dakera Cloud waitlist for managed hosting, SLA & founder pricing.