Skip to main content
Workflows starts runs of a deployed workflow and steers them: read a run, list runs, cancel, resume a suspended step, deliver signals, start batches, raise a parked run’s budget, and manage goals. Every member returns as soon as the platform accepts the call; none waits for a run to finish. Available in tools, jobs, webhooks, triggers, processors, and workflow code steps. From a code step, start() creates a detached run; to wait on a nested run, use the workflow() step of the workflow builder. Verified against lua-cli 3.33.0.

Quick example

Methods

start()

Starts a run and returns its id and status.
string
required
The workflow’s name on this agent, resolved first, or a workflow id.
unknown
The run’s input, validated against the workflow’s input schema. The REST route that lua test calls refuses JSON over 256 KB; deployed agents don’t apply that cap.
string
A second start() with the same key returns the existing run with idempotentReplay: true and deduplicated: true instead of creating another.
{ maxCredits?: number; maxSteps?: number; maxDurationSeconds?: number }
Caps for this run. A run that reaches a cap parks with nextAction: 'raise_budget'.
number
From 0 to 55. The platform holds the request for up to this long; when the run reaches a terminal or suspended state inside the window, the result is the run detail with output, otherwise the accepted { runId, status }. The execution model is unchanged either way.
Record<string, unknown>
Seed for the run’s state.
string
A key of your own that signalByKey() can address the run by.
string[]
Labels for list({ tags }).
{ channel: string; threadId: string }
Where the run’s replies go.
{ userId: string }
The end user the run acts for.
string
Pins a version. Defaults to the active version.
Returns
StartWorkflowRunResult
The accepted run.
Example
ErrorsRUNS_IN_FLIGHT when the workflow’s concurrencyPolicy is forbid and a run is in flight (under lua test the error carries blockingRunId); WORKFLOW_NOT_FOUND; PAYLOAD_TOO_LARGE (413) under lua test when input exceeds 256 KB; CONTROL_UNAVAILABLE (503) while the control plane is unavailable; waitSeconds must be 0..55 (got <n>) before any request is made.
Local runs only. In deployed agents start forwards only idempotencyKey, budget, correlationKey, tags, and workflowVersionId and resolves { runId, status }; see Deployed runtime differences for get, list, and cancel.

get()

Returns one run’s summary.
Returns — a WorkflowRun summary. hasOutput and a 2 KB outputPreview are included; output itself is not. A run whose outputs you may not read comes back with restricted: true and no output, never as an error. Read a run’s steps and full output with lua workflows. Example
ErrorsRUN_NOT_FOUND.

list()

Returns run summaries, optionally filtered.
number
Maximum number of runs.
WorkflowRunStatus
Only runs in this status.
string
Only runs of this workflow, by name or id.
string
Only runs started with this key.
string[]
Only runs carrying these tags.
string
Sort order accepted by the platform.
Returns — an array of WorkflowRun summaries, with the same output rules as get(). Example
Errors — none beyond platform refusals.

cancel()

Requests or forces a cancellation.
'request' | 'force'
default:"request"
request asks the run to stop at its next checkpoint; force abandons it once forceAvailableAt has passed.
string
Recorded on the run.
Returns
CancelRunVerdict
What the cancellation did. A force before forceAvailableAt returns transitioned: false with nextAction: 'cancel_again' and the time; a run that is already terminal answers state: 'terminal'. Neither is an error.
Example
ErrorsRUN_NOT_FOUND.

resume()

Resumes a suspended step with the data it is waiting for.
string
required
The run.
string
required
The suspended step’s id.
unknown
required
Validated against the step’s resume schema.
Returns{ resumed: true, runStatus }, or { resumed: false, reason: 'already_resumed', recorded: { at, by? }, runStatus } when another caller resumed the step first. The loser of the race gets the recorded outcome, never an error. Example
ErrorsRUN_NOT_FOUND, STEP_NOT_FOUND.

signal()

Delivers a named signal to a run.
string
required
The signal name a waitForSignal step listens for.
unknown
Delivered to the step.
string
A repeated key returns duplicate: true instead of delivering twice.
Returns
SignalRunResult
Example
ErrorsRUN_NOT_FOUND.

signalByKey()

Delivers a signal to the live run that carries a correlation key.
string
required
The workflow, by name or id.
string
required
The key the run was started with.
string
required
The signal name.
boolean
Deliver to every live run with the key. Without it, more than one match is an error.
Returns{ runIds, delivered }. At run time the object also carries a results array with one { runId, accepted, consumed?, duplicate?, signalId?, code? } per run; it isn’t in the typings. Example
ErrorsWORKFLOW_NOT_FOUND, CORRELATION_KEY_NOT_FOUND, CORRELATION_KEY_AMBIGUOUS (several live runs carry the key and allowMultiple is not set).

startBatch()

Starts up to 200 runs of one workflow in a single call.
array
required
One entry per run, up to 200; idempotencyKey is required on each. A malformed item refuses the whole batch.
'reject' | 'gate'
default:"gate"
What happens to runs that don’t get a slot: gate parks them, reject refuses them.
object
A budget applied to each run that has none of its own.
ReturnsbatchId, the number accepted, and one item per input with its runId and status (queued, gated, replayed for an idempotency match, or rejected with a code). Example
ErrorsWORKFLOW_NOT_FOUND, BATCH_ITEM_INVALID, BATCH_TOO_LARGE (400) past 200 items, RUNS_IN_FLIGHT (the whole batch is refused).

raiseBudget()

Raises the caps of a parked run so it can continue. Increases only.
Returns{ raised: true, budget, runStatus, resumed }, or { raised: false, reason: 'already_raised' } when another caller raised it first. Example
ErrorsVALIDATION_FAILED and CAP_EXCEEDED (400), NOT_RUN_CREATOR (403), BUDGET_NOT_RAISABLE (409).
No runtime serves this member in lua-cli 3.33.0: lua test throws WorkflowApiError with code WORKFLOWS_API_UNAVAILABLE, and deployed agents throw WorkflowsApiError with code not_implemented (501). Raise a budget with lua workflows raise-budget instead.

setGoal()

Creates a goal: the platform runs the workflow repeatedly until a judge decides the objective is met.
string
required
The id of the agent the code runs in. Goals are scoped to that agent; any other id is refused with FORBIDDEN.
object
required
workflowId or workflow (a name), objective, judge, and maxRuns, plus optional cadence, evaluation, budget, maxTotalCredits, initialState, input, idempotencyKey, and workflowVersionId. The judge is { agentId?, role?: { name, instructions, tools }, schema?, predicate?: { path, op, value? } }.
Returns — the goal record: goalId, status (active, paused, done, or closed), runsUsed, iteration, currentRunId, verdict, pauseReason, and the fields you set. Typed loosely as Record<string, unknown>. Example
ErrorsFORBIDDEN (403) for another agent’s id, VALIDATION_FAILED, GOAL_MAX_RUNS_INVALID, GOAL_CAP.

goals

Reads and controls goals. Every member takes the bound agent’s id first and refuses any other id with FORBIDDEN.
Returns — goal records as setGoal(); get() adds the goal’s runs history. pause() needs an active goal, resume() a paused one, and close() is terminal. Example
ErrorsFORBIDDEN, GOAL_NOT_FOUND, GOAL_NOT_ACTIVE.

Deployed runtime differences

Under lua test every member calls the platform’s REST routes and returns the typed shapes documented earlier. In deployed agents the members are served in process, and several return less than the typings declare.
  • start() forwards idempotencyKey, budget, workflowVersionId, correlationKey (up to 200 characters), and tags (up to 10, each up to 64 characters). It drops waitSeconds, initialState, replyTo, and onBehalfOf, skips the 256 KB input check, and resolves { runId, status }, with status failed when the run was recorded but could not start, for example because input failed the workflow’s input schema.
  • get() resolves runId, workflowId, workflowVersionId, status, trigger, createdAt, and, when set, startedAt, completedAt, durationMs, gate, reason, output, and error. There is no nextAction, budget, outputPreview, or restricted.
  • list() filters by status and an untyped workflowId only; workflow, correlationKey, tags, and sort are ignored. limit is clamped to 1 to 200 and defaults to 50.
  • cancel() resolves { status, nextAction, forceAvailableAt? }.
  • resume() throws code resume_unavailable (501) on a platform without the resume handler.
  • signal() and signalByKey() throw code signal_unavailable (501) on a platform without the signal handler. When served, signal() resolves { accepted, reason? } and signalByKey() resolves { runIds, delivered } with no results array; a delivery the platform refuses comes back as { accepted: false, reason }, not as an error.
  • startBatch(), setGoal(), and goals.* throw code not_implemented (501) when the platform’s optional batch or goal provider is absent, so handle that error. startBatch() also resolves nameOrId as a workflow id only, never a name.
  • raiseBudget() always throws code not_implemented (501). Raise a budget with lua workflows raise-budget or the POST /workflows/:agentId/runs/:runId/budget route instead.

Errors

A refusal throws an Error with a code (the platform’s discriminator, as listed per method) and a statusCode. Under lua test the error’s name is WorkflowApiError and it carries the detail fields the platform sent, such as blockingRunId. In deployed agents the name is WorkflowsApiError; detail fields are attached only when the platform’s refusal carried them (startBatch and goals), so a RUNS_IN_FLIGHT from start has no blockingRunId. Neither class is exported; branch on code.
A runtime without workflow support throws Workflows API is not available in this runtime with code workflows_unavailable.

Types

Workflows, WorkflowsApi, and WorkflowRunTrigger are exported. The result shapes are not; name them from the method that returns them.

WorkflowRunStatus

queued, running, cancellation_requested, gated, suspended, waiting, completed, failed, cancelled, abandoned, or timed_out.

WorkflowRun

string
The run’s id; older responses spell it id.
string
Where the run belongs.
WorkflowRunStatus
Current status.
WorkflowRunTrigger
chat, sdk, api, schedule, webhook, template, workflow, or device.
string | string[]
Optional identity you or a parent run gave it.
{ kind: string; reason?: string; code?: string; stepId?: string; expiresAt?: number }
Why a gated run holds no slot.
'cancel_again' | 'force' | 'none' | 'raise_budget' | 'top_up'
What the platform suggests next.
{ requestedAt: number; requestedBy: string; forceAvailableAt: number; forcedAt?: number; forcedBy?: string; forceReason?: string }
The pending or applied cancellation.
string
Why a failed run failed.
boolean
true when outputs are withheld from the caller.
boolean | string | unknown
Whether a result exists, its 2 KB preview, and the full value when the view includes it.
{ creditsUsed?: number; actionsUsed?: number; steps?: number; inputTokens?: number; outputTokens?: number; metering?: 'flat' | 'priced' }
Settled spend.
{ maxCredits?: number; maxSteps?: number; maxDurationSeconds?: number; spent?: object; remaining?: number }
Caps and remaining allowance.
string
ISO 8601 timestamps.

See also