# Tasks

A task is one piece of work by one worker, from the moment you give it to its result.

A task is one piece of work given to one worker. You give it with `POST /tasks` and say what you want in a message. The worker does the work, and the task says where it stands until the worker is done. The app lists the same tasks, so a task you give with the API shows up there, and a person can follow it or step in.

The [Overview](/get-started/overview) walks a task from start to finish. This page explains what a task holds, what each state means, and what limits it has. Every field is on the [Tasks reference](/api/tasks).

## What a task holds

- **A worker.** The one that does the work. A task keeps the worker version it was made with, even after the worker changes, so a change to a worker reaches the next task and not the one at work. The task's `worker` shows the worker as this task runs it.
- **A chat.** Every task lives in a chat, and a chat belongs to one worker. The API has no chat object: a chat is only an id, `chat_id`, on a task. A task made without `chat_id` gets a chat of its own, and the worker starts fresh. A task made with a `chat_id` joins that chat, and the worker reads the finished work already in it. Use that for follow-up work. The chat must be one of the same worker's, or the answer is `404`. `GET /tasks?chat_id=` lists the tasks in a chat.
- **A title and an ask.** `title` is 1 to 500 characters. Left out, it is the first words of the first message. `ask` is what that message asked.
- **Labels.** `metadata` holds up to 16 keys with string values, for your own use.
- **A budget.** The most the task's work may cost. See [Budgets](#budgets).
- **What it may use.** `resources` lists files, repositories and memory stores, up to 100 in all. `password_set_ids` lists the password sets it signs in with, up to 20. Both are set when the task is made. `password_set_ids` cannot change after that, and files can be added and removed later. See [Files](/concepts/files), [Memory](/concepts/memory) and [Password sets](/concepts/password-sets).
- **Who made it.** `created_by` is `person` for a task given by a person or a key, `worker` for one a worker started, and `need` for one made because a run needed the person and had no task to ask in. A task made by a [routine](/concepts/routines) reads `worker` here. Its `routine_id` names the routine, and is `null` for any other task.

## Where a task stands

A task says where it stands in two sets of words. `status` is a Claude session's: `running`, `idle`, `rescheduling` or `terminated`. `state` says the same in the words the app shows. Three fields explain the rest:

- `state.status` is `not_started`, `working`, `needs_you` or `done`.
- `state.needs` is set only while `state.status` is `needs_you`. It says what the task asks of you: `allow`, `answer`, `help`, or `look`.
- `state.waiting_reason` says why a task waits.

| What is happening | `status` | `state` | `stop_reason` |
| --- | --- | --- | --- |
| The worker is on it | `running` | `working` | `null` |
| It waits behind another task of the same worker | `running` | `not_started`, with `waiting_reason` `busy` | `null` |
| A plan, trial, balance or spending cap holds it. It goes on by itself when there is room | `rescheduling` | `needs_you`, with `needs` `help` and `waiting_reason` naming the cap | `null` |
| It waits for your Allow, your answer or your help | `idle` | `needs_you` | `requires_action` |
| Its own budget holds it | `idle` | `needs_you`, with `needs` `help` | `budget_reached` |
| Its run failed, and Little Worker runs it again by itself | `rescheduling` | `needs_you`, with `needs` `help` | `null` |
| Its run failed and will not run again by itself | `idle` | `needs_you`, with `needs` `help` | `retries_exhausted` |
| The model declined its turn for safety | `idle` | `needs_you`, with `needs` `help` | `refusal` |
| Its run took 200 model turns | `idle` | `needs_you`, with `needs` `help` | `turn_limit` |
| Its run took 2 hours of active model time | `idle` | `needs_you`, with `needs` `help` | `time_limit` |
| The check of its work still found it short | `idle` | `needs_you`, with `needs` `look` | `end_turn` |
| It is done | `idle` | `done` | `end_turn` |
| You stopped it | `idle` | `not_started`, with `waiting_reason` `stopped` | `end_turn` |

A cap's `waiting_reason` is one of `five_hour`, `week`, `month`, `trial`, `balance`, `monthly_limit`, `chatgpt_plan` (the ChatGPT plan's limit), `plan_task_limit` (the most one task may use on the plan) or `spend_limit` (a cap the gateway did not name). `terminated` is part of the shape because a Claude session has it, but no task has it today.

## What a stop means

While a task is `idle`, `stop_reason` says why the worker stopped. It is the same value the task's last `task.status_idle` event carries.

| `stop_reason.type` | What it means | What to do |
| --- | --- | --- |
| `end_turn` | The worker finished its turn. An interrupt or a Stop ends the turn the same way. When `state.status` is `done`, the work is finished. | Read the result, or send a message to go on. |
| `requires_action` | The worker waits on steps that only you can answer. `event_ids` names the tool uses, and `blocking` lists every step with its kind. | Answer them. See [Approvals](/concepts/approvals). |
| `budget_reached` | The task spent its own budget. A plan or spending cap is not this: that task stays `rescheduling` and goes on by itself. | Raise the budget. The task goes on at once. |
| `retries_exhausted` | The run failed and Little Worker stopped trying. A `task.error` comes right before, with the reason. | Read the error, then send a message to try again. |
| `refusal` | The model declined the turn for safety. The turn is not asked again and no `task.error` comes. `stop_details` has a `category` and an `explanation` for people. Its wording can change, so do not parse it. | Send a new message. |
| `turn_limit`, with `limit` | One run took 200 model turns. A run guard stopped it cleanly, and its work is kept. | Send a message or send the task back. That starts a fresh run with fresh limits. |
| `time_limit`, with `limit_ms` | One run took 2 hours of active model time (`7200000`). It stops the same way. | The same. |

## Budgets

Every task has a budget: the most its work may cost at list price. It is a money value in whole US cents, written as a string:

```json
{ "type": "limit", "max_list_cost": { "amount": "500", "currency": "USD" } }
```

Left out, the budget is $5.00 (`"500"`). The most is $1,000.00 (`"100000"`); more is `400` with `error_code` `budget_too_high`. A budget can be changed but not removed, so `null` is `400` with `error_code` `budget_required`.

Work is counted at list price: each model turn's tokens at its model's list price, plus $10 for every 1,000 web searches. `usage.list_cost` on the task shows the total so far. When the task reaches its budget it stops as `idle` with `budget_reached`. Raise the budget with `POST /tasks/{task_id}`. The new amount must be more than the task has spent, and work held at the old budget goes on at once.

A budget is not the same as a plan cap. A plan, trial, balance or spending cap holds the task as `rescheduling`, and it goes on by itself when there is room.

## Getting a result

Finished work is done by itself. When the worker finishes, the task becomes `done` with no step from you. `result_summary` holds one line about the result, and the worker's full answer is its last `worker.message` event. There is nothing to accept.

A task can also have an outcome. Send a `user.define_outcome` event, in `initial_events` or later, and the task is checked against it before it counts as done. Send either a `rubric`, written as text or held in a file, or `done_means`, a list of 1 to 8 checks of up to 200 characters each, but not both. `max_iterations` is how many check rounds the task may take, 1 to 20, and 3 when left out. While the check runs, the task stays `working`. Each round is listed in `outcome_evaluations` with a `result` of `satisfied`, `needs_revision`, `max_iterations_reached`, `failed` or `interrupted`.

When the last round still finds the work short, the task stops as `needs_you` with `needs` set to `look`. You can then:

- **Accept it** with a `user.accept` event. The work is done as it is. `user.accept` is `409` while the worker is still on the task.
- **Send it back** with a `user.send_back` event and a `reason` of up to 4,000 characters. The worker works on it again in a new run, and `sent_back_count` goes up by one.
- **Send a message.** A plain `user.message` to a done task reopens it the same way, with the message as the reason.

Send `user.accept` and `user.send_back` alone, one in each request. A done task in a project (a room of several workers) is `409` for a send back or a message: answer in the chat in the app. An archived task takes no message.

## One task at a time

A worker does one task at a time. Its other tasks wait in the order they were given, and show `status` `running` with `state.waiting_reason` `busy`. A worker holds at most 20 waiting runs. Past that, the next message is `429` with `error.type` `rate_limit_error` and `error_code` `queue_limit`. `retryable` is `true`, so send it again once the worker has caught up.

## Ending a task

There are four ways to end a task's work, from the lightest to the heaviest.

| To do this | Use | What happens |
| --- | --- | --- |
| Stop the work in hand | `user.interrupt` event | The model stops at once and the turn ends with `task.status_idle` and `end_turn`. The task stays open, and the next `user.message` starts a new turn. A task held at its own budget has nothing to stop, so the interrupt is accepted and not listed. |
| Take the task back | `POST /tasks/{task_id}/withdraw` | Every run that has not finished stops, and the Allows and questions it waits on are closed. The task is gone: lists leave it out and reading it answers `404`. A task that is already done stays done, and the answer says `done`. |
| Keep the task, but close it | `POST /tasks/{task_id}/archive` | Everything is kept. The task takes no new message and leaves lists unless you ask for `include_archived=true`. It cannot be undone. |
| Remove the task | `DELETE /tasks/{task_id}` | The task, its events and the files it made that you did not keep are removed. It needs a key made with **Can delete tasks**. Settings has no switch for that yet, so a key made there cannot delete. |

Archive and delete are `409` while the task has a run that has not ended: interrupt it, wait for the stop, then try again. Each route has its own section on the [Tasks reference](/api/tasks).

> [!WARNING]
> An interrupt stops the next step, not the last one. An email already sent, a post already made, a file already written and a form already submitted stay done. A step that was running may have finished: its `worker.tool_result` has a `status` of `cancelled` or `outcome_unknown`. Read the events, and check the outside system when the status is `outcome_unknown`. To refuse an action before it runs, make it ask first.

## How long a task is kept

Nothing about a task expires. What is kept depends on the plan:

| Plan | History |
| --- | --- |
| Free | 7 days. A piece of work is deleted once every run in it ended more than 7 days ago. |
| Any paid plan | Kept until you delete it. |

The task itself stays readable after history is deleted, and its events start with a `history.purged` event. A purge removes the work's runs, messages, tool uses, results, approvals and events, and the files the work made unless you kept them. It keeps the workers, tasks, routines, memory stores, password sets, saved files, receipts and a person's decisions. See [Runs and events](/concepts/runs-and-events) and [Files](/concepts/files).

## Limits

| What | Limit |
| --- | --- |
| Title | 1 to 500 characters |
| Labels (`metadata`) | 16 keys |
| `initial_events` | 50 events |
| Resources | 100, of which at most 8 are memory stores |
| Password sets named | 20 |
| Budget | $5.00 by default, $1,000.00 at most |
| One run | 200 model turns and 2 hours of active model time |
| Waiting runs per worker | 20 |
| Send back reason | 4,000 characters |
| Outcome check rounds | 1 to 20, and 3 when left out |

## Next steps

- [Runs and events](/concepts/runs-and-events): every event a task writes, and how to follow them without missing one.
- [Approvals](/concepts/approvals): how a worker asks before it acts, and who may answer.
- [Tasks reference](/api/tasks): every field of a task and each route that gives, lists, reads, changes and takes back tasks.
