What is a Workflow?
A Workflow is a directed acyclic graph (DAG) of blocks connected by edges. Each block performs a specific action: calling an LLM, running code, evaluating a condition, or executing an agent. Data flows from block to block through the edges. Unlike orchestrations (where the coordinator decides what happens), workflows follow a fixed, predetermined path every time.Block Types
The block registry accepts these canonical types (plus the back-compat aliasesfunction for code and api_call for general_api):
Unknown block types are rejected at
PUT /api/workflows/{id}/graph with 400 Unknown block type.
Graph Execution
When you execute a workflow, the engine evaluates blocks in topological order. Each block receives the outputs of its upstream blocks as input. Condition blocks create branches, and only the matching branch continues execution. The workflow finishes when all output blocks have been reached.Workflow DAG with branching logic
Programmatic vs Copilot
You can build workflows two ways. The programmatic approach uses the PUT /api/workflows/{id}/graph endpoint to define blocks and edges as JSON. The Copilot approach uses natural language: describe what you want, and the AI copilot generates the workflow graph for you. Both produce the same underlying graph structure.Variables and references
Workflow blocks pass data to downstream blocks through theiroutput. To reference an upstream block’s output from another block’s config, use angle-bracket reference syntax:
<Lookup Customer.output.email> is valid.
Two contexts:
- Inside a string (most block configs): every
<blockId.output.field>placeholder gets substituted as a string."Hello <fetch.output.name>!"becomes"Hello Alice!". - Inside a JSON value (e.g.
general_apibody,codeinputs, agent block messages): if the entire string is one reference, the resolved value is returned with its original type (so you can pass a number, array, or object, not just a string)."<extract.output.tags>"returns["foo", "bar"]rather than'["foo", "bar"]'.
<starter.output.variableName>, and you’ll also see the older {{variables.x}} syntax in agent / code block templates. Both work; the angle-bracket form is canonical and applies to every block.
Unresolvable references (block not yet run, missing field) leave the placeholder string as-is so you can see what failed when inspecting block logs.
For condition blocks, the expression evaluator uses a Python-safe AST subset: comparisons, BoolOp (and/or/not), BinOp (+/-/*//), attribute access, and subscripting. Function calls are not permitted.
Scheduling
When a workflow’s starter block hasschedule_enabled: true in its config, deploying the workflow materializes a schedule_config on the workflow row and Celery’s scheduler tick (every 30 seconds) fires runs at the configured cadence.
The starter block’s config takes:
On
/deploy, the platform reads these from the starter block, normalizes them into schedule_config on the workflow row, resets schedule_run_count to 0, and the tick worker picks it up. /undeploy clears schedule_config and stops further scheduled runs.
Scheduled runs execute as if invoked through /execute: the starter block’s variables get whatever default values are configured (no per-run override is possible from the schedule itself).
Deployment & Webhooks
Workflows expose two activation modes for their webhook block:- Deploy (
POST /api/workflows/{id}/deploy) setsstate = "deployed". The webhook accepts unlimited calls until youundeploy. Use this for production. - Arm (
POST /api/workflows/{id}/arm) leavesstate = "internal"but opens a 10-minute window during which the webhook accepts exactly one call. After it fires (or expires), you must arm again. Use this for one-shot tests.
webhook_id and webhook_secret live in the webhook block’s config; they’re stored on the block when you add it to the graph. The studio editor mints both client-side when you drag in a webhook block. Neither /deploy nor /arm returns secrets: /deploy returns {"ok": true, "state": "deployed"} and /arm returns {"ok": true, "armed_until": "<iso8601>"}. To retrieve credentials programmatically, fetch the workflow with GET /api/workflows/{id} and read them from the webhook block’s config.
Next Steps
Workflows (Programmatic)
Build a workflow step by step using the API.
Workflows (Copilot)
Build a workflow using natural language.
Workflows API Reference
Full endpoint documentation.