The Workflow DSL Explained: Task, Assert, If, Loop, Parallel
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.
# 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.