This document describes the state and variable management system within RAGFlow's Agent and Workflow Engine (Canvas). It covers variable naming, scoping, and resolution across the Python backend, the Go agent runtime, and the frontend visual editor. The system enables dynamic data flow between components, maintains conversation context, and provides a standardized syntax for referencing data across the workflow graph. It covers both the Python Graph state and the Go CanvasState implementation designed for concurrent access.
Sources: agent/canvas.py49-87 agent/component/base.py43-55 internal/agent/runtime/state.go1-30
RAGFlow uses three primary variable scopes, identified by specific prefixes or separators:
| Scope | Syntax | Example | Purpose |
|---|---|---|---|
| System | sys.<name> | sys.query, sys.user_id | Built-in workflow state managed by the engine agent/canvas.py81-85 |
| Environment | env.<name> | env.api_key | User-defined persistent variables within the global scope. |
| Component Output | <component_id>@<output_name> | retrieval_0@content | Output values produced by specific components during execution agent/canvas.py200-201 |
Variables are referenced in prompts or parameters using double curly braces: {{variable}}. The backend resolves these using regex patterns to identify the source component and variable name agent/canvas.py168-207
Sources: agent/canvas.py75-86 agent/component/llm.py43 agent/component/message.py193
The Graph class in agent/canvas.py orchestrates variable resolution during Python-based workflow execution.
get_value_with_variable(value): The entry point for string interpolation. It scans a string for {{variable}} patterns and replaces them with resolved values agent/canvas.py168-193get_variable_value(exp): The core logic that determines the scope. If the expression contains @, it splits it into cpn_id and var_nm to fetch from component outputs via self.get_component(cpn_id) agent/canvas.py195-207string_format(template, args): Used by components like LLM to perform final substitution using the resolved arguments dictionary agent/component/base.py265-274Message consume the generator to produce a combined string agent/component/message.py161-167 agent/component/message.py182-186json.dumps agent/component/message.py137-142doc_id, filename), which can be extracted as downloads or stringified into content agent/component/message.py69-87Sources: agent/canvas.py168-207 agent/component/message.py103-143 agent/component/message.py182-186
CanvasState)The Go agent port implements a high-performance, concurrent state management system in internal/agent/runtime/state.go. Unlike the Python implementation, which relies on dictionary access within the Graph object, the Go CanvasState uses a RWMutex to ensure thread safety during parallel execution of nodes.
CanvasState: Holds the global variables and component-specific outputs internal/agent/runtime/state.go1-30sync.RWMutex to allow multiple components to read variables simultaneously while serializing writes to outputs internal/agent/runtime/state.go1-40The Go runtime handles component output mapping and variable resolution during the invocation of components like Retrieval and CodeExec. For instance, the retrievalComponent in internal/agent/component/universe_a_wrappers.go merges node-level defaults with per-call inputs before calling the underlying tool internal/agent/component/universe_a_wrappers.go167-175
Sources: internal/agent/runtime/state.go1-40 internal/agent/component/universe_a_wrappers.go197-212
The following diagrams bridge the Natural Language references in prompts to the code entities that resolve them.
Sources: agent/canvas.py168-207 agent/component/base.py43-47 rag/prompts/generator.py41-66
Sources: internal/agent/component/universe_a_wrappers.go167-183 internal/agent/runtime/state.go1-30
System variables are initialized in the globals dictionary of the Canvas DSL. They track the state of the current execution task and provide context to components.
| Variable Name | Description |
|---|---|
sys.query | The user's input string for the current turn agent/canvas.py82 |
sys.user_id | The unique identifier for the tenant/user executing the flow agent/canvas.py83 |
sys.conversation_turns | Counter for the number of rounds in the current session agent/canvas.py84 |
sys.files | A list of files or attachments provided in the current turn agent/canvas.py85 |
Sources: agent/canvas.py80-85 agent/component/llm.py43
Each component maintains its own inputs and outputs dictionaries within its param object agent/component/base.py43-47
LLM parses sys_prompt and prompts agent/component/llm.py101-110get_kwargs (in Message) or applyDefaults (in Go wrappers) resolves these references into actual values agent/component/message.py154-180 internal/agent/component/universe_a_wrappers.go197-212set_output(key, value) to store results. For example, the Categorize component sets category_name and _next to determine the subsequent path agent/component/categorize.py149-150LLMToolPluginCallSession and MCPToolCallSession to handle tool-calling state and reasoning context agent/component/agent_with_tools.py113-116Sources: agent/component/base.py43-55 agent/component/message.py144-180 agent/component/categorize.py149-150 rag/prompts/generator.py41-66 agent/component/agent_with_tools.py104-116
The globals section of the DSL is persisted within the dsl JSON object. This includes sys.* defaults and any env.* variables agent/canvas.py81-86 The Graph.load() method reconstructs component objects and their parameters from this DSL, ensuring that parameters are validated against their respective ComponentParamBase classes agent/canvas.py102-115
Components can interact with the persistent memory system. The Message component triggers queue_save_to_memory_task to ensure conversation history reflects resolved values agent/component/message.py43 The Categorize component dynamically updates its system prompt based on category descriptions before invocation agent/component/categorize.py55-88
Sources: agent/canvas.py80-86 agent/canvas.py102-115 agent/component/message.py43 agent/component/categorize.py55-88
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.