STRANDS AGENTS · PYTHON

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.

Package: strands-dakera v0.2.0  ·  Apache-2.0  ·  Python ≥ 3.10  ·  GitHub →  ·  PyPI →

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_memory tool — a native Strands tool the model invokes explicitly to store, retrieve, get, update and delete memories. Best when you want the model to reason out loud about what to remember.
  • DakeraMemoryStore — a class that conforms to the Strands MemoryStore protocol and plugs into MemoryManager. 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 traceYou want continuity with zero prompt or logic changes
The model should decide what is worth rememberingEvery turn should transparently recall relevant context
You need fine-grained control over importance and type per writeYou want the framework to distil and store facts for you
Not mutually exclusive. Both patterns talk to the same Dakera server and the same agent_id namespace, so you can start with the store for effortless continuity and add the tool later for explicit control — no data migration.
HOW DAKERA MEMORY FLOWS THROUGH A STRANDS AGENT User turn the new message Dakera recall rank by importance × recency × relevance → top-K memories Strands loop DakeraMemoryStore or dakera_memory memories injected → LLM Reply write-back: the new exchange is stored for next time

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

1

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
2

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.

3

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.

What's exported. 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

ActionRequired fieldsOptional fieldsDescription
storeagent_id, contentimportance, memory_type, metadataStore a new memory and return its ID
retrieveagent_id, querytop_k (default 5)Decay-weighted semantic search
getagent_id, memory_idFetch a specific memory by ID
updateagent_id, memory_idcontent, memory_type, metadataUpdate content, type or metadata of an existing memory
deleteagent_id, memory_idDelete a memory by ID

Tool parameters

ParameterTypeNotes
actionstrRequired. One of store · retrieve · get · update · delete
agent_idstrRequired for every action — the namespace that owns the memories
contentstrMemory text. Required for store; optional for update
querystrNatural-language query. Required for retrieve
memory_idstrRequired for get, update, delete
importancefloat0.0–1.0 weight applied on store
memory_typestrepisodic · semantic · procedural · working (default episodic)
metadatadictArbitrary structured metadata stored alongside the memory
top_kintNumber 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
Why consent matters here. With the tool pattern the model — not you — decides when to write or delete. The confirmation gate is a safety default so an over-eager agent can't silently rewrite or drop memories; disable it deliberately once you trust the flow.

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

ParameterTypeDefaultDescription
agent_idstrAgent namespace that owns the memories (required, positional)
namestr"dakera"Store name within the MemoryManager
descriptionstr · None"Persistent, decay-weighted long-term memory backed by Dakera."Human-readable store description
max_search_resultsint · NoneNoneCap on memories per recall. When unset, falls back to 5
writableboolTrueWhether the agent loop writes memories back via add()
extractionAnyNoneFact-extraction config handed to the manager's ModelExtractor
importancefloat · NoneNoneDefault importance (0.0–1.0) applied to writes
memory_typestr"episodic"episodic · semantic · procedural · working
base_urlstr · None$DAKERA_BASE_URL or http://localhost:3000Dakera server URL
api_keystr · None$DAKERA_API_KEYAPI key for the Dakera server
clientDakeraServiceClient · NoneNoneInject 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

VariableDefaultDescription
DAKERA_BASE_URLhttp://localhost:3000Dakera server URL (used by both patterns)
DAKERA_API_KEYAPI key for the Dakera server (dk-…)
BYPASS_TOOL_CONSENTSet true to skip confirmation on mutating tool actions
Why decay-weighted? Unlike a fixed-TTL store, 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.

TypeWhat it holdsExample
episodicSpecific events and interactions, tied to a moment"Alex asked for a refund on July 30."
semanticDurable facts and preferences that stay true over time"Alex prefers dark-mode dashboards."
proceduralHow-to knowledge and repeatable steps"Deploy runs on Wednesdays via the release script."
workingShort-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

SymptomLikely cause & fix
Connection refused / timeoutThe 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 inputA mutating action is asking for consent. In headless runs set BYPASS_TOOL_CONSENT=true.
Store never recalls anythingCheck the agent_id matches what was written, and that memories exist for that namespace. Recall is scoped per agent_id.
ImportError on strands.memoryThe MemoryStore path needs strands-agents ≥ 1.45.0. Upgrade Strands.
401 / auth errorsSet DAKERA_API_KEY (or pass api_key=) to match the server's configured key.

Related integrations

Links

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.

Self-Host Free → Join Cloud Waitlist →

Give your AI agents persistent memory

Self-host free today — or join the Dakera Cloud waitlist for managed hosting, SLA & founder pricing.

✓ You're on the list. We'll be in touch.