# AI Field

An AI Field is a collection field with a prompt: the AI fills it with the data of each row (classify a lead, summarize a note, pull the city out of an address). Through the API you can fill **one cell** or **a whole column**.

> Scope `items:generate`, on **live** keys only: a `met_test_` key gets `403` with `test_mode_restricted`. **It consumes Energy for each cell**, just like filling it in the panel; with no balance it responds `402` with `energy_depleted`. The prompt is configured on the collection from the panel.

```ts
import { Met } from '@meteor.ia/sdk';

const met = new Met(process.env.MET_KEY!, { workspaceId: 42 });
```

## One cell

Synchronous: the response arrives once the cell is already written to the item.

```ts
const { value } = await met.aiFields.generate(5, 901, 'resumen');
```

## One column

Fills up to **100 rows per call**, in the background. By default it only takes empty cells. To go through a large collection, follow the cursor: each call starts after the last item the previous one looked at, so no row is charged twice.

```ts
let after: number | undefined;
do {
  const run = await met.aiFields.createRun(5, 'resumen', { only_empty: true, starting_after: after });
  const done = await met.aiFields.waitForRun(run.id);
  console.log(done.status, done.succeeded, done.failed);
  if (done.status !== 'completed') break; // it stopped: check stop_reason
  after = done.has_more ? done.next_starting_after ?? undefined : undefined;
} while (after !== undefined);
```

| Run field | What it means |
|---|---|
| `status` | `queued`, `running`, `completed`, `stopped` or `failed`. |
| `requested` / `processed` / `succeeded` / `failed` | Rows taken, attempted, written (each one was charged) and failed. A row someone filled while the run was moving forward is skipped without charging: it counts in `processed`, not in `succeeded` or `failed`. |
| `has_more` / `next_starting_after` | There may be more rows: when it finishes, call again with `starting_after` = `next_starting_after`. |
| `stop_reason` | `energy_depleted` (top up and call again), `plan_inactive`, `interrupted` or `error`. |

If Energy runs out halfway, the run ends as `stopped` and what was already written is kept. While a run of the same field is still in progress, another one responds `409` with `ai_field_run_in_progress`.

With `only_empty: false` you also regenerate the cells that already had a value, and each one is charged again; with the cursor no row is repeated either. With `item_ids` you choose the rows (up to 100; there is no cursor or `has_more` there, and also sending `starting_after` responds `400`).

If the AI leaves a cell empty, that execution was already charged: later calls with `only_empty` will not take it again. The same applies if it fails after the charge (the answer is not one of the field's options, or it could not be written). To try it again, pass it in `item_ids`.

If the field is a **select**, the AI can only answer one of its options. If it answers something else, the cell is not written —the execution is still charged— and it counts as failed; on a single cell it responds `422` with `ai_field_invalid_option`. If it happens often, review the field's prompt.

## Errors

| Code | When |
|---|---|
| `not_an_ai_field` (400) | The field exists but has no prompt. |
| `ai_field_not_found` (404) | The collection does not have that field. |
| `collection_not_found` / `item_not_found` (404) | The collection or the item does not belong to your workspace. |
| `ai_field_invalid_option` (422) | The field is a select and the AI answered something that is not one of its options. Nothing was written. |
| `energy_depleted` (402) | Out of Energy. |
| `ai_field_run_in_progress` (409) | There is already a run of that field in progress. |
