Skip to main content

Graph Format

A workflow is stored as two JSON arrays: nodes and edges. This format is compatible with React Flow and is what you send to the API when creating or running a workflow.

Node Schema

{
"id": "fetchEntries",
"type": "get_entries",
"data": {
"label": "Fetch Entries",
"isExecuted": false,
"handles": ["outputs"],
"schema": {},
"params": {
"datasetId": {
"value": 42,
"isExpression": false,
"isAttachedToInputNode": false
},
"numberOfEntries": {
"value": "{{ $input.limit }}",
"isExpression": true,
"isAttachedToInputNode": false
}
},
"inputs": [],
"outputs": [],
"errors": []
},
"position": { "x": 0, "y": 0 },
"isSelected": false,
"isDragging": false
}

Node Fields

FieldTypeDescription
idstringUnique identifier for this node within the workflow. Used to reference the node's output in template expressions
typestringThe node type — see Node Types
data.labelstringDisplay name shown in the UI
data.isInputboolean?Marks this as a group input boundary node
data.isOutputboolean?Marks this as a group output boundary node
data.isToolboolean?Marks this node as an agent tool
data.isExecutedbooleanSet to true by the worker after execution
data.handlesstring[]Active connection handles — see handle types below
data.schema.inputJSONSchema7?Expected input schema for this node type
data.schema.outputJSONSchema7?Produced output schema for this node type
data.paramsobjectNode parameters — each key maps to a param object
data.params[key].valueanyThe parameter value. May contain template expressions
data.params[key].isExpressionbooleanSet to true if value contains a {{ ... }} expression
data.params[key].isAttachedToInputNodebooleanSet by the UI when a param is wired to an input handle
data.inputsarrayPopulated by the worker with runtime inputs after execution
data.outputsarrayPopulated by the worker with runtime outputs after execution
data.errorsarrayPopulated by the worker if the node fails: [{ message, code? }]
positionobject{ x, y } canvas coordinates — used by the UI, ignored by the worker
measuredobject?{ width?, height? } canvas rendering hints — ignored by the worker
isSelectedbooleanUI state — ignored by the worker
isDraggingbooleanUI state — ignored by the worker
note

Before a job is sent to the workers, the platform strips the NodeDataParam wrappers. Workers receive params as a plain Record<string, any> where each key maps directly to its value.

Edge Schema

{
"id": "edge_fetchEntries_to_search",
"source": "fetchEntries",
"sourceHandle": "outputs",
"target": "vectorSearch",
"targetHandle": "inputs"
}

Edge Fields

FieldTypeDescription
idstringUnique identifier for this edge
sourcestringNode id of the source node
sourceHandlestringThe handle on the source node — one of inputs, outputs, tools, agents
targetstringNode id of the target node
targetHandlestringThe handle on the target node — one of inputs, outputs, tool, agent

Handle Types

Handles determine both the visual connection points in the UI and the execution semantics in the worker.

sourceHandletargetHandleMeaning
outputsinputsFlow edge — data flows from source to target. The worker uses these edges to compute execution order via topological sort
toolstoolTool edge — connects an agent node to a tool node. Does not affect execution order
agentsagentAgent edge — connects a deep agent to a sub-agent. Does not affect execution order

Complete Example

A two-node workflow that fetches entries and runs a vector search:

{
"nodes": [
{
"id": "fetchEntries",
"type": "get_entries",
"data": {
"label": "Fetch Entries",
"isExecuted": false,
"handles": ["outputs"],
"schema": {},
"params": {
"datasetId": {
"value": 5,
"isExpression": false,
"isAttachedToInputNode": false
},
"numberOfEntries": {
"value": 20,
"isExpression": false,
"isAttachedToInputNode": false
}
},
"inputs": [],
"outputs": [],
"errors": []
},
"position": { "x": 0, "y": 0 },
"isSelected": false,
"isDragging": false
},
{
"id": "vectorSearch",
"type": "vector_search",
"data": {
"label": "Vector Search",
"isExecuted": false,
"handles": ["inputs", "outputs"],
"schema": {},
"params": {
"query": {
"value": "{{ $input.query }}",
"isExpression": true,
"isAttachedToInputNode": false
},
"collectionName": {
"value": "{{ @fetchEntries.collection }}",
"isExpression": true,
"isAttachedToInputNode": false
},
"topK": {
"value": 5,
"isExpression": false,
"isAttachedToInputNode": false
}
},
"inputs": [],
"outputs": [],
"errors": []
},
"position": { "x": 350, "y": 0 },
"isSelected": false,
"isDragging": false
}
],
"edges": [
{
"id": "e1",
"source": "fetchEntries",
"sourceHandle": "outputs",
"target": "vectorSearch",
"targetHandle": "inputs"
}
]
}

Group Nodes

A group node encapsulates a nested sub-workflow. Its data.workflow field contains a full nodes and edges structure. At execution time the worker dissolves the group in-place, replacing it with its inner nodes and rewiring all edges transparently. group_input and group_output nodes mark the boundaries of the nested graph.

{
"id": "myGroup",
"type": "group",
"data": {
"label": "My Sub-Workflow",
"isExecuted": false,
"handles": ["inputs", "outputs"],
"schema": {},
"params": {},
"inputs": [],
"outputs": [],
"errors": [],
"workflow": {
"nodes": [
{ "id": "groupIn", "type": "group_input", ... },
{ "id": "innerNode", "type": "chat_completion", ... },
{ "id": "groupOut", "type": "group_output", ... }
],
"edges": [
{ "id": "e1", "source": "groupIn", "sourceHandle": "outputs", "target": "innerNode", "targetHandle": "inputs" },
{ "id": "e2", "source": "innerNode", "sourceHandle": "outputs", "target": "groupOut", "targetHandle": "inputs" }
]
}
},
"position": { "x": 0, "y": 0 },
"isSelected": false,
"isDragging": false
}