The Workflow DSL Explained: task, assert, if, loop, parallel
Most automation fails when a page changes layout or an API endpoint shifts. You end up patching selectors or regexes. The Coasty Workflow DSL lets you define the full sequence of runs, checks, and decisions in a single JSON document. You can assert outcomes, conditionally branch, repeat loops, and run parallel tasks with a single POST to /v1/workflows, then spin up runs with /v1/workflows/{id}/runs.
How the Workflow DSL works
A workflow is a versioned JSON object. You POST it to /v1/workflows with an id and a version. The document contains a steps array where each element is one of task, assert, if, loop, parallel, human_approval, retry, succeed, or fail. Each step can reference variables like {{inputs.x}} or stepId.field and can include hard guards such as budget_cents, max_iterations, and deadline_seconds. A task step spawns a run and bills $0.05 per agent step. The workflow structure is stateless, but you can reference previous outputs to drive later steps.
curl -X POST https://coasty.ai/v1/workflows \
-H "X-API-Key: $COASTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "demo-order-flow",
"version": 1,
"steps": [
{
"id": "launch-store",
"type": "task",
"task": "Open https://example.com/store",
"cua_version": "v3"
},
{
"id": "check-title",
"type": "assert",
"condition": {
"operator": "includes",
"field": "outputs.launch-store.title",
"value": "Store"
}
},
{
"id": "if-available",
"type": "if",
"condition": {
"operator": "truthy",
"field": "outputs.check-title.success"
},
"then": {
"steps": [
{
"id": "add-to-cart",
"type": "task",
"task": "Click the first Add to Cart button",
"cua_version": "v3"
},
{
"id": "verify-cart",
"type": "assert",
"condition": {
"operator": "includes",
"field": "outputs.add-to-cart.title",
"value": "Cart"
}
}
]
}
},
{
"id": "loop-items",
"type": "loop",
"items": "{{inputs.cart_items}}",
"max_iterations": 5,
"steps": [
{
"type": "task",
"task": "Click the Add to Cart button for item {{loop.items}}",
"cua_version": "v3"
},
{
"type": "assert",
"condition": {
"operator": "truthy",
"field": "outputs." + loop.stepId + ".success"
}
}
]
},
{
"id": "parallel-checkout",
"type": "parallel",
"steps": [
{
"id": "checkout-task",
"type": "task",
"task": "Navigate to checkout and submit",
"cua_version": "v3"
},
{
"id": "email-task",
"type": "task",
"task": "Open email and click the verification link",
"cua_version": "v3"
}
]
},
{
"id": "final",
"type": "succeed",
"message": "Workflow completed successfully"
}
]
}'Task steps
- ●task steps invoke a run with POST /v1/runs (or via workflow) and set outputs.stepId.* for later reference.
- ●Each task is billed $0.05 per agent step.
- ●You can override the default cua_version to v4 for autonomous run with pass/fail verifier.
Assert steps
- ●assert steps check the truthiness of a field from an output, such as outputs.launch-store.success.
- ●Operators include truthy, includes, equals, and others.
- ●A failed assert causes the workflow to transition to fail or cancel depending on configuration.
If conditions
- ●if steps evaluate a condition against outputs.stepId.field and execute the then block when true.
- ●You can nest if blocks to create complex branching logic.
- ●The condition field can reference variables like {{inputs.x}} or outputs.stepId.field.
Loop steps
- ●loop steps iterate over an array field such as {{inputs.cart_items}} with a max_iterations guard.
- ●Each iteration creates a new stepId that you can reference in later steps.
- ●Loops are useful for bulk actions, retries, or processing dynamic lists.
Parallel branches
- ●parallel steps run independent tasks concurrently, often for side effects or multi-step flows.
- ●Each branch spawns its own run and you can reference outputs.branchId.field separately.
- ●Parallelism reduces total wall-clock time for independent operations.
Where this beats brittle automation
With pure selectors or API-only tools, a layout change breaks your script. The Workflow DSL lets you assert that a title includes a word, that a success field is true, or that a button exists. You can loop over a dynamic list of items, branch based on whether a task succeeded, and run parallel tasks without managing separate scripts. The server manages runs, streams events via /v1/runs/{id}/events, and reuses the same cua_version across tasks, so your agent behaves like a human across the whole sequence.
POST /v1/workflows with a JSON DSL lets you compose runs, asserts, conditions, loops, and parallel branches into a single stateful plan.
Now you can build multi-step, stateful agents that verify results, adapt on failure, and scale with loops and parallelism. Get a key at https://coasty.ai/developers and start modeling your workflows.