Back to Blog
Tutorial

James Liu6 min
Ctrl+Z

Automated agents that touch the real desktop often need you. A user might need to approve a payment, enter a one-time code, or fix a configuration issue. The runs API supports this pattern with a dedicated awaiting_human state. When a task hits awaiting_human the agent stops and waits. Your system can notify a human, collect the input, then resume the run. This avoids fragile workarounds and gives you a single place to manage the lifecycle of a computer use agent.

How awaiting_human and resume work

Start a run with POST /v1/runs. Set on_awaiting_human to pause. The run transitions to queued, then running, then awaiting_human. You can poll GET /v1/runs or stream events from GET /v1/runs/{id}/events to detect this state. Once the human provides the required input, call POST /v1/runs/{id}/resume with the input. The server continues from the same step. The run can then succeed, fail, or enter another awaiting_human state. The runs API manages the state machine so you do not need to build it yourself.

python
import os
import requests
import json
from pathlib import Path

# read the key from the environment
COASTY_API_KEY = os.getenv('COASTY_API_KEY')
BASE_URL = 'https://coasty.ai/v1'
HEADERS = {
    'Authorization': f'Bearer {COASTY_API_KEY}',
    'Content-Type': 'application/json',
}

# 1. start a run with on_awaiting_human = 'pause'
r = requests.post(
    f'{BASE_URL}/runs',
    headers=HEADERS,
    json={
        'machine_id': 'your_machine_id',
        'task': 'Open Chrome and go to the login page, then wait for me to enter my password.',
        'on_awaiting_human': 'pause',
        'cua_version': 'v3',
    },
)
r.raise_for_status()
run = r.json()
run_id = run['run_id']
print('Run started:', run_id)

# 2. stream events to detect awaiting_human
print('Streaming events...')
events = requests.get(
    f'{BASE_URL}/runs/{run_id}/events',
    headers=HEADERS,
    stream=True,
).iter_lines()
for line in events:
    if line:
        event = json.loads(line)
        if event.get('state') == 'awaiting_human':
            print('Agent is waiting for human input. Provide input via resume.')
            break

# 3. resume with the human input
resume_payload = {
    'input': 'my_password',
}
r = requests.post(
    f'{BASE_URL}/runs/{run_id}/resume',
    headers=HEADERS,
    json=resume_payload,
)
r.raise_for_status()
print('Resume response:', r.json())

# 4. final status
r = requests.get(
    f'{BASE_URL}/runs/{run_id}',
    headers=HEADERS,
)
r.raise_for_status()
print('Final state:', r.json()['state'])

Key fields and states

  • on_awaiting_human accepts 'pause', 'fail', or 'cancel'. When you set it to pause the run stops at awaiting_human.
  • States for a run include queued, running, awaiting_human, succeeded, failed, cancelled, and timed_out.
  • GET /v1/runs returns a list of runs with state, created_at, machine_id, and task.
  • GET /v1/runs/{id} returns the full run including current step and any pending input.
  • GET /v1/runs/{id}/events streams Server-Sent Events with state updates. Reconnect using Last-Event-ID if needed.
  • POST /v1/runs/{id}/resume accepts an input field for human-provided data and continues the run.
  • Billing is $0.05 per agent step. Steps taken while awaiting_human do not incur extra cost.
  • POST /v1/runs/{id}/cancel can stop a run early, and POST /v1/runs/{id}/resume can restart it later.

Use on_awaiting_human = 'pause' to let your agent stop and resume on demand.

Where this beats brittle automation

Traditional automation relies on brittle selectors, XPath, or hardcoded IDs. When a UI changes, the script breaks. With the computer use API, the agent sees the real screen and can read text, click buttons, fill forms, and even wait for a human. The awaiting_human state gives you a clean, observable breakpoint. You can integrate with Slack, email, or your own service to notify a human and collect input. The runs API handles the lifecycle, so you can focus on the human interaction logic instead of managing state machines yourself.

What to build next

Combine awaiting_human with workflows to create multi-step processes that require human approval at specific points. For example, a workflow can install software, prompt you for a license key, then continue installation. Or build an account creation agent that asks you to verify your email before finalizing the signup. The runs API gives you a reliable foundation for human-in-the-loop automation. Get a key at https://coasty.ai/developers to start building agents that pause, wait, and resume on real desktops.

The awaiting_human state in the runs API gives you a clean, server-managed way to pause and resume computer use agents. Use on_awaiting_human = 'pause', stream events to detect awaiting_human, and resume with POST /v1/runs/{id}/resume. This lets you build robust automation that genuinely interacts with the desktop and hands control back to humans when needed. Get a key at https://coasty.ai/developers .

© 2026 Coasty

Backed byYCombinator