Dify is one of the fastest ways to build an LLM app — but out of the box, its apps forget everything between runs. The Dakera Memory plugin fixes that: install it from the Marketplace, point it at a self-hosted Dakera server, and your Dify Agent, Chatflow, and Workflow apps get persistent, importance-scored memory that decays gracefully instead of piling up.
Why memory, and why decay
A stateless agent has two failure modes. It either forgets — losing a user's preferences, decisions, and hard-won context the moment a session ends — or it remembers too much, stuffing every past turn into the prompt until the signal drowns in noise. Dify's built-in conversation variables cover the short-term case: they carry state within a single chat. What they can't do is carry a fact from last week into today, share it across apps, rank it against everything else the agent knows, or prune it when it goes stale.
Dakera's answer is decay-weighted memory: every memory carries an importance score, and older low-value facts fade over time so they stop competing with what's relevant now. Reach for the plugin when you want a Dify app to remember users across sessions, keep context fresh rather than bloated, and stay entirely on infrastructure you control. If you only need in-conversation state, the built-in variables are enough — Dakera is for durable memory that outlives the conversation and is shared, ranked, and prunable.
The plugin at a glance
Dakera Memory is a tool plugin (identifier dakera/dakera, author dakera, name dakera), not a model plugin — it requests only the tool permission and never touches your LLM configuration.
| Field | Value |
|---|---|
| Identifier | dakera/dakera · version 0.0.1 |
| Plugin type | tool (no model / LLM permission requested) |
| App types | Agent · Chatflow · Workflow |
| Runtime | Python 3.12 · amd64 + arm64 |
| Compatibility | Dify Community Edition and Dify Cloud |
| Tags | productivity · utilities |
Once installed and authorized, all six tools are available in every app type — the only difference is who decides to call them. In an Agent app you expose the tools and the LLM decides when to remember and when to look things up, guided by each tool's description. In a Chatflow or Workflow app the tools become nodes you place on the canvas and wire explicitly — typically Recall before the LLM node and Store after it.
Six tools, namespaced per agent
The plugin exposes six tools, each scoped by an agent_id (default dify-agent) so different apps or users never see each other's memories. Each maps to one REST call on your Dakera server:
| Tool | What it does | REST call |
|---|---|---|
| Store | Save an importance-weighted fact | POST /v1/memory/store |
| Recall | Ranked semantic retrieval | POST /v1/memory/recall |
| Search | Filtered browse by tags / importance | POST /v1/memory/search |
| Get | Fetch one memory by ID | GET /v1/memory/get/{id} |
| Update | Edit content / importance / tags | PUT /v1/memory/update/{id} |
| Forget | Delete, always scoped | POST /v1/memory/forget |
The full parameter reference
Every parameter below comes from the plugin manifest. agent_id is optional on all six tools and defaults to dify-agent; keep it consistent across Store and Recall or the reads won't find the writes.
Store · POST /v1/memory/store
| Parameter | Req | Default | Notes |
|---|---|---|---|
| content | required | — | Concise, self-contained fact. Empty content makes no HTTP call. |
| importance | optional | 0.5 | 0.0–1.0, clamped. Higher values decay more slowly — use 0.8–1.0 for durable facts. |
| session_id | optional | — | Tag with a conversation ID for session-scoped recall. |
| tags | optional | — | Comma-separated, e.g. preference,ui,dark-mode. |
Recall · POST /v1/memory/recall
| Parameter | Req | Default | Notes |
|---|---|---|---|
| query | required | — | Natural-language description of what to recall. Empty query makes no HTTP call. |
| top_k | optional | 5 | Number of memories to return, 1–20 (clamped to 20). |
| session_id | optional | — | Restrict to one session; omit to search all sessions for the agent. |
Search · POST /v1/memory/search
| Parameter | Req | Default | Notes |
|---|---|---|---|
| query | optional | — | Optional text query; omit to browse/filter without semantic matching. |
| tags | optional | — | Comma-separated filter — results must match all tags. |
| min_importance | optional | — | Lower bound on importance, 0.0–1.0. |
| top_k | optional | 10 | Number of memories to return, 1–50 (clamped to 50). |
Get, Update, Forget
| Tool · parameter | Req | Notes |
|---|---|---|
| Get · memory_id | required | Fetch one memory (content, importance, tags, metadata). agent_id is passed as a query parameter. |
| Update · memory_id | required | Only the fields you supply change. |
| Update · content | optional | Replacement text — re-embedded server-side if provided. |
| Update · importance | optional | New importance, 0.0–1.0. |
| Update · tags | optional | Comma-separated tags that replace (not merge with) current tags. |
| Forget · memory_ids | selector | Comma-separated IDs, e.g. mem_a,mem_b. |
| Forget · session_id | selector | Delete all memories tagged with this session. |
| Forget · tags | selector | Delete memories matching all these tags. |
| Forget · below_importance | selector | Delete memories strictly below this value (0.0–1.0) — prunes low-value noise. |
Forget's four selectors are each individually optional, but you must supply at least one. Recall and Search both return each memory's ID, so results chain straight into Get, Update, and Forget.
Recall vs. Search — two reads, two jobs
The two read tools look alike but answer different questions. Recall is the in-conversation call: a semantic match that returns the best hits ranked most-relevant-first, over a store where Dakera weights memories by importance and lets old ones decay. Use it when the agent needs the most useful context right now, capped at top_k = 20. Search is the deterministic browse: filter by tags and min_importance to pull a specific slice, with a larger ceiling of top_k = 50. Use it when you want everything matching a rule, or to list and audit what an agent remembers rather than the "best" hits.
Why decay-weighted recall matters
A flat vector store returns the nearest neighbours and nothing more — a fact you mentioned once, months ago, competes on equal footing with what the user just said. Dakera ranks recall by importance and recency as well as similarity, so relevance keeps pace with the conversation and the context you inject stays fresh instead of growing unbounded. That's the same engine that scores 88.2% Recall@20 on the 1,540-question LoCoMo benchmark, where retrieval is judged on surfacing the right memories, not raw vector distance alone. In a Dify app it means a Recall node with top_k = 5 spends its five slots on what actually matters — durable preferences and recent decisions — rather than on stale facts that happen to sit close in embedding space.
Safe by design. Forget refuses an unscoped mass-delete — you must pass at least one selector (memory_ids, session_id, tags, or below_importance), so it can't wipe a namespace by accident. The dk- API key is stored as a Dify secret and sent only as a Bearer token, never echoed back into tool output. Tool calls use a 15-second timeout; the credential health check uses 5 seconds, so a stalled server can't hang your flow.
Self-hosted, nothing phones home
The plugin is a thin HTTP client for a Dakera server you run. Every tool call is a JSON request to the server URL you configured, and nowhere else. There's no code execution, no filesystem access, no SQL, no browser, and no arbitrary per-invocation URL fetching; the destination is fixed per credential set, and it ships a PRIVACY.md referenced from its manifest. All memory content lives on your server — Dakera AI handles no third-party accounts and no health, financial, or biometric data on your behalf. Start a server with Docker Compose:
git clone https://github.com/dakera-ai/dakera-deploy
cd dakera-deploy && docker compose up -d # API on :3000
Then install Dakera Memory from the Dify Marketplace and authorize it with two credentials:
| Credential | Required | Value |
|---|---|---|
| Dakera Server URL | Yes | Base URL of your server, e.g. http://localhost:3000. Trailing slashes are trimmed. |
| Dakera API Key | No | dk-…, stored as a Dify secret. Leave empty for unauthenticated local dev (server started without DAKERA_API_KEY). |
On save, the provider probes GET /health/live with a 5-second timeout, so a bad URL or wrong key fails fast at setup rather than mid-flow. A 401 means the API key was rejected; any status other than 200/204 means the server URL is wrong or the server is unhealthy, and the save fails with a specific message. It runs on both Dify Community Edition and Dify Cloud — on Cloud the server must be publicly reachable (or tunneled), since localhost only works when Dify runs on the same host.
A typical loop
Wiring memory into a Dify app is two moves. Early in the flow, Recall something like "user's preferred language and conventions" to pull prior context into the prompt. When the agent learns something durable, Store it — e.g. "Alice prefers Rust over Python for backend services" with importance = 0.9. Next session, the same agent_id surfaces it, ranked above older, lower-importance facts. Under the hood, that Store call is a single JSON request to your server, and it hands back the stored memory's ID:
POST /v1/memory/store # Authorization: Bearer dk-...
{
"content": "Alice prefers Rust over Python for backend services",
"agent_id": "support-bot",
"importance": 0.9,
"tags": ["preference", "language"]
}
# → { "memory": { "id": "mem_abc123", ... } }
Wire it into a Chatflow
In a Dify Chatflow or Workflow app the tools become nodes you chain around your LLM. A minimal remember-then-answer loop uses just two of the six:
- Recall before the LLM. Add a Dakera · Recall node early in the flow. Feed the user's message in as the
query(e.g. thesys.queryvariable), keep a stableagent_idper app (saysupport-bot), and settop_k = 5. - Inject the memories. Reference the Recall node's output in your LLM node's context or system prompt, so the model answers with prior knowledge already in hand.
- Store what's durable after the LLM. Add a Dakera · Store node to persist any new, durable fact — set
importanceto0.8–0.9for preferences and commitments so they outlast decay.
The same pattern works in an Agent app: expose Store and Recall as tools and let the model decide when to remember and when to look things up. Because each tool ships an LLM-facing description, the agent gets guidance on how to use them without extra prompting.
Curate, don't just accumulate
Most memory add-ons only let you write and read. Dakera's plugin covers the full lifecycle, so you can keep a store healthy over time rather than watching it bloat:
- Get fetches a single memory by ID to inspect its content, importance, and tags.
- Update changes a memory in place — new content is re-embedded server-side, and tags replace rather than merge, so a corrected fact doesn't become a duplicate.
- Search browses deterministically by tags and
min_importance(up to 50 results) when you want to audit what an agent remembers, not just the top hits. - Forget prunes — pass
below_importance = 0.3to sweep out low-value memories, or asession_idto clear one conversation. It refuses to run without a selector, so you can't wipe a namespace by accident.
It's a complete CRUD-plus-recall surface, not a write-only bucket. Over time you Store durable facts at high importance, let decay demote the rest, Update what changes, and Forget below a threshold to keep the namespace lean.
Full setup, the complete six-tool parameter reference, and the config fields are on the Dify integration page → The plugin source is public on GitHub (repo: dakera-py). Dify joins Dakera's lineup alongside LangChain, LlamaIndex, CrewAI, AutoGen, Strands, PraisonAI, Agent Squad, and the Vercel AI SDK — see them all on the integrations page →
