When a workflow beats an agent
- The sequence must not vary. Fetch, compute, write — always in that order, never skipping the check in the middle.
- The computation must be exact. Sums, groupings and date arithmetic belong in code, not in a model’s head.
- Nobody is there to steer. Scheduled and unattended runs need a deterministic path; see User workflows and schedules for the end-user variant.
The shape of a definition
A workflow is a JSON document with three parts:steps, a map of named
steps; flow, the ordered list of operators that run them; and an optional
output_text template for the result message.
GET /v1/workflows/definition-schema returns the full JSON Schema, with a
definition per step kind, if you generate or validate definitions in your own
tooling.
Step kinds
Agent steps are self-contained. The model, its settings (temperature,
reasoning effort) and its instructions live on the step. An agent step does
not reference one of your saved agents, so editing an agent can never change
what a workflow does, and none of a saved agent’s memory, tools or sub-agents
apply. Give it an
output_schema and the step returns the parsed object
directly; without one it returns { text, object, raw }.
Tool steps reference tools by stable id, not by name — a renamed tool or
provider keeps working. A tool step can carry a loop block to walk every
page, fan out over a list of values and project fields, exactly as an agent
with loop_responses would; see Working with large APIs.
Code steps run in a worker with a blank environment: standard ECMAScript
globals plus console, and nothing else — no fetch, require, process,
filesystem or timers. Use a tool step to reach anything outside. The code
receives its input mapping as input, may use await, and must return a
JSON-serialisable value, which becomes $.steps.<id> with no envelope. The
default timeout is five seconds, the ceiling thirty. In the Studio, the keys
of every return { … } literal feed the reference autocomplete for later
steps, so a step that returns { sum, count } offers $.steps.total.sum to
whatever comes next.
Flow operators
flow is a list of operators. Each references steps by id.
Conditions use a small expression language —
eq, ne, gt, gte, lt,
lte, truthy, not, and, or — over the same references as everything
else, so a branch can gate on $.steps.fetch._loop.complete or on a code
step’s result.
Control-flow positions reference a single step. To nest a sequence inside a
branch or a loop, put the sequence in its own workflow and reference it with
a workflow step.
Parallel steps
In the Studio aparallel operator is a gate node: the previous operator
attaches to the gate, members fan out from it, and the next operator fans in
from all of them. Fill it three ways — drop a step from the palette onto the
gate, connect an existing step node to it, or add members from the gate’s
config panel. Later steps read each member’s result at $.steps.<name> as
usual.
Wiring data
Every reference is a path rooted at$:
Index arrays with numeric brackets —
$.steps.fetch.items[0].id. In a step’s
input, mapping or condition, write a reference as { "ref": "$.…" }; in an
agent step’s prompt and in output_text, embed it as {{ $.… }}.
Non-string values render as JSON and an unresolved reference renders as an
empty string.
In the Studio, references are picked from a tree rather than typed, and
display without the $. prefix (steps.fetch.items[0].id); the prefix is
added back when the draft is saved. Renaming a step rewrites every
reference to it — in inputs, conditions and prompt templates — so ids are
safe to change as a workflow grows.
Publishing checks the wiring: a reference to a step that runs later, or to a
step that does not exist, is rejected with the offending path named.
Running one
There are three ways:- From the Studio. The run panel renders a form from
input_schema(or a JSON editor when there is none) and streams the run onto the canvas — each node shows its status live. When a step misbehaves, the first thing to open is Input from last run under that step’s configuration, which shows exactly what the step received. - From the API.
POST /v1/workflows/{id}/runwithinput. Add"stream": truefor server-sent events — one event per step start and result, ending inrun-completeorrun-error— or"notify_thread": trueto file the result as a conversation the user can read and reply to. Select a version with?version=active|draft|v3. - As a tool an agent calls. See Giving an agent a workflow.
text is the rendered output_text. A run of the draft is validated first
and rejected with the issues listed if the draft is not runnable; a failed
run answers 500 with the step error.
Lifecycle
Workflows use the same draft → publish → activate model as agents. Saving a draft only checks structure, so half-built graphs save fine. Publishing runs the full validation — unknown or forward references, orphan steps, cycles, code that does not compile — and then does a trial build without running anything. Activating picks which published version serves. See Versions, environments and deploying.output_text is the message posted after a successful run: a template over
$.input and $.steps, up to 4,000 characters, which may contain
<component id="<stepId>"/> anchors for rich-UI steps. Without it the result
message is a fixed completion notice with the output attached as JSON. Set
it through the API or the draft editor; it is what a user reads in a result
thread.
Credentials and billing
A run carries the calling user’s stored tool credentials — the same store a token mint orPATCH /v1/users/{userId} writes — and they reach both HTTP
and MCP tool steps. There is no fallback to the organization’s credentials:
a step whose provider the user has no access to fails, rather than quietly
running as someone else. With the organization API key a runtimeAuth map
in the request body wins over the store, which is how a server-side
integration runs a workflow on a user’s behalf.
Every run is one trace, billed to the group named on the request (or the
user’s group), gated by the same usage limits as chat, and enriched after the
fact with cost and participants — the tools and agent steps that ran. See
Traces, cost and billing groups.