> ## Documentation Index
> Fetch the complete documentation index at: https://docs.guidinghand.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tasks

> A task is one job in plain language, run by the agent on a connected computer.

A task is what you want done on the customer's computer, in plain language: "Turn on Dark Mode", "Connect to the office Wi-Fi called Acme-Guest", "Export last month's invoices from Acme Billing to the Desktop". Describe the outcome, not the clicks. The agent looks at the screen, acts, looks again, and repeats until it is done or needs a person.

Start one with `POST /v1/sessions/{session_id}/tasks`. The prompt can be up to 8,000 characters.

## Status lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> queued
    queued --> running
    running --> waiting_for_user: agent asks a question
    waiting_for_user --> running: answered by you or the customer
    running --> waiting_for_approval: agent asks for approval
    waiting_for_approval --> running: POST /respond with a decision
    running --> completed: agent finished
    running --> failed: something went wrong
    running --> stopped: stopped by you or the customer
    waiting_for_user --> stopped
    waiting_for_approval --> stopped
    completed --> [*]
    failed --> [*]
    stopped --> [*]
```

| `status`               | Meaning                                                                                                                                                 |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `queued`               | Accepted, and about to start. Usually too short to see.                                                                                                 |
| `running`              | The agent is working on the computer.                                                                                                                   |
| `waiting_for_user`     | The agent asked a question. `pending` holds it.                                                                                                         |
| `waiting_for_approval` | The agent wants to do something consequential and needs a yes or no. `pending` holds it.                                                                |
| `completed`            | Finished. `result` has the agent's summary.                                                                                                             |
| `failed`               | Couldn't finish. `error` has the reason.                                                                                                                |
| `stopped`              | Stopped by `POST /v1/tasks/{task_id}/stop`, by the customer, or because an approval for a safety check was denied. The last event's message says which. |

`done` is `true` for `completed`, `failed` and `stopped`, and nothing changes after that.

## Events

Everything a task does is an event with an increasing `cursor`. Follow them with `GET /v1/tasks/{task_id}/events?after={cursor}&wait_ms=25000`, or fetch them all with `GET /v1/tasks/{task_id}?include=events`.

```json theme={null}
{ "cursor": 3, "type": "action", "message": "Click at (412, 88)", "ts": "2026-09-26T15:05:39.584Z",
  "data": { "action": { "type": "click", "button": "left", "x": 412, "y": 88 } } }
```

| `type`              | Meaning                                                                                                                                                                                                        |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `started`           | The task was received and is starting on the computer.                                                                                                                                                         |
| `progress`          | A status note, such as looking at the screen or retrying a step another way.                                                                                                                                   |
| `thinking`          | A short summary of the model's reasoning for the next step.                                                                                                                                                    |
| `action`            | Something the agent did on the computer. `data.action` has the details: `type` (`click`, `type`, `keypress`, `scroll`, …) and fields like `x`, `y`, `text`, `keys`. Long typed text is cut to 200 characters.  |
| `message`           | Text from the agent. The last one before `completed` is its summary.                                                                                                                                           |
| `question`          | The agent asked something. `data` has `question_id`, `question` and `options`.                                                                                                                                 |
| `answer`            | The question was answered. `message` is the answer; `data` has `question_id` and `answered_by`: `operator` (your team, through the API or the console) or `customer` (the person at the computer, in the app). |
| `approval_required` | The agent wants approval. `data` has `approval_id`, `action`, `risk` and `source`.                                                                                                                             |
| `approved`          | The approval was granted. `data` has `approval_id`, `answered_by` (`customer` or `operator`) and your `note`, if you sent one.                                                                                 |
| `denied`            | The approval was denied. `data` has `approval_id`, `answered_by` and your `note`, if you sent one.                                                                                                             |
| `completed`         | The task finished. `message` is the result.                                                                                                                                                                    |
| `error`             | The task failed. `message` is the reason.                                                                                                                                                                      |
| `stopped`           | The task was stopped. `message` says by whom.                                                                                                                                                                  |

`wait_ms` holds the request open (up to 55,000 ms) until there is at least one new event, the task ends, or the time runs out. An empty `data` array just means nothing happened yet; call again with the same `after`.

## Questions and approvals

The agent pauses and asks when it needs a person. While it waits, `task.pending` is set, the status is `waiting_for_user` or `waiting_for_approval`, and the matching webhook (`task.waiting_for_user`, `task.waiting_for_approval`) fires. The task waits until it gets an answer or is stopped.

**Questions** are for things only a person knows: which account, which file, which of two printers.

```json theme={null}
{ "type": "question", "question_id": "q_yrJaMMY1ZMM", "question": "Which account?", "options": ["Work", "Home"], "customer_can_answer": true }
```

`options` are suggestions, and may be empty. The `answer` is free text, up to 4,000 characters (longer answers are cut there).

Questions can be answered on the customer's screen. Unless the agent turns it off (its [`customer_answers`](/concepts/agents#questions-the-customer-can-answer) setting), the question also appears in the GuidingHand app with its options, and the customer can answer it there. `customer_can_answer` is `true` when they can. Your team can answer too, with `/respond` or in the console: the first answer is used, and the task's `answer` event and the `task.question_answered` webhook say who gave it (`answered_by`). So you can relay the question in your chat, or simply wait for the customer to answer it on screen.

```json theme={null}
POST /v1/tasks/{task_id}/respond
{ "question_id": "q_yrJaMMY1ZMM", "answer": "Work" }
```

If the customer answered first, this returns `409 conflict` with `code: "already_answered"`:

```json theme={null}
{ "error": { "type": "conflict", "message": "That was already answered by the person at the computer.", "code": "already_answered", "answered_by": "customer" } }
```

Treat that as done, not as a failure: the task already has its answer and carries on.

**Approvals** come before anything consequential or irreversible: purchases, sending messages, deleting data, submitting forms, changing settings, entering personal data. `action` says exactly what the agent is about to do.

```json theme={null}
{ "type": "approval", "approval_id": "appr_OZ0pj8lNbZk", "action": "Click Save to apply the new billing address", "risk": "medium", "customer_can_approve": true }
```

```json theme={null}
POST /v1/tasks/{task_id}/respond
{ "approval_id": "appr_OZ0pj8lNbZk", "decision": "deny", "note": "Don't save yet, the customer wants to check the postcode." }
```

Approvals can be decided on the customer's screen too. Unless the agent turns it off (its [`customer_approvals`](/concepts/agents#approvals-the-customer-can-decide) setting), the request also appears in the GuidingHand app, and the customer can allow it or not there. `customer_can_approve` is `true` when they can. As with questions, the first decision is used, a later one gets `409` with `code: "already_answered"`, and the `approved` or `denied` event and the `task.approval_decided` webhook say who decided (`answered_by`).

`risk` is `low`, `medium` or `high`. `decision` is `approve` or `deny`, and the optional `note` (up to 1,000 characters) is passed to the agent. When you deny an approval the agent asked for, it is told not to do that and carries on another way. The model can also raise its own safety checks, which arrive as approvals with `risk: "high"`; denying one of those stops the task.

Respond only to what is pending now. An id that isn't pending returns `409 conflict`, with `error.code` saying why: `already_answered` (with `answered_by`) when that question or approval has just been answered or decided by someone else, `not_pending` otherwise (an older id, or a task that has ended).

## Idempotency with `request_id`

Send a `request_id` of your own (up to 200 characters) when starting a task. If the same `request_id` was already used on that session, you get the existing task back instead of a new one, whatever its status. Use it so a retried request, after a timeout or a crash, doesn't run the job twice. Use a new `request_id` when you do want to run it again.

## One task at a time per computer

A computer runs one task at a time. Starting a task while another runs returns `409 conflict`, with the running task's id in `error.active_task_id`. Wait for it to finish, or stop it with `POST /v1/tasks/{task_id}/stop`.

Your plan also limits how many tasks the whole org runs at once. Past that limit, starting a task returns `429 rate_limit`. See [Errors](/guides/errors).

## Stopping

`POST /v1/tasks/{task_id}/stop` stops the task right away and returns it, with `interrupted: false` if it had already finished. The customer can stop it too, from the banner or with the keyboard shortcut. See [what the customer sees](/concepts/sessions#what-the-customer-sees).

A task also fails if it runs 150 steps without finishing. Break long jobs into several tasks.

## Billing

Tasks use **agent minutes**, which count only the time a task spends `running`. Time spent waiting for an answer or an approval is not counted, so a slow reply from a person doesn't cost you anything.

* `active_seconds` is the running time so far.
* `billed_minutes` is the running time rounded up to whole minutes, set when the task ends.
* A task where the model never acted on the computer is free.

The free plan's minutes are used once per account. When they run out, a running task is stopped and new ones return `402 payment_required`. Plans and prices are on [guidinghand.ai/pricing](https://guidinghand.ai/pricing).

## Listing

`GET /v1/tasks` lists tasks newest first, filtered by `session_id`, `agent_id` or `status`. Each has `recording.frames`, the number of recorded screens. See [pagination](/guides/errors#pagination).
