Dify Memory Plugin
A first-party MemorySync Tool plugin for Dify: recall context before LLM nodes, remember the facts in what the user said after them, search with scores, and forget one memory at a time — the cross-conversation user memory Dify does not have natively.
What Dify cannot do natively
Dify’s built-in memory is per-conversation: the LLM-node memory toggle and conversation variables reset with every new thread, and the knowledge base is static documents. Nothing remembers the USER across conversations or apps — exactly the gap this plugin fills with four curated tools.
- Install the plugin and add your MemorySync API key as its credential.
- Drop a Recall Context node before your LLM node and reference its output in the prompt.
- Drop a Remember node after it to store what the user shared.
- Facts now follow the user across every conversation, every Dify app — and every other MemorySync surface.
Before you start
- A MemorySync API key. Create one in the dashboard under Settings → API Keys, inside a project.
- Dify 1.14+ (cloud or self-hosted). Self-hosted needs plugin installs enabled.
Install the plugin
Step 1 — get the package
The plugin is not on the Dify Marketplace yet. Until it is, build the package from its public source with Dify’s own plugin CLI:
git clone https://github.com/memorysyncio/memorysync-dify memorysyncdify plugin package ./memorysync# → memorysync.difypkg
Step 2 — upload it
In Dify go to Integrations → Install → Local Package File and pick memorysync.difypkg. In older Dify versions the same menu is Plugins → Install Plugin → Install from Local Package File.
If your self-hosted instance enforces marketplace signatures, allow local packages in .env:
FORCE_VERIFYING_SIGNATURE=false
Step 3 — add the credential
Open Integrations → Tool Plugin → MemorySync and add your MemorySync API key under Authorization. Dify validates it against the live API immediately — a bad key fails here, not mid-workflow.
Wire a chatflow
The canonical pattern — recall before the LLM, remember after it:
- 01
User Input
The end user asks a question in your Dify app.
- 02
Recall Context — MemorySync tool node
Fetches the user’s relevant long-term memories and outputs a prompt-ready block as
{{recall_context.text}}. - 03
LLM Node
Reference
{{recall_context.text}}in the prompt — the model answers with the memory block in context. - 04
Remember — MemorySync tool node
Sends the user’s message to fact extraction — only the durable facts in it are stored; a re-run is recognised and not processed twice.
- 05
Answer
The reply goes back to the user — and the memory follows them to every future conversation.
Reference {{recall_context.text}} inside the LLM node’s prompt. User identity needs ZERO wiring: the plugin reads Dify’s own runtime user automatically, with an optional per-call override parameter and a deterministic default fallback.
The four tools
| Tool | What it does |
|---|---|
| Recall Context | Prompt-ready block of the user’s relevant memories (text + variable + JSON outputs) — drop before any LLM node |
| Remember | Send the user’s message (or a fact about the user) to fact extraction — only the durable facts in it are stored, never the text. Speaker role is a choice: assistant messages are acknowledged and not stored. Re-running the node never processes a message twice |
| Search Memories | Scored JSON list, capped at 25 results, for branching or custom formatting |
| Forget Memory | Delete exactly ONE memory by id — loud on failure, never pretends |
Remember reports what happened, both as JSON (status, accepted, stored_as, processing_status, already_exists, request_id) and as a message: sent for fact extraction, nothing worth remembering, already sent and not processed again, assistant messages not stored, or the monthly quota reached. It never reports a memory id — facts are extracted asynchronously and get their own.
Memories flow to and from every other MemorySync surface — a fact learned in a Dify chatbot is recallable from LangChain agents, the CLI, or voice agents.
Quotas and plan limits
Hitting a monthly plan limit never breaks a workflow: over-limit writes are accepted without storing and recalls come back empty (the {{recall_context.text}} output then reads “No relevant memories yet.”), so the LLM node keeps running. Failures the workflow should react to arrive as branchable JSON with http_status and a friendly quota message — never an opaque blob.
Billing counts requests, not results: every Remember run is one add, whichever speaker role it sends, and every Recall Context or Search Memories run is one retrieval — Recall Context is one more when recall returns nothing and its semantic fallback runs. A Remember re-run recognised as already sent is not counted again. Forget Memory is free.
Troubleshooting
- Plugin refuses to install (self-hosted) — your instance enforces marketplace signatures; set
FORCE_VERIFYING_SIGNATURE=falsein.envand restart. - Credential validation fails — the key is checked live: 401 means a wrong/revoked key. Paste a fresh one from the dashboard.
- Recall block is empty — first conversations have nothing to recall yet; extraction is asynchronous, so a fact stored seconds ago may take a moment to appear.
- Node re-runs duplicated nothing — expected: deterministic idempotency seeds let the server recognise a Remember re-run (“Already sent to MemorySync — not processed again.”).
- Remember said nothing was saved — read its message: small talk has nothing worth remembering, and assistant messages are not stored as memories. Pass the user’s own words.
Supported versions
| Surface | Requires | Verified on |
|---|---|---|
memorysync plugin 1.1.0 | Dify 1.14+ (plugin runner Python 3.12+) | 38 CI checks via the SDK’s own offline harness (Tool.from_credentials) on the latest dify_plugin: the user ladder, idempotent Remember with honest outcome reports, capped scored Search with tolerant parsing, loud single-id Forget with the no-delete_all assertion, provider credential validation (200/403 valid, 401 invalid), quota modes, and manifest/provider/tool YAML schema sanity |
How it compares
| Mem0 (community plugin) | Zep | Supermemory | MemorySync | |
|---|---|---|---|---|
| Authorship | ✗ community (verified: false), 2 tools | — no plugin at all | — no plugin at all | ✓ first-party, 4 curated tools |
| User scoping | ✗ user_id is a free-form parameter — forget to wire it and every end user shares one memory | — | — | ✓ auto-resolved: parameter → Dify’s runtime user → default |
| Session scoping | ✗ none | — | — | ✓ the conversation_id recorded as session_id on every fact, with retries recognised per dify::<conversation_id> scope |
| Latency | ✗ 30s hard timeout — a hang blocks the workflow node | — | — | ✓ 10s budget, structured soft-fail |
| Errors | ✗ opaque blobs the LLM was never told to handle | — | — | ✓ branchable JSON with http_status + a friendly quota message |
| Schema drift | ✗ bare r["score"] KeyErrors | — | — | ✓ tolerant parsing, never raises |
| Retries | ✗ node re-runs duplicate extractions | — | — | ✓ deterministic idempotency seeds |
| Mass deletion | ✗ a fork exposes delete_all_memories to the LLM | — | — | ✓ single-id Forget only — no delete-everything tool exists |