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

# Running tasks

> scout.run(task, options): caps, schemas, cancelling, live steps, what a run returns, and the two errors it can throw.

export const OutcrawlStyles = () => {
  if (typeof document !== 'undefined' && !document.getElementById('outcrawl-overrides')) {
    const s = document.createElement('style');
    s.id = 'outcrawl-overrides';
    s.textContent = `
      /* Match the product's radius grid (4 / 6 / 8 / 9999), not Mintlify's default. */
      .rounded-sm { border-radius: 0.375rem !important; } /* 6px, --r-ctl */
      .rounded-md { border-radius: 0.375rem !important; } /* 6px, --r-ctl */
      .rounded-lg { border-radius: 0.5rem !important; }   /* 8px, --r-panel */
      .rounded-l-sm { border-top-left-radius: 0.375rem !important; border-bottom-left-radius: 0.375rem !important; }
      .rounded-r-sm { border-top-right-radius: 0.375rem !important; border-bottom-right-radius: 0.375rem !important; }
      .rounded-l-md { border-top-left-radius: 0.375rem !important; border-bottom-left-radius: 0.375rem !important; }
      .rounded-r-md { border-top-right-radius: 0.375rem !important; border-bottom-right-radius: 0.375rem !important; }
      .rounded-l-lg { border-top-left-radius: 0.5rem !important; border-bottom-left-radius: 0.5rem !important; }
      .rounded-r-lg { border-top-right-radius: 0.5rem !important; border-bottom-right-radius: 0.5rem !important; }

      /* Cards: never pure white in light mode, matching the one-big-card surface tone. */
      .card { background-color: #fcfcfc !important; border-radius: 0.5rem !important; }
      html.dark .card { background-color: #141311 !important; }

      /* Docs hero box */
      .oc-hero { background-color: #fcfcfc; border: 1px solid #e5e2dc; }
      html.dark .oc-hero { background-color: #141311; border-color: #26241f; }
      html.dark .oc-hero h1 { color: #edeae4; }

      /* Thin, transparent-track, hide-until-hover scrollbar. */
      ::-webkit-scrollbar { width: 6px; height: 6px; background-color: transparent; }
      ::-webkit-scrollbar-track { background-color: transparent; }
      ::-webkit-scrollbar-thumb { background-color: rgba(155, 155, 155, 0.5); border-radius: 10px; transition: opacity 0.3s ease; opacity: 0; }
      ::-webkit-scrollbar-thumb:hover { background-color: rgba(155, 155, 155, 0.7); }
      *:hover::-webkit-scrollbar-thumb,
      *:focus::-webkit-scrollbar-thumb,
      *:active::-webkit-scrollbar-thumb { opacity: 1; }
      * { scrollbar-width: thin; scrollbar-color: rgba(155, 155, 155, 0.5) transparent; }
    `;
    document.head.appendChild(s);
  }
  return null;
};

<OutcrawlStyles />

`scout.run(task, options)` runs one task to an end and returns what it found. A run that falls short or reaches a cap still returns, with the data it collected. It throws only when it cannot start.

```ts theme={"theme":{"light":"github-light","dark":"catppuccin-mocha"}}
const controller = new AbortController();

const result = await scout.run(task, {
  caps: { steps: 30, duration: '5m', budget: '0.50' },
  schema: { ... },
  signal: controller.signal,
  onStep: (step) => console.log(step.action.description),
});
```

`task` is the task in words, as a non-empty string. Every option is optional. One `Scout` can run many tasks: each run opens its own browser, or its own tab on a browser you passed in, and closes it at the end.

## Caps

`caps` says when the run stops. Reaching a cap is a normal ending, not an error: the result carries what was found.

| Cap | Default | What it limits |
| - | - | - |
| `steps` | `40` | Most actions, as a positive whole number. |
| `duration` | `'10m'` | Wall clock, written as `<n>ms`, `<n>s`, `<n>m` or `<n>h`. |
| `budget` | none | Most model spend, in USD as a decimal string such as `'0.50'`. Needs [`models.rates`](/docs/scout/models#cost); without it, `run` throws `ScoutConfigError`. |

`steps` and `duration` always apply. A run that ends on a cap you set has `status: 'capped'`.

## Schema

`schema` is a JSON Schema for the answer. With one, `result.data` comes back in that shape, and is partly filled on a partial run. Without one, the answer is the agent's own summary, and `result.suggestedSchema` may carry a schema derived from the task that you can pass next time.

```ts theme={"theme":{"light":"github-light","dark":"catppuccin-mocha"}}
type Book = { title: string; price: string };

const result = await scout.run<Book>(
  'On https://books.toscrape.com, open the first Poetry book and report its title and price.',
  {
    schema: {
      type: 'object',
      properties: {
        title: { type: 'string' },
        price: { type: 'string' },
      },
      required: ['title', 'price'],
    },
  },
);
```

The type parameter only types `result.data`; the schema is what shapes it.

## Cancelling

`signal` takes an `AbortSignal`. Aborting it stops the run, which ends with `stopReason: 'cancelled'` and returns what it found so far.

## Watching steps

`onStep` is called with each step as it is recorded. It must not throw. A step carries, among other fields:

* `index`: its position, from 0;
* `action.description`: what it did, in words, and `action.method`, for example `click` or `fill`;
* `reasoning`: the model's stated reason, when it gave one;
* `usage`: the tokens it used.

## The result

`run` resolves to a `ScoutResult`:

| Field | What it is |
| - | - |
| `id` | The run's id. |
| `status` | `completed`, `partial` (fell short, see `error`), `capped` (a cap you set was reached) or `failed`. |
| `data` | The answer: schema-shaped with a schema, the agent's summary without one; partly filled on a partial run. Absent when the task asked nothing. |
| `stopReason` | Why it stopped, for example `task-complete`, `schema-satisfied`, `max-steps`, `max-duration`, `max-budget` or `cancelled`. |
| `error` | On a partial or failed run, what went wrong or what is still missing. |
| `steps`, `stepsUsed` | Every step in order, and how many there were. |
| `goals` | The plan the agent made and how each part ended. Absent when it made none. |
| `findings` | Facts the run established on the way, including on a run that ended early. |
| `suggestedSchema` | A schema derived from the task, when you passed none. |
| `usage` | Tokens used across the run. |
| `costUsd` | Model spend in USD, as a decimal string. Absent when it is not known; see [cost](/docs/scout/models#cost). |
| `durationMs`, `pages` | Wall time, and pages loaded. |
| `replayUrl` | On Outcrawl's cloud, a link to watch the run. Absent on other browsers, or when the recording was declined. |
| `recordingDeclined` | On Outcrawl's cloud, `true` when you passed `record: false`. |

```ts theme={"theme":{"light":"github-light","dark":"catppuccin-mocha"}}
if (result.status === 'completed') {
  console.log(result.data);
} else {
  // what is still missing, and what it found anyway
  console.log(result.status, result.stopReason, result.error);
  console.log(result.data);
}
```

## Errors

`new Scout` and `run` throw only when a run cannot start. Both errors are exported from `@outcrawl/scout`, and each message says what to pass instead.

| Error | When |
| - | - |
| `ScoutConfigError` | A configuration Scout cannot run with: no `models.hands`, a bad option, an empty task, a cap it cannot read, `caps.budget` without `models.rates`, or `browser: 'outcrawl'` without an API key. |
| `ScoutBrowserError` | The browser could not be started, reached or connected to: no `playwright-core` or `puppeteer-core` to launch with, a CDP address that does not answer, or the cloud refusing the session. |

Everything after the start, including a model endpoint that refuses a request, ends the run with a `status` and an `error` rather than a throw.

```ts theme={"theme":{"light":"github-light","dark":"catppuccin-mocha"}}
import { Scout, ScoutBrowserError, ScoutConfigError } from '@outcrawl/scout';

try {
  const result = await scout.run(task);
} catch (error) {
  if (error instanceof ScoutConfigError) {
    console.error('fix the options:', error.message);
  } else if (error instanceof ScoutBrowserError) {
    console.error('no browser:', error.message);
  } else {
    throw error;
  }
}
```

## Logging

Pass `logger` to `new Scout` to hear what Scout is doing. Any structured logger fits: it needs `info(event, fields)` and `warn(event, fields)`.

```ts theme={"theme":{"light":"github-light","dark":"catppuccin-mocha"}}
const scout = new Scout({ browser: 'outcrawl', models, logger: console });
```

Scout logs which browser a run opened (`scout.browser`), a model whose cost could not be known (`scout.cost_unknown`), and a cloud session that published no replay link (`scout.no_replay_url`).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.