The Variable Resolution System provides a unified mechanism for referencing and accessing data from different sources within workflow execution. This system enables blocks to access outputs from previous blocks, environment variables, workflow variables, and loop/parallel execution context using a consistent reference syntax.
For information about workflow variables as a storage mechanism, see Workflow Variables. For information about how variables are used in specific block types, see Workflows & Blocks.
Sources: apps/sim/executor/variables/resolvers/block.ts1-245 apps/sim/app/api/function/execute/route.ts347-562
The Variable Resolution System converts reference strings (e.g., <block_name.field>, {{ENV_VAR}}, <variable.name>) into their actual values during workflow execution. Resolution occurs at multiple execution stages and supports different contexts including:
Title: Variable Resolution Architecture
Sources: apps/sim/executor/variables/resolver.ts1-100 apps/sim/executor/variables/resolvers/reference.ts1-50
The system supports five distinct reference syntax types, each with specific use cases and resolution rules:
| Syntax Type | Pattern | Example | Use Case |
|---|---|---|---|
| Block Reference | <block_name> or <block_name.path> | <email.subject> | Access output from upstream blocks |
| Environment Variable | {{VAR_NAME}} | {{API_KEY}} | Access environment variables |
| Workflow Variable | <variable.name> | <variable.userId> | Access workflow-scoped variables |
| Loop Context | <loop.property> | <loop.index>, <loop.item> | Access loop iteration state |
| Parallel Context | <parallel.property> | <parallel.index>, <parallel.currentItem> | Access parallel branch state |
Block references use angle brackets with optional dot-notation for nested field access. Block names are normalized (spaces removed, lowercase) for matching.
<block_name> # Entire block output
<block_name.field> # Single field
<block_name.nested.path.field> # Nested field access
Special characters in references:
. (period) - Path delimiter for nested property access_ (underscore) - Valid in block names and field names[email protected]) are NOT treated as referencesSources: apps/sim/executor/constants.ts100-108 apps/sim/executor/variables/resolvers/block.ts36-46 apps/sim/app/api/function/execute/route.test.ts293-324
Environment variables use double curly braces and must match exact variable names (case-sensitive).
{{API_KEY}} # Resolves to environment variable value
{{DATABASE_URL}} # Resolves to environment variable value
Sources: apps/sim/app/api/function/execute/route.ts419-468 apps/sim/executor/utils/reference-validation.ts1-50
Workflow variables use the <variable. prefix followed by the variable name. Variable names are normalized for matching.
<variable.userName> # Workflow variable
<variable.api_config> # Workflow variable with underscore
Sources: apps/sim/app/api/function/execute/route.ts347-416
Variable resolution follows a multi-stage process that handles different reference types and contexts:
Title: Variable Resolution Flow
The system resolves variables in a specific order to ensure correct scoping and prevent conflicts:
<variable.name>) - Resolved first, highest priority{{VAR}}) - Resolved second<block_name>) - Resolved lastThis order ensures that workflow variables can override environment variables when needed, and block references are resolved after all other variable types.
Sources: apps/sim/app/api/function/execute/route.ts537-562
To prevent naming conflicts and ensure safe code execution, the system replaces references with safe variable names:
| Original Reference | Safe Variable Name | Purpose |
|---|---|---|
<variable.userName> | __variable_userName | Prevent conflicts with user code |
{{API_KEY}} | __var_API_KEY | Prevent conflicts with user code |
<email.subject> | __tag_email_0subject | Prevent conflicts, escape dots |
The safe variable names are then injected into the execution context (code environment) with their resolved values.
Sources: apps/sim/app/api/function/execute/route.ts410-413 apps/sim/app/api/function/execute/route.ts462-465 apps/sim/app/api/function/execute/route.ts522-524
The Variable Resolution System uses a resolver pattern with multiple specialized resolver implementations:
Title: Resolver Class Hierarchy
Sources: apps/sim/executor/variables/resolvers/reference.ts1-50 apps/sim/executor/variables/resolver.ts1-100
The BlockResolver class handles resolution of block output references. It maintains mappings between block names and IDs, and provides path navigation for nested properties.
Key responsibilities:
Implementation details:
Sources: apps/sim/executor/variables/resolvers/block.ts21-245
The BlockResolver formats resolved values differently based on the target block type:
| Target Block Type | Formatting Behavior |
|---|---|
| condition | Strings are JSON-stringified with escaped quotes |
| function | Objects are JSON-stringified; strings in template literals kept as-is |
| response | Strings kept as-is; objects/arrays JSON-stringified |
| other | Objects JSON-stringified; primitives converted to string |
Sources: apps/sim/executor/variables/resolvers/block.ts168-243
For Function blocks and custom tools that execute code, the system performs comprehensive variable resolution before code execution.
Title: Code Variable Resolution Pipeline
Workflow variables are resolved by:
<variable.name> patterns in the codeExample:
Sources: apps/sim/app/api/function/execute/route.ts347-416
Environment variables are resolved from two sources:
params)envVars)Parameters take precedence over environment variables.
Example:
Sources: apps/sim/app/api/function/execute/route.ts419-468
Block references (tags) are resolved using:
Special handling:
undefined values are replaced with language-appropriate literals (undefined for JavaScript, None for Python){ or <FileRef file-url="https://github.com/simstudioai/sim/blob/31fdd2be/ are parsed as JSON\n- Complex objects are stored in context variables as-is (not stringified)\n\nExample#LNaN-LNaN" NaN file-path="` are parsed as JSON\n- Complex objects are stored in context variables as-is (not stringified)\n\nExample">HiiThe collectBlockData function gathers all necessary block outputs and metadata for variable resolution. This function is called before executing blocks that need to resolve references (Agent, Function, Condition blocks).
Title: Block Data Collection Process
The function collects three key data structures:
Usage locations:
function_execute tool for custom tool execution apps/sim/executor/handlers/agent/agent-handler.ts308-320function_execute tool apps/sim/executor/handlers/function/function-handler.ts26-38function_execute tool for condition evaluation apps/sim/executor/handlers/condition/condition-handler.ts29-40Sources: apps/sim/executor/utils/block-data.ts1-100
Variable resolution behavior changes based on execution context, particularly for loop and parallel constructs.
Within loop iterations, the system provides special loop-scoped variables:
| Variable | Type | Description |
|---|---|---|
<loop.index> | number | Current iteration index (0-based) |
<loop.item> | any | Current item (forEach loops) |
<loop.iteration> | number | Current iteration (1-based) |
Nested loops: Each loop level maintains its own scope. The innermost loop's context takes precedence.
Sources: apps/sim/executor/variables/resolvers/loop.ts1-100 apps/sim/executor/orchestrators/loop.ts1-500
Within parallel branches, each branch has isolated context:
| Variable | Type | Description |
|---|---|---|
<parallel.index> | number | Branch index (0-based) |
<parallel.currentItem> | any | Current item (collection-based parallels) |
<parallel.branchId> | string | Unique branch identifier |
Branch isolation: Each parallel branch cannot access other branches' execution state. Only the parent context is shared.
Sources: apps/sim/executor/variables/resolvers/parallel.ts1-100 apps/sim/executor/orchestrators/parallel.ts1-500
The resolution process requires a ResolutionContext containing:
This context provides:
Sources: apps/sim/executor/variables/resolvers/reference.ts1-50
Email addresses containing angle brackets (e.g., John Doe <[email protected]>) are NOT treated as variable references. The reference detection pattern specifically excludes email formats.
Pattern matching rules:
<block_name> where block_name matches [a-zA-Z_][a-zA-Z0-9_.]*<[email protected]> (contains @)Sources: apps/sim/app/api/function/execute/route.ts483-485 apps/sim/app/api/function/execute/route.test.ts293-324
When a reference resolves to undefined, the system uses language-appropriate representations:
| Language | Undefined Representation |
|---|---|
| JavaScript | undefined |
| Python | None |
Sources: apps/sim/app/api/function/execute/route.ts506-508
String values that look like JSON are automatically parsed:
This parsing is attempted for strings starting with { or <FileRef file-url="https://github.com/simstudioai/sim/blob/31fdd2be/.\n\nSources#LNaN-LNaN" NaN file-path="`.\n\nSources">Hii
The BlockResolver includes special handling for legacy block types:
Response Block:
<response.response> but output doesn't have a response field, the system tries the root levelWorkflow Block:
<workflow.result.response> but result.response doesn't exist, the system tries result directlyThis ensures workflows created with older versions continue to work correctly.
Sources: apps/sim/executor/variables/resolvers/block.ts108-148
Block name matching is case-insensitive and spaces are removed:
"My Email Block" matches <myemailblock>
"API Call" matches <apicall>
"api_call" matches <apicall>
Environment variable names are case-sensitive:
{{API_KEY}} does NOT match {{api_key}}
Sources: apps/sim/executor/constants.ts165-174 apps/sim/executor/variables/resolvers/block.ts164-166
Variable resolution integrates at multiple points in the workflow execution lifecycle:
Title: Variable Resolution in Execution Lifecycle
Sources: apps/sim/executor/handlers/agent/agent-handler.ts56-107 apps/sim/executor/handlers/function/function-handler.ts12-55 apps/sim/executor/handlers/condition/condition-handler.ts18-69 apps/sim/executor/handlers/workflow/workflow-handler.ts84-139
Refresh this wiki
This wiki was recently refreshed. Please wait 7 days to refresh again.