Guide

The Workflow DSL Explained: Task, Assert, If, Loop, Parallel

Marcus Sterling||10 min
F5

Browser automation that clicks a button once works. Automation that runs nightly across dozens of apps or handles human approval gates needs structure. The Coasty workflow DSL lets you define multi-step runs with tasks, assertions, conditionals, loops, and parallel branches from a single versioned JSON document. You post that DSL to /v1/workflows, start it via /v1/workflows/{id}/runs, and the server drives the computer use agent to completion, billing $0.05 per agent step. This post explains the DSL step types and how to use them with real requests and prices.

Workflow DSL structure

  • A workflow is a versioned JSON document you POST to /v1/workflows. The server stores it and returns an id.
  • Each workflow can contain multiple steps of known types: task, assert, if, loop, parallel, human_approval, retry, succeed, fail.
  • Variables are referenced with double-brace syntax like {{inputs.username}} or stepId.field for outputs.
  • Hard guards on every workflow include budget_cents, max_iterations, and deadline_seconds.
  • When you start a workflow run you POST to /v1/workflows/{id}/runs with a machine_id, task, and optional instructions and system_prompt.
bash
# POST a workflow DSL to /v1/workflows
# Note: machine_id comes from the /v1/machines endpoint
# 1 credit = $0.01. Tasks cost $0.05 each.

export COASTY_API_KEY=$(cat ~/.coasty-key)
machine_id="mch_1234567890"

curl -X POST https://coasty.ai/v1/workflows \
  -H "X-API-Key: $COASTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "version": "1.0",
  "hard_guards": {
    "budget_cents": 10,
    "max_iterations": 100,
    "deadline_seconds": 300
  },
  "steps": [
    {
      "id": "task_login",
      "type": "task",
      "instruction": "Log in to the app using the username and password from inputs."
    },
    {
      "id": "assert_logged_in",
      "type": "assert",
      "description": "Verify the user is logged in by checking the dashboard page contains the username."
    },
    {
      "id": "conditional",
      "type": "if",
      "condition": {
        "type": "expression",
        "expression": "inputs.environment == "production""
      },
      "then": [
        {
          "id": "parallel_tasks",
          "type": "parallel",
          "steps": [
            {
              "id": "task_report_a",
              "type": "task",
              "instruction": "Open and generate the daily report A."
            },
            {
              "id": "task_report_b",
              "type": "task",
              "instruction": "Open and generate the daily report B."
            }
          ]
        }
      ],
      "else": {
        "id": "task_dev_report",
        "type": "task",
        "instruction": "Generate the development report."
      }
    },
    {
      "id": "loop_items",
      "type": "loop",
      "items": "{{inputs.item_list}}",
      "step": {
        "id": "task_process_item",
        "type": "task",
        "instruction": "Open the item details for {{loop_item}} and mark it as processed."
      }
    },
    {
      "id": "human_gate",
      "type": "human_approval",
      "prompt": "Wait for approval to proceed with the final upload."
    },
    {
      "id": "final_upload",
      "type": "task",
      "instruction": "Upload the processed files to the specified storage location."
    },
    {
      "id": "cleanup",
      "type": "task",
      "instruction": "Close all browser windows and log out."
    },
    {
      "id": "success_result",
      "type": "succeed"
    }
  ]
}'

Task step

  • type: task - The agent drives the computer to complete a step. Each task step costs $0.05 per agent step.
  • instruction: string - Natural language instruction the agent receives.
  • output: optional field that the server stores so you can reference it in later steps via stepId.field.
  • Use task when you need the agent to see the screen and act like a human, rather than call an API directly.

Assert step

  • type: assert - A non-persistent check that the server evaluates after a task step or as part of a conditional.
  • description: string - The element description or assertion the server uses to verify state.
  • If the assertion fails, the workflow can proceed to fail, retry, or human_approval depending on your configuration.
  • You can assert UI elements, text presence, or any condition you can express in a short description.

If step

  • type: if - Conditionally executes one branch or another.
  • condition: object - A structured condition object with expression or other supported forms.
  • then: array of steps - Steps to run if the condition is true.
  • else: object or array of steps - Steps to run if the condition is false.
  • You can nest if steps inside parallel branches or loops for complex control flow.

Loop step

  • type: loop - Iterates over an array of items and runs a step for each item.
  • items: string - A reference to a list variable, likely from inputs or a previous step.
  • step: object - The task or other step to run for each item.
  • loop_item: special variable inside the step's instruction that contains the current item.
  • Each iteration is billed as a separate agent step at $0.05.

Parallel step

  • type: parallel - Runs multiple steps concurrently. The server executes them in order but may overlap.
  • steps: array of steps - Each step can be task, assert, if, loop, or other supported types.
  • Parallel steps do not add net cost beyond the steps themselves.
  • Use parallel to speed up workflows that can run independently, such as generating multiple reports.
  • Outputs from parallel branches are merged or you can pick one branch's output for later steps.

POST your versioned workflow DSL to /v1/workflows, start a run via /v1/workflows/{id}/runs, and let the server drive the computer use agent, billing $0.05 per step.

Where this beats brittle automation

  • The workflow DSL describes intent and logic, not low-level selectors. The agent sees the screen and acts like a human, which means you do not need to maintain brittle CSS selectors or element IDs.
  • Parallel and loop steps let you scale from single actions to multi-step pipelines without rewriting logic for each use case.
  • Hard guards on budget_cents, max_iterations, and deadline_seconds keep runs safe and predictable.
  • Assert steps let you verify state without brittle assertions, relying on the agent's ability to see and interpret the UI.
  • Using a single versioned JSON definition makes it easy to version, audit, and roll back workflows across your fleet of machines.

You can now define multi-step, conditionally executed, and parallelized automation with the Coasty workflow DSL. Start by creating a workflow via /v1/workflows, then launch runs via /v1/workflows/{id}/runs. Each agent step costs $0.05, and hard guards on budget and iterations keep your runs safe. Get your API key and start building at https://coasty.ai/developers.

Want to see this in action?

View Case Studies
Try Coasty Free