workflows:write on the agent; pausing, resuming, and closing goals and releasing a workspace need workflows:execute; reads need workflows:read. Run routes, recovery, and the error codes are on Workflows, which also holds the base URL, scopes, and envelope pointer.
Verified against lua-cli 3.33.0.
Compose
POST /workflows/:agentId/compose
Validates a dynamic definition and, unlessdryRun, saves it as a draft that POST .../runs can start by composeId. This is what the agent’s own compose tool calls.
string
required
graph or script.object
The graph document, for
form: "graph".string
The script source (at most 256 KB), for
form: "script".any
A sample input to validate against.
string
Save under this name: lowercase kebab-case, at most 64 characters.
boolean
Validate only; write no draft.
string
The originating chat thread, when composed from chat.
200 with the compose result; validation problems are returned in issues[], never as a 4xx. 400 VALIDATION_FAILED for a malformed body; 422 COMPOSE_FORM_FORBIDDEN when the organization allows one form only; 503 CONTROL_UNAVAILABLE.
Schedules
A schedule is a job that starts a workflow on a cadence. Each schedule row is{ jobId, workflowId, trigger: [{ type, expression?, executeAt?, seconds?, timezone?, triggerId? }], status, paused, nextRunAt, lastFiredAt?, consecutiveFailures, autoDisabled?, lastError?, idempotencyKeyTemplate?, goalId? } with status one of active, paused, inactive, completed, missed, and nextRunAt null unless the schedule is live. A schedule that fails on consecutive fires is disabled by the platform and reports autoDisabled { at, consecutiveFailures, lastRunId?, lastReason }.
GET /workflows/:agentId/schedules
Lists the agent’s schedules as{ "items": [...] }.
Equivalent: lua workflows schedules list.
GET /workflows/:agentId/schedules/:jobId
Returns one schedule.404 SCHEDULE_NOT_FOUND, also for a job that is not a workflow schedule.
POST /workflows/:agentId/schedules
Creates a schedule, or replaces the one for the same workflow.string
required
The definition; must be on this agent (
400 WORKFLOW_NOT_ON_AGENT).array
required
From 1 to 5 slots of
{ type: "cron" | "once" | "interval", expression?, executeAt?, seconds?, timezone?, triggerId? }: a 5-field cron expression with an IANA timezone, an ISO 8601 instant, or whole minutes of at least 60 seconds. A sixth slot is 409 SCHEDULE_CAP.string
Display name, at most 120 characters; defaults to the workflow name.
any
The run input on every fire; frozen at create.
object
{ maxCredits?, maxSteps?, maxDurationSeconds? } per run.string
emailApp, email, app, or off.string
Pin a version.
string
Rendered per fire, for example with
{{occurrenceIso}}; at most 128 characters.string
Rendered per fire into the run’s idempotency key from
${input.<path>} and ${scheduledTime} (at most 128 characters); a fire whose key is still held replays that run instead of starting one. Refused with 400 VALIDATION_FAILED when it has no placeholder or does not render against the input.string[]
At most 10 of at most 40 characters.
object
Seeds every run.
object
{ maxOccurrences }: fire missed occurrences when re-enabled.201 with { "jobId", "workflowId", "schedules", "nextRunAt", "notify" }. 400 VALIDATION_FAILED with schedules-required or cadence-invalid at /schedules/<i>/<field>, or WORKFLOW_NOT_ON_AGENT; 404 WORKFLOW_NOT_FOUND; 409 SCHEDULE_CAP; 503 SCHEDULE_PROVISION_FAILED.
Equivalent: lua workflows schedules create <workflow> --cadence '0 9 * * 1' --timezone Europe/London.
PATCH /workflows/:agentId/schedules/:jobId
Pauses or resumes a schedule and sets its backfill options.boolean
false re-enables the schedule.object or null
{ maxOccurrences } to persist; null to clear.boolean
One-shot backfill on this re-enable; needs
paused: false in the same body (400 VALIDATION_FAILED with backfill-now-requires-enable otherwise).string or null
Set or clear the fire-time template; refused on a goal’s cadence job.
200 with { "jobId", "workflowId", "status", "backfillOnEnable"?, "idempotencyKeyTemplate"?, "backfill"? }. 400 VALIDATION_FAILED; 404 SCHEDULE_NOT_FOUND.
Equivalent: lua workflows schedules pause <jobId>, lua workflows schedules resume <jobId> --backfill-now.
DELETE /workflows/:agentId/schedules/:jobId
Deletes a schedule and answers{ "success": true }. 404 SCHEDULE_NOT_FOUND; 409 GOAL_SCHEDULE with goalId for a goal’s cadence, which is stopped by pausing or closing the goal.
Equivalent: lua workflows schedules delete <jobId> --yes.
Goals
A goal runs a workflow repeatedly until a judge says the objective is met, withinmaxRuns and an optional credit cap. A goal is { goalId, orgId, agentId, workflowId, workflowVersionId?, objective, judge, cadence, evaluation, maxRuns, budget?, maxTotalCredits?, initialState?, input?, status, runsUsed, iteration, currentRunId?, lineageId, jobId?, lastRunId?, verdict?, pauseReason?, consecutiveContinues, createdBy, createdAt, updatedAt, doneAt?, closedBy?, closeNote?, note?, raises?, rearmed?, job? } with status one of active, paused, done, closed, and pauseReason one of user, budget, max_runs, strikes.
POST /workflows/:agentId/goals
Creates a goal.string
required
The definition; must be on this agent.
string
required
At most 2,000 characters.
object
required
Either a predicate judge,
{ predicate: { path, op, value? } }, where path is a dotted path (at most 256 characters) into the finished run (output, state, steps.<stepId>, iteration, runStatus) and op is one of eq, neq, gt, gte, lt, lte, exists, truthy; or an agent judge, { agentId, schema, role? }, where agentId is a sub-agent id or $self, schema is a JSON Schema with a boolean done at the root, and role ({ name, instructions, tools }) is required for $self.integer
required
From 1 to 100.
array
At most 5 schedule slots in the schedule grammar; empty means
evaluation.mode: "immediate".object
{ mode: "immediate" | "cadence", delaySeconds? }; delaySeconds only with immediate.object
{ maxCredits?, maxSteps?, maxDurationSeconds? } per iteration.integer
Cap across every iteration; the goal parks when it is met.
object
Seeds every iteration.
any
The run input on every iteration, at most 64 KB.
string
Pin a version.
string
At most 128 characters; a replay answers
200 with the existing goal.201 with the goal. 400 VALIDATION_FAILED (goal-judge-schema-missing-done, goal-predicate-invalid, goal-cadence-invalid, goal-evaluation-invalid, goal-objective-too-long, cadence-invalid), GOAL_MAX_RUNS_INVALID, or WORKFLOW_NOT_ON_AGENT; 409 GOAL_CAP (cap) past the organization’s active-goal cap, 20 by default; 503 CONTROL_UNAVAILABLE.
Equivalent: lua workflows goals create <workflow> --objective "Reach 50 signups" --judge-predicate 'output.signups gte 50', Workflows.setGoal().
GET /workflows/:agentId/goals
Lists goals as{ "items": [...], "nextCursor"? }.
string
active, paused, done, or closed.string
Goals of one definition.
string
Page cursor.
integer
From 1 to 100.
400 BAD_CURSOR or VALIDATION_FAILED.
Equivalent: lua workflows goals list <workflow> --status active, Workflows.goals.list().
GET /workflows/:agentId/goals/:goalId
Returns the goal with its run history,runs: [{ runId, status, iteration?, verdict?, creditsUsed, createdAt, purged? }]. 404 GOAL_NOT_FOUND.
Equivalent: lua workflows goals get <goalId>.
PATCH /workflows/:agentId/goals/:goalId
Edits an active or paused goal:objective, judge, cadence, evaluation (the mode is fixed at create; delaySeconds: null clears the delay), maxRuns, maxTotalCredits (null clears), budget (null clears), note (at most 2,000 characters; null clears), and ifMatch (the updatedAt you read; a mismatch is 409 GOAL_VERSION_CONFLICT with the current updatedAt). Answers the goal, with rearmed: true when the edit cleared a budget or run-count park. 400 VALIDATION_FAILED (an empty edit, or the create-time codes) or GOAL_MAX_RUNS_INVALID; 404 GOAL_NOT_FOUND; 409 GOAL_NOT_ACTIVE on a done or closed goal.
Equivalent: lua workflows goals edit <goalId> --max-credits 500 --every 30m.
POST /workflows/:agentId/goals/:goalId/raise
RaisesmaxTotalCredits or maxRuns, increases only, with an optional note and ifMatch; the same value twice is a 200 no-op, and the raise is recorded in raises[]. 400 GOAL_RAISE_BELOW_SPENT (field, value, spent), VALIDATION_FAILED (nothing to raise, or a value below the current cap), or GOAL_MAX_RUNS_INVALID; 404 GOAL_NOT_FOUND; 409 GOAL_NOT_ACTIVE or GOAL_VERSION_CONFLICT.
Equivalent: lua workflows goals raise <goalId> --max-runs 24.
POST /workflows/:agentId/goals/:goalId/pause
Pauses an active goal;409 GOAL_NOT_ACTIVE otherwise. POST .../resume resumes a paused goal without backfill, and refuses with 409 GOAL_BUDGET_EXHAUSTED (spent, cap) while a credit cap is met. POST .../close closes it for good with an optional note of at most 2,000 characters. Each answers the goal; 404 GOAL_NOT_FOUND.
Equivalent: lua workflows goals pause <goalId>, Workflows.goals.pause(), resume(), close().
Workspaces and Job-tier steps
GET /workflows/:agentId/runs/:runId/workspace
Returns the run’s workspace view,{ runId, kind: "git" | "empty", backend, status, repo?, ref?, credentialsRef?, sizeGb, ttlHours, keepArtefacts?, branch?, baseSha?, headSha?, pushed?, bytesUsed?, filesChanged?, ... }; credentialsRef is an id, never a token. 404 RUN_NOT_FOUND or WORKSPACE_NOT_FOUND.
Equivalent: lua workflows workspace <runId>.
POST /workflows/:agentId/runs/:runId/workspace/release
Releases the workspace early, with an optionalnote (at most 512 characters). Answers { "released": true, "status": "released" | "held" | "expired" } or { "released": false, "reason": "not_provisioned" | "already_released" | "held_empty" }; 404 RUN_NOT_FOUND; 409 WORKSPACE_IN_USE with the stepId still using it; 503 CONTROL_UNAVAILABLE.
Equivalent: lua workflows workspace <runId> --release.
GET /workflows/:agentId/runs/:runId/steps/:stepId/job
Returns a Job-tier step’s view:segment of segmentsTotalMax, checkpoint, pod phase and timings, and a bounded log tail.
integer
One attempt instead of the current one.
integer
default:"200"
Log lines, from 1 to 2,000 (and at most 64 KB).
400 VALIDATION_FAILED for a non-numeric attempt or tail; 404 RUN_NOT_FOUND, JOB_NOT_FOUND, or JOB_LOGS_NOT_PERSISTED for a finished attempt that kept nothing; 503 CONTROL_UNAVAILABLE only for a live attempt.
Equivalent: lua workflows jobs <runId>, lua workflows job-logs <runId> <stepId> --tail 500.
Organization-wide routes
GET /workflows/runs
Lists runs across an organization;workflows:read is checked on the organization.
string
required
The organization. Missing, blank, repeated, or over-long is
400 VALIDATION_FAILED, never 403.string
Narrow to one agent.
GET /workflows/:agentId/runs applies. 403 when the caller holds no workflows:read on that organization; an unknown organization and another organization look the same. The CLI lists runs per agent only, so there is no CLI tab.
GET /workflows/runs/:runId
Returns a run by id alone, for deep links from inbox receipts and notifications; the scope is checked on the run’s agent. Same body asGET /workflows/:agentId/runs/:runId. 404 RUN_NOT_FOUND.
Moving one user’s schedules, approvals, connections, and drafts to another user is POST /workflows/reassign on Workflow approvals.
See also
- Workflows — the run model, run routes, and every error code
- Goals and schedules — when a goal beats a schedule
- Job-tier steps — what a workspace is and how a Job-tier step uses it
lua workflows—schedules,goals,workspace,jobs, andjob-logsWorkflows—setGoal()andgoals.*from agent code

