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

# How Web Tasks work

> Execution model, reuse semantics, and the rules that govern Web Task runs

This page explains what happens when you call the [Web Tasks API](./overview): how the agent decides between AI and code, how `reuseKey` evolves over time, and the rules that govern concurrent runs.

## Execution model

When you submit a task, Intuned spins up a browser on managed infrastructure, then runs an agent that mixes AI exploration with generated code.

```
Submit task → load reusable code (if reuseKey)
            → agent explores / runs code
            → write or refine code (if reuseKey)
            → return result
```

1. **Load**: if you provided a `reuseKey`, the system loads any code previously saved under that key. If you didn't, the server mints a fresh `wtr_`-prefixed key and uses it for this run; the key comes back in `reuse.key` so you can reuse the same automation on later calls.
2. **Execute**: the agent runs the task. If saved code exists and works, it is used directly. Otherwise the AI explores the site, decides which parts of the task benefit from being code, and writes that code as it goes.
3. **Save**: on success, the improved code is saved under the key (whether you provided it or the server generated it). On failure, the previous code is left untouched so a bad run can't poison a working automation.
4. **Return**: the result is returned [inline or as a file](./overview#result-delivery), along with `reuse`, `cost`, and timing metadata.

The first run for a new key is the "figuring it out" run: slower, more expensive, AI-heavy. Subsequent runs mostly execute saved code, making them fast, cheap, and consistent. The same applies when the site changes: the AI repairs the code, the next run is back to fast and cheap.

### Rejection

Before the agent starts, the system checks if the task is eligible for Web Tasks. If not, the request is rejected. Common reasons for rejection include:

* Illegal activity, harassment, targeted harm and other violations of our [Terms of Service](/main/06-resources/terms-of-service).
* Tasks that are not web automation (for example, "Write a poem about the sea").
* Tasks that are impossible, incoherent or self-contradictory.

### Model selection

Every run uses an Anthropic model, controlled by the `model` request field: `haiku` (default), `sonnet`, or `opus`. Heavier models cost more but help on harder tasks, such as complex multi-step flows and fiddly extraction. Most repeat runs that just execute saved code work well with `haiku`.

## Reuse rules

### Same key, same automation

A `reuseKey` identifies one reusable automation. Two runs with the same key share code, **regardless of `startUrl` or `parameters`**:

```jsonc theme={null}
// Both runs use the same reusable automation: "companies"
{
  "task": "Scrape YC companies",
  "startUrl": "https://www.ycombinator.com/companies",
  "reuseKey": "companies"
}
{
  "task": "Scrape Wellfound companies",
  "startUrl": "https://wellfound.com/companies",
  "reuseKey": "companies"
}
```

If you want separate automations, use separate keys (`yc_companies`, `wellfound_companies`). The system does not create hidden per-URL memories.

### Failed runs do not update code

If `outcome` is `failed`, `reuse.updated` is always `false`. A failed attempt cannot overwrite a working automation.

## The `reuse` response

When you provide a `reuseKey`, the result includes a `reuse` object describing what happened to the saved code:

| Field                | Meaning                                                                            |
| -------------------- | ---------------------------------------------------------------------------------- |
| `key`                | The `reuseKey` you sent.                                                           |
| `used`               | `true` if existing saved code was loaded and executed.                             |
| `created`            | `true` if this run created the first saved code for this key.                      |
| `updated`            | `true` if this run improved or repaired the saved code. Always `false` on failure. |
| `revision_id`        | ID of the Web Task run whose code is currently saved under this key.               |
| `revision_timestamp` | When the saved code was last updated.                                              |

Three common shapes:

```jsonc theme={null}
// First successful run for a new key
{ "reuse": { "key": "yc_companies", "used": false, "created": true,  "updated": true } }

// Later run, saved code worked as-is
{ "reuse": { "key": "yc_companies", "used": true,  "created": false, "updated": false } }

// Later run that repaired or improved the saved code
{ "reuse": { "key": "yc_companies", "used": true,  "created": false, "updated": true } }
```

## Cost dynamics

Costs are reported per run as `aiUsd` (model spend) and `compute.amount` in hours. Expect cost to follow this shape:

* **First run for a key**: high AI cost, longer compute.
* **Steady-state runs**: low AI cost, short compute.
* **Repair runs**: moderate AI cost when the saved code needs updating (for example, after a site change).

This is the central tradeoff Web Tasks make: pay AI cost up front to generate code, then amortize it across many cheap repeat runs.
