A Transform node renders a Scriban template against workflow + context variables and the structured upstream input, producing a transformed artifact. It eliminates agent and Logic-script overhead for deterministic data shaping — when the only thing a node needs to do is reshape data, a Transform is cheaper, faster, and easier to read than either an LLM call or a routing script.
Companion references: prompt-templates.md documents the Scriban engine, sandbox, and syntax — Transform nodes use the exact same engine. port-model.md explains the implicit
Failedport. workflows.md explains wherecontext.*andworkflow.*come from.
Transform nodes are distinct from:
- Prompt templates — the system/user prompt fed into an LLM agent.
- Decision-output templates — agent-side rewrites of an artifact after a decision is submitted (see decision-output-templates.md).
- Logic nodes — script-driven routing/transformation when the work cannot be expressed declaratively.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
Transform |
yes | New WorkflowNodeKind value. |
template |
string | yes | Scriban body. Must parse on save. |
outputType |
"string" | "json" |
no | Default "string". When "json", the rendered text is parsed as JSON before becoming the output payload. |
inputScript |
string | null | no | Same setInput slot as Agent/HITL/Subflow/ReviewLoop. Optional — most Transform nodes won't need it. |
outputScript |
string | null | no | Same setOutput slot as Agent/HITL/Subflow/ReviewLoop. Optional. |
Ports:
- One
inport (standard). - One declared output port:
Out. - Implicit
Failed(universal, never declared inoutputPorts).
Agent-related fields (agentKey, agentVersion), subflow fields (subflowKey, subflowVersion), and review-loop fields (reviewMaxRounds, loopDecision) are not populated on Transform nodes.
When the saga reaches a Transform node:
- If
inputScriptis set, run it under existingsetInputsemantics to shape the structured input the template will see. - Build the Scriban scope from workflow variables, context variables, and the structured input. Same sandbox, timeout, and resource caps as prompt-template rendering.
- Render
template. Render error →Failed. - If
outputType === "json", parse the rendered string. Parse error →Failed. - The rendered (and optionally parsed) value becomes the payload on
Out. - If
outputScriptis set, run it under existingsetOutputsemantics before the payload lands onOut.
All errors route through the implicit Failed port. There are no other failure modes the author needs to declare.
| Name | Type | Notes |
|---|---|---|
input.<path> |
nested object | The structured upstream artifact this node consumed (same shape an agent would see). |
context.<path> |
nested object | Workflow-local inputs (saga's local context bag). |
workflow.<path> |
nested object | Workflow-global inputs (propagated across parent/subflow boundaries). |
The Scriban sandbox is identical to prompt templates — no filesystem, no network, no reflection. See prompt-templates.md for the full list of allowed built-ins.
The node config panel reuses:
- Monaco editor with Scriban autocomplete (E3).
- Live preview pane (VZ3) — accepts a sample structured input fixture and shows rendered output. When
outputType === "json", the pane also surfaces parse errors. - An
outputTyperadio toggle (String / JSON).
Validation on save:
templateis required and must Scriban-parse.- If
outputType === "json", the live preview's sample render must JSON-parse — surfaced as an authoring warning, not a save block (the live sample may legitimately differ from runtime data).
| Need | Use |
|---|---|
| Reshape structured data deterministically (rename fields, project subsets, format Markdown/JSON) | Transform |
| Conditional branching across multiple ports based on input shape | Logic |
| Anything requiring reasoning, summarization, or external knowledge | Agent |
A Transform node with outputType: "json" is the canonical replacement for a Logic node whose only purpose was setOutput(JSON.parse(renderedTemplate)).
- Multiple output ports / template-driven port selection.
- Async or streaming rendering.
- Custom Scriban functions beyond what prompt templates already expose.
- File or network I/O from inside templates.