Internal Parameters¶
This document describes the internal parameter system used in FlowDrop for system-level state management and orchestration.
Overview¶
Internal parameters are special parameters used for internal state management within the FlowDrop runtime. They follow a naming convention and receive special treatment by the ParameterResolver.
Quick Reference¶
| Parameter | Type | Description | Used By |
|---|---|---|---|
__iterator__ |
object |
Iterator state for loops | ForEachNode, IteratorNextNode, IteratorCollectNode, LoopControlNode |
__current_item__ |
mixed |
Current item in iteration | Nodes needing loop item |
__state__ |
object |
Complete graph state | ApprovalGateNode |
__messages__ |
array |
Message history | Nodes needing chat history |
__data__ |
object |
Workflow data store | StateStorageNode |
__node_id__ |
string |
Current node instance ID | ChatOutput |
__execution_id__ |
string |
Current execution ID | ChatOutput |
Naming Convention¶
Internal parameters are identified by their name prefix:
- Prefix:
__(double underscore) - Examples:
__iterator__,__context__,__state__
This convention follows the common practice in many programming languages where double underscores indicate internal/private/magic variables.
Special Handling¶
Internal parameters receive special treatment in the ParameterResolver:
-
Bypass Connectable Check: Internal parameters always accept runtime inputs, regardless of whether
connectable: TRUEis set in the node type configuration. -
Bypass Configurable Check: Internal parameters cannot be configured by users. Even if
configurable: TRUEis set, workflow values from users are ignored for internal parameters. This prevents users from tampering with system state. -
Automatic Injection: The orchestrator can inject internal parameters into nodes without requiring UI configuration.
-
Not User-Facing: Internal parameters should not be exposed to end users in the workflow editor UI (i.e., "Show Port" and "Config" should typically be unchecked).
Resolution Priority¶
For internal parameters: 1. Runtime input (always accepted) 2. Entity default 3. Schema default
Note: Workflow values (user configuration) are never used for internal parameters.
For regular parameters:
1. Runtime input (only if connectable: TRUE)
2. Workflow value (if configurable: TRUE)
3. Entity default
4. Schema default
Currently Defined Internal Parameters¶
__iterator__¶
Used by: ForEachNode, IteratorNextNode, IteratorCollectNode, LoopControlNode
Type: object
Description: Contains the iterator state for loop iteration. Injected by the StateGraphOrchestrator when executing loop-related nodes.
Structure:
{
"items": ["a", "b", "c"],
"currentIndex": 0,
"currentItem": "a",
"hasMore": true,
"results": []
}
Fields:
| Field | Type | Description |
|-------|------|-------------|
| items | array | The array being iterated over |
| currentIndex | integer | Current position in the array (0-based) |
| currentItem | mixed | The current item at currentIndex |
| hasMore | boolean | Whether there are more items after the current one |
| results | array | Collected results from each iteration |
Injection Point: StateGraphOrchestrator::buildRuntimeInputData()
Source: GraphState.iterator (of type IteratorState)
__current_item__¶
Used by: Nodes that need access to the current loop item
Type: mixed
Description: A convenience parameter containing just the current item from the iterator. This is a shorthand for accessing __iterator__.currentItem.
Injection Point: StateGraphOrchestrator::buildRuntimeInputData()
Source: GraphState.iterator.currentItem
__state__¶
Used by: ApprovalGateNode, and nodes that need full state access
Type: object
Description: Contains the complete graph state as an array. Used by nodes that need to inspect or manipulate the full execution state.
Structure:
{
"messages": [...],
"data": {...},
"iterator": {...},
"status": "running",
"error": null
}
Injection Point: StateGraphOrchestrator::buildRuntimeInputData()
Source: GraphState.toArray()
__messages__¶
Used by: Nodes that need access to the message history
Type: array
Description: Contains all messages in the current execution as an array. Each message is serialized using toArray().
Structure:
[
{
"role": "user",
"content": "Hello",
"timestamp": "2026-01-19T00:00:00Z"
},
{
"role": "assistant",
"content": "Hi there!",
"timestamp": "2026-01-19T00:00:01Z"
}
]
Injection Point: StateGraphOrchestrator::buildRuntimeInputData()
Source: GraphState.messages (mapped to arrays)
__data__¶
Used by: StateStorageNode, and nodes that need access to workflow data
Type: object
Description: Contains the workflow's data store - a key-value store for persisting data across nodes during execution.
Structure:
{
"user_name": "John",
"counter": 5,
"items": ["a", "b", "c"]
}
Injection Point: StateGraphOrchestrator::buildRuntimeInputData()
Source: GraphState.data
__node_id__¶
Used by: ChatOutput, and nodes that need to identify themselves
Type: string
Description: Contains the unique node instance ID within the workflow (e.g., chat_output.1).
Injection Point: Varies by context
Source: Job metadata or execution context
__execution_id__¶
Used by: ChatOutput, and nodes that need the execution context
Type: string
Description: Contains the unique execution ID for the current workflow run.
Injection Point: Varies by context
Source: Execution context
Adding New Internal Parameters¶
When creating a new internal parameter, follow these guidelines:
1. Naming¶
- Use the
__name__format (double underscores on both sides) - Choose a descriptive name that indicates the parameter's purpose
- Keep names lowercase with underscores for multi-word names
2. Define in Plugin Schema¶
Add the parameter to your plugin's getParameterSchema() method:
public function getParameterSchema(): array {
return [
"type" => "object",
"properties" => [
"__my_internal__" => [
"type" => "object",
"description" => "Internal state for [purpose]. Automatically injected by orchestrator.",
],
// ... other parameters
],
];
}
3. Document the Parameter¶
Add documentation for your internal parameter in this file, including: - Name and type - Which processor(s) use it - Structure/schema - Where it's injected from - Purpose and behavior
4. Inject from Orchestrator¶
If your internal parameter needs to be injected by the orchestrator, add the injection logic to StateGraphOrchestrator::buildRuntimeInputData():
// Inject __my_internal__ for MyNode nodes.
$nodeTypeId = $metadata["node_type_id"] ?? "";
if ($nodeTypeId === "my_node" && $state->myInternalState !== NULL) {
$runtimeData["__my_internal__"] = $state->myInternalState->toArray();
}
5. Node Type Configuration¶
In the node type configuration: - Show Port: Typically unchecked (internal parameters shouldn't be visible as ports) - Config: Typically unchecked (users shouldn't configure internal parameters) - Required: Typically unchecked (the parameter may be NULL on first execution)
Best Practices¶
-
Don't Expose to Users: Internal parameters are for system use. Keep "Show Port" and "Config" unchecked in node type configuration.
-
Handle NULL Gracefully: Internal parameters may be NULL on first execution or in certain contexts. Always check for NULL before using.
-
Use DTOs: For complex internal state, create a DTO class (like
IteratorState) with proper serialization methods (toArray(),fromArray()). -
Document Thoroughly: Internal parameters can be confusing for developers. Always document their purpose, structure, and injection points.
-
Keep State Minimal: Only include necessary data in internal parameters. Large state objects can impact performance.
Related Files¶
modules/flowdrop_runtime/src/Service/ParameterResolver.php- Handles internal parameter resolutionmodules/flowdrop_stategraph/src/Service/StateGraphOrchestrator.php- Injects internal parametersmodules/flowdrop_stategraph/src/DTO/IteratorState.php- DTO for__iterator__statemodules/flowdrop_stategraph/src/DTO/GraphState.php- Contains iterator state for injection
See Also¶
- FlowDrop Node Processor - Node processor development guide
- Gateway Nodes and Branching - Gateway node system with
branchesandactive_branches