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

# Batch executions

> Run one workflow across many rows of input, paced so you do not overwhelm the target site.

A **batch** runs your workflow once per row of a spreadsheet. You supply the rows and the pacing. The
platform creates one scheduled execution per row, and starts each one when its turn arrives.

<CardGroup cols={2}>
  <Card title="Many inputs, one action" icon="table" horizontal>One row becomes one execution</Card>
  <Card title="Paced" icon="gauge" horizontal>Cap how many run at once, or how many start per interval</Card>
  <Card title="Controllable" icon="circle-pause" horizontal>Pause, resume, or cancel the whole batch</Card>
  <Card title="Tracked" icon="chart-column" horizontal>See how many rows are pending, running, and done</Card>
</CardGroup>

Open a workflow and go to the **Batch** tab to create one.

```mermaid theme={null}
graph LR
    Rows[Rows] --> Mapping[Column mapping]
    Mapping --> Config[Pacing and start time]
    Config --> Batch[Batch]
    Batch --> SE1[Scheduled execution 1]
    Batch --> SE2[Scheduled execution 2]
    Batch --> SE3[Scheduled execution N]
    SE1 --> E1[Execution 1]
    SE2 --> E2[Execution 2]
    SE3 --> E3[Execution N]
```

***

## Create a batch

<Steps>
  <Step title="Add the rows">
    Pick one of three sources.

    | Source                    | What it takes                                                                                    |
    | ------------------------- | ------------------------------------------------------------------------------------------------ |
    | **Upload a spreadsheet**  | A `.csv`, `.xlsx`, or `.xls` file, up to 10 MB. Drop it on the card or click to browse.          |
    | **Import a Google Sheet** | A sheet URL. The `gid` in the URL selects the tab. Without one the platform reads the first tab. |
    | **Enter values**          | Rows you type by hand, up to 1,000 executions.                                                   |

    The file needs a header row. Every row becomes one execution.
  </Step>

  <Step title="Map the columns">
    Tell the platform what each column feeds.

    | Mapping                | Effect                                                         |
    | ---------------------- | -------------------------------------------------------------- |
    | **Input variable**     | Fills one of the workflow's declared inputs.                   |
    | **Agent profile name** | Overrides the batch's default profile for that row.            |
    | **Agent profile ID**   | Same, by ID rather than name.                                  |
    | **Metadata**           | Attaches a key and value to the execution.                     |
    | **Variant key**        | Selects the variant, for a workflow that runs in variant mode. |
    | **Skip**               | Ignores the column.                                            |

    The platform maps a column automatically when its header matches an input name. The match ignores
    case and treats whitespace as underscores. Change any mapping by hand.

    A mapping passes when it satisfies all of these:

    * Every required workflow input has a column.
    * No two columns feed the same field.
    * At least one column is not skipped.
    * Every metadata mapping has a name.

    <Tip>
      The platform saves your mappings per workflow in your browser. Upload a file with the same headers
      and it restores them.
    </Tip>
  </Step>

  <Step title="Preview the rows">
    The preview shows the first 10 rows and how each field resolves. A valid row is marked ready. An
    invalid row shows the reason.

    Fix the spreadsheet and upload it again before you continue.
  </Step>

  <Step title="Configure the batch">
    | Setting                   | What it does                                       |
    | ------------------------- | -------------------------------------------------- |
    | **Batch name**            | Identifies the batch in the list.                  |
    | **Workflow version**      | The published version every row runs.              |
    | **Default agent profile** | The profile or pool for rows that do not name one. |
    | **Start time**            | When the platform starts triggering rows.          |
    | **Pacing**                | How fast the rows go out. See [Pacing](#pacing).   |

    <Info>
      A start time that has already passed starts the batch at once, in the `running` status. A future
      start time creates the batch as `pending`, and it starts itself when the time arrives.
    </Info>

    You can also make the batch repeat. Set it to run on a schedule and each tick re-reads the sheet
    and creates a fresh batch. See [Schedules](/operate/schedules).
  </Step>
</Steps>

***

## Pacing

Pacing has two modes. They limit different things, so pick the one that matches the constraint you
actually have.

### Limit how many run at the same time

Bounds simultaneity. The first rows start straight away, up to the limit. Each time an execution finishes,
the next one starts. The batch works through the sheet as fast as it can without exceeding the cap.

Rows above the cap wait in the `awaiting_capacity` status until a slot frees.

Use this when the target site limits concurrent sessions. Use it also when you want the batch
finished as soon as it can be.

### Limit how many start per interval

Bounds the rate. A fixed number of rows start every interval, whether or not the earlier ones have
finished.

The platform assigns each row a start time when it creates the batch:

```
For the row at index i:
  batchIndex = floor(i / batchSize)
  executeAt  = startAt + (batchIndex × batchInterval seconds)
```

With `batchSize = 5` and `batchInterval = 60`:

| Rows  | Start at         |
| ----- | ---------------- |
| 0–4   | `startAt`        |
| 5–9   | `startAt` + 60s  |
| 10–14 | `startAt` + 120s |
| 15–19 | `startAt` + 180s |

Use this for a site that refuses to be hit faster than a set rate.

<Warning>
  This mode does not bound how many run at once. A new set starts every interval regardless. If an execution
  takes longer than the interval, runs overlap, and the overlap has no ceiling.
</Warning>

<Tip>
  Rows that overlap while sharing one profile compete for the same browser state. Give the batch a
  profile pool instead, so each row gets its own profile. See [Agent profiles](/concepts/profiles).
</Tip>

***

## Batch statuses

```mermaid theme={null}
graph TB
    pending[pending]
    running[running]
    paused[paused]
    completed[completed]
    cancelled[cancelled]

    pending --> running
    pending --> cancelled
    running --> paused
    running --> completed
    running --> cancelled
    paused --> running
    paused --> cancelled

    style completed fill:#dcfce7
    style cancelled fill:#fef3c7
    style running fill:#dbeafe
    style pending fill:#e0e7ff
    style paused fill:#fde68a
```

| Status      | Meaning                                             |
| ----------- | --------------------------------------------------- |
| `pending`   | The batch has a future start time and waits for it. |
| `running`   | The batch is triggering rows.                       |
| `paused`    | A person paused it. No new rows start.              |
| `completed` | Every row has been triggered.                       |
| `cancelled` | The batch stopped. Remaining rows will not start.   |

### Row statuses

Each row inside a batch carries its own status.

| Status              | Meaning                                                  |
| ------------------- | -------------------------------------------------------- |
| `pending`           | Waiting for its start time.                              |
| `awaiting_capacity` | Waiting for a concurrency slot to free.                  |
| `batch_paused`      | Held because someone paused the batch.                   |
| `triggered`         | The execution started.                                   |
| `cancelled`         | This row was cancelled.                                  |
| `failed`            | The row could not start at all, and will not be retried. |

Every row has an execution behind it from the moment you create the batch. That execution holds the
`queued` status until the row's turn arrives. It then moves to `starting` and runs like any other
execution. See [Executions and statuses](/concepts/executions).

***

## Run the batch

Manage batches from the **Batch** tab. Each card shows the name, the status, a progress bar of
triggered rows against total rows, and the timestamps.

<AccordionGroup>
  <Accordion title="Pause">
    Stops new rows from starting. Rows already running continue to the end. Use it to hold a batch
    without losing its place.
  </Accordion>

  <Accordion title="Resume">
    Recalculates the schedule from the current time and continues with the remaining rows.
  </Accordion>

  <Accordion title="Cancel">
    Stops the batch for good. Pending rows are cancelled and will not start. Rows already running
    are not affected.

    <Warning>
      Cancelling a batch cannot be undone.
    </Warning>
  </Accordion>
</AccordionGroup>

Click **View scheduled executions** on a batch card to open the row list. From there you can cancel
one row. Cancel a row first to reschedule it for a different time.

***

## Track progress

Each batch counts its rows.

| Count                 | Meaning                                             |
| --------------------- | --------------------------------------------------- |
| **Total**             | Rows in the batch.                                  |
| **Pending**           | Rows waiting to start.                              |
| **Triggered**         | Rows that have started.                             |
| **Cancelled**         | Rows that were cancelled.                           |
| **Awaiting capacity** | Rows waiting for a concurrency slot.                |
| **Errored**           | Rows that could not start, and will not be retried. |

The card also shows elapsed duration and cycle time. Cycle time is wall-clock time per triggered
row. While a batch runs, the card projects a finish time at the current rate.

Cycle time measures throughput, not how long a single execution takes. It falls when you raise concurrency.

### Find the executions

Batch runs are ordinary executions. List them with the executions endpoint. `triggerSource=schedule`
covers every execution the platform started for you, from a batch or from a schedule.

```bash theme={null}
curl -G "https://odyssey.asteroid.ai/agents/v2/executions" \
  -H "X-Asteroid-Agents-Api-Key: $ASTEROID_API_KEY" \
  --data-urlencode "agentId=$AGENT_ID" \
  --data-urlencode "triggerSource=schedule" \
  --data-urlencode "status=failed"
```

To pull one batch on its own, map a column to metadata and filter on it:
`GET /executions?metadataKey=batch&metadataValue=march-invoices`.

For a large batch, use [webhooks](/operate/webhooks-and-slack) instead of polling. Asteroid calls
you on every status change, and emits `BATCH_STARTED` and `BATCH_COMPLETED` for the batch itself.

***

## Practices that pay off

<AccordionGroup>
  <Accordion title="Test with 5 rows first">
    Run a small batch before a large one. It proves the column mapping, the input
    formatting, and the workflow's behaviour on real data. Five runs is a cheap rehearsal.
  </Accordion>

  <Accordion title="Start conservative on pacing">
    Begin with a low limit and raise it. Too many concurrent executions overwhelm the target site,
    or trigger its rate limiting. Every row then fails for the same reason.
  </Accordion>

  <Accordion title="Use a profile pool">
    A pool hands each row its own profile. That spreads the load across credentials, and stops two
    runs sharing one browser state. See [Agent profiles](/concepts/profiles).
  </Accordion>

  <Accordion title="Map a metadata column">
    Map your own order ID or record ID to metadata. Every execution then carries it, and
    `GET /executions?metadataKey=…&metadataValue=…` finds the run for any row.
  </Accordion>
</AccordionGroup>

***

## Next

<CardGroup cols={2}>
  <Card title="Schedules" icon="clock" href="/operate/schedules" horizontal>Repeat a batch on a cron schedule</Card>
  <Card title="Agent profiles" icon="id-card" href="/concepts/profiles" horizontal>Profiles and pools for concurrent executions</Card>
  <Card title="Webhooks and Slack" icon="webhook" href="/operate/webhooks-and-slack" horizontal>Get told when a row finishes</Card>
  <Card title="Executions and statuses" icon="activity" href="/concepts/executions" horizontal>What each execution does after it starts</Card>
</CardGroup>
