Workflow Memory Management#
Overview#
Three workflow node types handle conversation memory through distinct mechanisms with different user-control surfaces:
| Node Type | Memory Mechanism | User Control | Version |
|---|---|---|---|
| LLM (+ Question Classifier, Parameter Extractor) | TokenBufferMemory via MemoryConfig | Toggle + window size + role prefix | Built-in |
Legacy Agent (AgentNode) | MemoryConfig passed to plugin strategy | Toggle + window size + role prefix | "1" |
Agent V2 (DifyAgentNode) | Session snapshot (CompositorSessionSnapshot) | Reserved / not yet user-configurable | "2" |
Both AgentNode v1 and DifyAgentNode v2 share BuiltinNodeTypes.AGENT and are differentiated by version string in the node registry β see resolve_workflow_node_class().
LLM Node Memory (TokenBufferMemory)#
Applies to: LLM, QUESTION_CLASSIFIER, PARAMETER_EXTRACTOR nodes with memory set.
DifyNodeFactory._build_memory_for_llm_node() reads conversation_id from the variable pool, fetches the Conversation ORM row, and constructs a TokenBufferMemory object that is injected at node construction time. If memory config or conversation_id is absent, it returns None and no history is prepended.
TokenBufferMemory.get_history_prompt_messages() fetches up to 500 prior messages, then applies two limits in sequence:
- Message count β
MemoryConfig.window.size(whenwindow.enabled=True) - Token budget β pops the oldest messages until within
max_token_limit
MemoryConfig (imported in AgentNodeData from core.prompt.entities.advanced_prompt_entities) controls:
window.enabled/window.sizeβ sliding message windowrole_prefix.user/role_prefix.assistantβ text prefixes when formatting history as plain text
Key design constraint: All LLM nodes in a chatflow share the same conversation history because only the final Answer node output is saved as message.answer. An intermediate LLM node therefore reads the last turn's final reply, not its own prior outputs . Workarounds: disable memory on intermediate nodes, use Conversation Variables, or replace with an Agent node.
Preloading at construction time: get_node_creation_preload_selectors() ensures CONVERSATION_ID is inserted into the variable pool before DifyNodeFactory.create_node() runs for any memory-using node .
Legacy Agent Node Memory (AgentNode v1)#
Applies to: AgentNode registered at version "1".
AgentNodeData.memory is typed MemoryConfig | None = None. When set, the memory config is forwarded through the plugin-strategy adapter to the underlying agent runner, using the same MemoryConfig envelope as LLM nodes (window size, role prefix).
Node construction branches on issubclass(node_class, DifyAgentNode) inside _build_agent_node_init_kwargs(). For v1 nodes it supplies strategy_resolver, presentation_provider, runtime_support, and message_transformer β no session store is involved.
Agent V2 Node Memory (DifyAgentNode)#
Applies to: DifyAgentNode registered at version "2".
Agent V2 uses a session snapshot model: after each run the CompositorSessionSnapshot (from the agenton compositor inside the dify-agent service) is serialized to JSON and saved to AgentWorkspaceBinding.session_snapshot (a LongText column) by WorkflowAgentWorkspaceStore.save_active_snapshot(). On the next execution it is deserialized and forwarded in the CreateRunRequest to the dify-agent FastAPI service .
Inside dify-agent, PydanticAIHistoryLayer (type ID pydantic_ai.history) stores runtime_state.messages as a Pydantic model within the snapshot, providing automatic history reconstruction across turns .
Memory is currently reserved, not user-configurable. runtime_feature_manifest.py lists "memory" in RESERVED_AGENT_BACKEND_FEATURES with status "reserved_not_executed" β it is saved in Agent Soul config but not yet executed by the agent backend. The snapshot mechanism provides implicit multi-turn continuity without an explicit user-facing toggle.
DifyAgentNodeData carries no memory configuration fields; the node data model is intentionally minimal (agent_node_kind = "dify_agent", version = "2") .
Key Files#
| File | Purpose |
|---|---|
api/core/workflow/node_factory.py | Node construction; _build_memory_for_llm_node(), _build_agent_node_init_kwargs() |
api/core/memory/token_buffer_memory.py | TokenBufferMemory β history fetch, token pruning |
api/core/workflow/nodes/agent/entities.py | AgentNodeData with optional MemoryConfig field |
api/core/workflow/nodes/agent_v2/runtime_feature_manifest.py | Reserved feature list including "memory" |
api/core/workflow/nodes/agent_v2/session_store.py | WorkflowAgentWorkspaceStore β snapshot persistence |
api/core/workflow/nodes/agent_v2/runtime_request_builder.py | Forwards snapshot to agent backend run request |