Workflows
Technical reference for workflow nodes, retry policies, execution lifecycle, versioning, scheduling, and AI configuration
A workflow connects a Gmail trigger to an AI analysis step, routes the result through a condition branch, pauses for your approval if confidence is below 90%, and sends a follow-up email. Each piece -- the trigger, the AI call, the condition, the approval, the email -- is a node on a visual canvas. You wire nodes together, configure each one, and Rills handles execution, retries, and version management.
Node types
Workflows are built from 8 node types. Every workflow starts with an entry node and ends when execution reaches a terminal node with no outgoing connections.
| Node | Purpose |
|---|---|
| Entry | Starts the workflow. Requires at least one trigger: manual (user action or API call), webhook (HTTP request to a URL with optional HMAC or API key authentication), or schedule (cron expression with timezone). A single entry node can have multiple triggers. |
| Action | Executes operations. Two sources: builtin actions (http_request, send_email, custom_code, transform, filter_array, set_variable) and integration actions that call third-party APIs through the integration catalog. Custom code runs JavaScript or Python in a sandbox. Supports inline retry policies. |
| Condition | Branches execution based on rules. Each branch evaluates a field against an operator: equals, not_equals, greater_than, less_than, greater_equal, less_equal, contains, not_contains, starts_with, ends_with, is_empty, is_not_empty. Minimum 2 branches required. Includes a default/else branch for unmatched cases. |
| Loop | Iterates over a collection. Configure the items expression, item/index variable names, optional max iterations cap, and concurrency level (default 1, increase for parallel iteration). |
| AI | Calls an AI model with a prompt. Configurable model, temperature, max tokens, output schema, and approval mode. See AI model configuration below. Supports inline retry policies. |
| Human | Pauses for human input. Three approval types: approve_reject, multi_choice (custom labeled options with optional colors), and freeform (open text input). Configurable priority (low, normal, high, urgent) for mobile queue ordering. Optional timeout with configurable action on expiry (approve, reject, escalate, fail). |
| Wait | Pauses execution. Two modes: duration (e.g., "30 seconds", "2 hours") or until (specific ISO datetime or expression, with timezone support). Maps to durable sleep -- paused workflows cost nothing. |
| Merge (preview) | Joins parallel branches. Waits for all incoming connections before processing. Four modes: append (concatenate into array), combine (cartesian product), zip (pair by index), merge_fields (merge object keys with configurable conflict resolution: first_wins, last_wins, array, error). Optional timeout if not all inputs arrive. The merge node has schema and UI support, but execution engine support is not yet complete -- workflows using merge nodes may not execute the merge step as expected. |
Custom code execution
Custom code actions run JavaScript or Python in a sandboxed environment:
| Parameter | Value |
|---|---|
| Runtimes | Node 24 (JavaScript), Python 3.13 |
| Code size | 50 KB maximum |
| Timeout | 1--300 seconds (configurable per node) |
| Environment | Vercel Sandbox (isolated execution) |
Environment variables can be configured per action node as key-value pairs. Output from the code block is captured and passed to the next node in the workflow.
Condition operators
Each condition branch evaluates a field against one of these operators:
| Operator | Description |
|---|---|
equals | Exact match |
not_equals | Not an exact match |
greater_than | Numerically greater |
less_than | Numerically less |
greater_equal | Greater than or equal |
less_equal | Less than or equal |
contains | String or array contains value |
not_contains | String or array does not contain |
starts_with | String starts with value |
ends_with | String ends with value |
is_empty | Value is null, undefined, or empty string |
is_not_empty | Value exists and is not empty |
Conditions require a minimum of 2 branches. A default (else) branch executes when no explicit condition matches.
Loop configuration
| Parameter | Default | Description |
|---|---|---|
itemsExpression | -- | Data source expression referencing an array from a previous step |
itemVariable | item | Variable name for the current item inside the loop body |
indexVariable | index | Variable name for the current iteration index |
maxIterations | -- | Safety cap to prevent runaway loops (optional) |
concurrency | 1 | Iterations to run in parallel. 1 = sequential execution. |
Wait node types
| Mode | Configuration |
|---|---|
duration | Pause for a fixed delay (e.g., "30 seconds", "2 hours") |
until | Pause until a specific ISO datetime or expression, with timezone support (defaults to UTC) |
Both modes map to durable sleep. Paused workflows consume no compute resources.
Human node configuration
Three approval types:
| Type | Behavior |
|---|---|
approve_reject | Binary yes/no decision |
multi_choice | Choose from predefined options (label, value, optional color) |
freeform | Free text input |
Each human node supports:
| Parameter | Options | Description |
|---|---|---|
timeoutSeconds | Positive integer | Per-node timeout, separate from the workflow-level approval timeout |
timeoutAction | approve, reject, escalate, fail | What happens if nobody responds before the timeout |
contextFields | Array of strings | Which fields the reviewer sees alongside the proposal |
priority | low, normal, high, urgent | Affects mobile queue ordering and notification urgency |
Webhook triggers
Entry nodes support multiple triggers on the same workflow -- manual, webhook, and schedule can all be active simultaneously.
Webhook authentication options:
| Type | How it works |
|---|---|
none | No authentication. Accepts any request to the webhook URL. |
api_key | Requires a header (default: X-API-Key) with a matching value. |
hmac | Validates a signature header (default: X-Hub-Signature-256) using SHA-256, SHA-1, or SHA-512. Signature format: sha256=<hex_digest> (GitHub-compatible). |
Idempotency: Configure which request header carries the idempotency key (idempotencyHeader). Duplicate webhook deliveries with the same key are ignored for 24 hours (configurable via idempotencyTtlSeconds, default 86,400).
Event filtering: Set eventTypeField (e.g., $.type) and acceptedEventTypes (e.g., ["push", "pull_request"]) to process only specific event types from the webhook payload.
Retry and error handling
Action and AI nodes support inline retry policies. When a step fails with a retryable error, the retry policy controls how many times and how quickly Rills retries before marking the step as failed.
| Parameter | Range | Default | Description |
|---|---|---|---|
maxRetries | 1 -- 10 | 3 | Number of retry attempts. The retry policy only exists when retries are enabled -- if disabled, the field is omitted entirely. |
retryStrategy | fixed, exponential | exponential | Fixed uses constant delay. Exponential increases delay with each attempt. |
retryDelayMs | 100 -- 60,000 ms | 1,000 ms | Base delay between retries. |
backoffMultiplier | 1 -- 3 | 2 | Multiplier applied per attempt for exponential strategy. |
maxDelayMs | 1,000 -- 300,000 ms | 60,000 ms | Ceiling on delay for exponential backoff. |
retryableStatusCodes | HTTP status codes | 408, 429, 500, 502, 503, 504 | Which HTTP responses trigger a retry. |
The exponential formula: delay = min(maxDelayMs, retryDelayMs * backoffMultiplier ^ attempt). Runtime jitter is added to prevent thundering herd.
Retry delay calculation
With the defaults (exponential strategy, 1,000 ms base, 2x multiplier, 60,000 ms cap):
| Attempt | Delay |
|---|---|
| 1 | 1 s |
| 2 | 2 s |
| 3 | 4 s |
| 4 | 8 s |
| 5 | 16 s |
| 6+ | 32 s, then capped at 60 s |
With fixed strategy, every retry waits retryDelayMs regardless of attempt number.
When retries are exhausted, the step fails with an errorCode and errorMessage recorded for debugging.
Execution lifecycle
Workflow statuses
A workflow itself has one of three statuses:
active-- Running normally, triggers fire and create executions.paused-- Manually paused by a user. No new executions are created.paused_credits_exhausted-- Automatically paused because the workspace ran out of action credits. Resumes when credits are replenished.
Execution statuses
Each execution (a single run of a workflow) progresses through these statuses:
pending-- Execution created, waiting to start.running-- Steps are executing.success-- All steps completed successfully.failed-- A step failed after retries were exhausted.paused_quota-- Execution paused mid-run because the workspace ran out of credits. Resumes automatically when credits are replenished.paused_billing_lapse-- Execution paused because the workspace subscription lapsed. Resumes when the subscription is restored.
Typical flow: trigger fires, execution is created as pending, moves to running as steps execute, and reaches a terminal state (success, failed, or one of the paused states).
Each execution carries an idempotency key to prevent duplicate runs from the same trigger event.
Paused execution states
Two pause states are automatic and require no manual intervention to resume:
| Status | Cause | Resume trigger |
|---|---|---|
paused_quota | Workspace exhausted included credits mid-run | Credits replenish (next billing cycle or spending cap raise) |
paused_billing_lapse | Subscription payment failed and grace period expired | Payment is resolved |
Both states preserve the execution's position. When the underlying issue is resolved, the execution resumes from where it paused -- no data is lost and no steps are re-run.
Versioning
Workflows use immutable version snapshots. When you save changes to a workflow, a new version is created containing the complete workflow definition -- all nodes, edges, and configuration.
Running executions continue on the version they started with. You can edit a workflow while executions are in progress without affecting them. This means deploys are safe: no in-flight execution will see a half-updated definition.
Each execution record references the specific workflow_version_id it ran against, so you can always trace which version produced a given result.
Scheduling
Workflows can run on cron schedules with timezone support. Configure a cron expression (validated at save time) and a timezone (defaults to UTC).
The scheduler tracks consecutive failures per schedule. If a scheduled workflow fails repeatedly, the failure count and last error are recorded for monitoring. Schedules use optimistic locking (lockVersion, lockedBy, lockedAt) to prevent duplicate triggers when multiple scheduler instances run concurrently.
Schedules can be enabled or disabled independently of the workflow status. A disabled schedule stops firing without pausing the workflow itself -- manual and webhook triggers still work.
Schedule failure handling
The schedule tracks two diagnostic fields:
consecutiveFailures-- Counter of sequential schedule-triggered execution failures. Resets to 0 on the next successful run.lastError-- The most recent error message from a failed scheduled execution.
The schedule continues to fire after failures -- it does not automatically disable. Monitor consecutiveFailures to identify workflows that need attention.
AI model configuration
AI nodes call a language model with a prompt and optional output schema. Available models:
| Model ID | Provider |
|---|---|
claude-opus-4 | Anthropic |
claude-3-5-sonnet | Anthropic |
claude-3-haiku | Anthropic |
gpt-4-turbo | OpenAI |
gpt-4 | OpenAI |
gpt-3.5-turbo | OpenAI |
The available models may change as new models are released. The workflow builder's model dropdown always shows the current list.
Configuration per AI node:
| Parameter | Range | Default | Description |
|---|---|---|---|
temperature | 0 -- 2 | 0.7 | Lower values produce more deterministic output. Higher values increase variation. |
maxTokens | 1 -- 4,096 | 1,024 | Maximum response length in tokens. |
approvalMode | always, confidence, never | confidence | always pauses for human approval on every run. confidence pauses only when the model's confidence score falls below the threshold. never auto-approves everything. |
confidenceThreshold | 0 -- 100 | 90 | Percentage threshold for confidence-based approval. Only applies when approvalMode is confidence. |
samplingRate | 0 -- 100 | -- | Percentage of auto-approved actions sent for human spot-check. Useful for ongoing quality monitoring without blocking execution. |
The default approval timeout across the workspace is 24 hours (1,440 minutes), configurable per workflow.
Execution history
View past workflow runs at the workspace level (all workflows) or filtered to a single workflow.
Each execution in the list shows:
- Status --
succeeded,failed,pending,running, or one of the paused states - Trigger type -- Which trigger started the run (manual, webhook, or schedule)
- Start and end time -- When the run started and finished
- Duration -- Total wall-clock time from start to completion
Click into an execution to see step-by-step details: what data each step received, what it produced, and any errors. Failed executions highlight which step failed and display the error message, so you can diagnose issues without digging through raw logs.
Execution history is available at:
- Workspace level -- All executions across all workflows in the workspace
- Per workflow -- Executions for a specific workflow, accessible from the workflow detail page
Execution logs
Each workflow execution records step-level data for debugging and auditing:
Per step:
inputData-- The data the step received.outputData-- The data the step produced.status-- Step outcome:pending,running,success, orfailed.errorCodeanderrorMessage-- Populated when a step fails.
Execution events:
A timestamped event stream for the entire run. Each event has a type, category, and data payload. Events capture lifecycle transitions, approval decisions, retry attempts, and other execution details.
Data retention depends on your plan -- see billing for details.
Per-workflow data retention
Each workflow can override the workspace's default retention period with dataRetentionDays. This affects execution data only -- logs, step input/output, and events. The workflow definition itself is retained indefinitely.
Use shorter retention on high-volume workflows to manage storage. Use longer retention on workflows processing data that requires an audit trail.
To build your first workflow step by step, start with the workflow tutorial. Approval configuration and confidence scoring are covered in the approvals reference. For connecting third-party services, see integrations.