Coasty/

Developer API

Workflows

Steps, structured conditions, and variable refs

Workflow DSL

Workflow DSL, at a glance

Steps, structured conditions, and variable refs

definition.steps[]
The DSL passes typed inputs through task, branch, loop, parallel, assertion, approval, and terminal steps without arbitrary code execution.

The DSL (dsl_version 2026-06-01) is a JSON object with a steps array and an optional output. Each step has an id and a type. A task step runs the agent and binds its result ({ status, passed, result, run_id, steps, error }) under both its save_as name and its step id, so later steps can read it.

JSON
{
  "dsl_version": "2026-06-01",
  "definition": {
    "steps": [
      {
        "id": "fetch",
        "type": "task",
        "task": "Open order {{inputs.order_id}} and read the invoice total",
        "save_as": "invoice"
      },
      {
        "id": "check",
        "type": "assert",
        "condition": {
          "op": "truthy",
          "value": "{{invoice.passed}}"
        },
        "message": "Agent failed to read the invoice"
      },
      {
        "id": "branch",
        "type": "if",
        "condition": {
          "op": "contains",
          "left": "{{invoice.result}}",
          "right": "PAID"
        },
        "then": [
          {
            "id": "ok",
            "type": "succeed",
            "output": {
              "state": "paid"
            }
          }
        ],
        "else": [
          {
            "id": "no",
            "type": "fail",
            "message": "Invoice not marked paid"
          }
        ]
      }
    ],
    "output": {
      "paid": "{{invoice.result}}"
    }
  }
}
Step typeShapeDescription
task{ task, machine_id?, save_as? }Run an agent task. Supports {{var}} templating. Binds its result under save_as and the step id.
assert{ condition, message? }Fail the workflow unless the structured condition holds.
if{ condition, then, else? }Branch on a structured condition.
loop{ count | while, body }Repeat a body a fixed number of times or while a condition holds.
parallel{ branches: [[...], [...]] }Run independent branches concurrently.
human_approval{ message?, timeout_seconds? }Pause for a human to approve or reject before continuing.
retry{ body, max_attempts }Retry a body up to max_attempts times on failure.
succeed{ output? }Finish the workflow successfully with an optional output.
fail{ message? }Finish the workflow as failed with an optional message.

Conditions are structured rather than expression strings, which keeps them injection-safe. Each left, right, or value is either a literal or a {{path}} reference. Paths are dotted lookups into inputs.*, vars.*, and any step id or save_as name.

OperatorShapeDescription
eq / ne{ op, left, right }Equal / not equal.
lt / gt / lte / gte{ op, left, right }Ordered numeric comparison.
contains{ op, left, right }left contains right (substring or membership).
truthy / falsy / exists{ op, value }Test a single value for truthiness, falsiness, or presence.
and / or{ op, conditions: [..] }Combine several conditions.
not{ op, condition }Negate a condition.
Three hard guards stop a workflow run when breached: budget_cents (spend cap in USD cents; 0 means unlimited), max_iterations (loop cap), and deadline_seconds (wall-clock). A breach ends the run as failed or timed_out.

A definition is validated before it is accepted. The limits below are enforced at create and ad-hoc time, so an invalid definition is rejected with 422 VALIDATION_ERROR rather than failing mid-run.

LimitRule
Max stepsA definition holds at most 200 steps in total (counting every nested step).
Max nesting depthSteps can nest at most 8 levels deep (if, loop, parallel, retry bodies).
Parallel branchesA parallel step takes at most 16 branches; they run concurrently.
Retry attemptsretry max_attempts is an integer from 1 to 20.
Parallel contentshuman_approval, succeed, and fail are not allowed inside a parallel branch.
save_as namesave_as must not be "inputs" or "vars" (those namespaces are reserved).
Workflows are version-pinned. When a run starts, the workflow's current definition is snapshotted into that run, so editing or replacing the workflow (which bumps its version) never changes runs already in flight. Each run records the workflow_version it executed.
API reference — Coasty Computer Use API | Coasty - AI Computer-Use Agent