Most automated agents fail when they hit a popup, a CAPTCHA, or a workflow step that needs a human decision. The Coasty runs API solves this with a built-in human-in-the-loop mode. When an agent encounters an ambiguous situation, it transitions to the awaiting_human state instead of failing. Your application can then prompt a user, approve a step, or provide missing data via a webhook. You can then resume the run to let the agent continue. This works with the task runs endpoint, which bills $0.05 per agent step and streams events via Server-Sent Events.
How it works
A task run starts with a POST /v1/runs payload. You set on_awaiting_human to 'pause' (the default). The server runs the agent and streams progress through GET /v1/runs/{id}/events. If the agent reaches a state where it needs a human, the run enters the awaiting_human state and the event stream emits that status. Your application can then call POST /v1/runs/{id}/resume to tell the agent what to do. The run then continues in the running state until it reaches succeeded, failed, cancelled, or timed_out. The agent uses the cua_version (default is v3, v4 uses an autonomous pass/fail verifier) to drive real desktops, browsers, and terminals, not just API calls.
#!/bin/bash
# Start a human-in-the-loop task run
# Replace YOUR_API_KEY with your actual key
API_KEY="${COASTY_API_KEY}"
SERVER="https://coasty.ai/v1"
# Create a run that pauses on awaiting_human
RESPONSE=$(curl -s -X POST "${SERVER}/runs" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"machine_id": "m-12345",
"task": "Fill in the customer name and click submit",
"cua_version": "v3",
"on_awaiting_human": "pause",
"max_steps": 20,
"deadline_seconds": 300
}')
RUN_ID=$(echo $RESPONSE | jq -r '.id')
echo "Run ID: $RUN_ID"
# Poll the run status until it enters awaiting_human
while true; do
STATUS=$(curl -s -X GET "${SERVER}/runs/${RUN_ID}" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Accept: application/json" | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "awaiting_human" ]; then
echo "Agent paused waiting for human action."
break
elif [ "$STATUS" = "succeeded" ] || [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
echo "Run finished with status: $STATUS"
break
fi
sleep 2
done
# When human input is ready, resume the run
RESUME_RESPONSE=$(curl -s -X POST "${SERVER}/runs/${RUN_ID}/resume" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"action": "continue",
"feedback": "Human approved the step."
}')
echo "Resume response: $RESUME_RESPONSE"
# Stream events until done
echo "Streaming events..."
curl -s -N -X GET "${SERVER}/runs/${RUN_ID}/events" \
-H "Authorization: Bearer ${API_KEY}" | jq -r '.type.message'Key runs API fields
- POST /v1/runs creates a task run. Required fields: machine_id (provisioned cloud VM), task (natural language instruction), cua_version (default v3, v4 for autonomous verifier). Optional: on_awaiting_human (pause|fail|cancel), max_steps (default unlimited), deadline_seconds, system_prompt.
- on_awaiting_human controls behavior when the agent hits an ambiguous state. Set to 'pause' to stop the run and wait for resume (recommended for humans), 'fail' to stop and signal failure, or 'cancel' to stop the run.
- GET /v1/runs returns the current run status (queued, running, awaiting_human, succeeded, failed, cancelled, timed_out).
- GET /v1/runs/{id}/events streams Server-Sent Events with type and message. Reconnect with the Last-Event-ID header on disconnect.
- POST /v1/runs/{id}/resume accepts a JSON body with action (continue is common) and optional feedback to feed back human decisions after awaiting_human.
- Billing: $0.05 per agent step. The runs API is separate from the predict API, which costs $0.05 per vision call or $0.04 per stateful predict.
Set on_awaiting_human to 'pause' and call POST /v1/runs/{id}/resume when the human decision is ready.
Where this beats brittle automation
Traditional automation relies on brittle selectors, hardcoded XPath, or APIs that do not exist. If a UI changes, the selector breaks and the script fails. Computer use agents see the screen like a human, interpret instructions, and can handle popups, CAPTCHAs, and dynamic elements. The awaiting_human state lets you inject human judgment at exactly the right moment, such as verifying an email, approving a financial transfer, or entering a one-time password. This reduces false positives and lets you keep automation code simple while handling the edge cases that usually break scripts.
Use runs API on_awaiting_human and resume to pause agents for human decisions, then continue automatically. Build workflows that handle real-world edge cases without brittle selectors. Get your API key and start building at https://coasty.ai/developers.
Want to see this in action?
View Case Studies