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

# Run agents via API

> Create a run, follow its status, and collect the agent's answer

A **run** is one unit of agent work started by your system: you send an instruction, the agent executes it, and the run carries the status and the result. This page walks through the full lifecycle — create, poll, collect, cancel.

## Before you start

* An API token with `read_write` mode, from **Settings → API tokens** ([authentication](/api/overview#authentication)).
* The agent's ID, visible on the agent page in the dashboard.

## Create a run

Send the instruction in `input.message`. If the run is reacting to an event, put the event's payload in `input.data` — the agent receives it as data, never as instructions.

```bash theme={null}
curl -X POST https://app.leme.ai/api/v1/agents/AGENT_ID/runs \
  -H "Authorization: Bearer leme_pat_v1_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: lead-4821" \
  -d '{
    "input": {
      "message": "Qualify this lead and reply with a short summary.",
      "data": { "leadId": "4821", "source": "landing-page" }
    },
    "metadata": { "leadId": "4821" }
  }'
```

<ParamField body="input.message" type="string" required>
  The instruction for the agent. Up to 128 KiB.
</ParamField>

<ParamField body="input.data" type="object">
  Free-form JSON with event data, up to 128 KiB. Framed as untrusted data for
  the agent — use it for payloads coming from the outside world.
</ParamField>

<ParamField body="metadata" type="object">
  Up to 16 string keys (values up to 512 characters). Echoed back on the run
  and in webhooks — use it to correlate with records in your system.
</ParamField>

<ParamField body="sessionId" type="string">
  Continue an existing API session of this agent instead of starting a new
  conversation. Runs on the same session are processed in order.
</ParamField>

<ParamField body="callbackUrl" type="string">
  HTTPS URL notified when the run finishes. See
  [Completion webhooks](/api/webhooks).
</ParamField>

<ParamField body="title" type="string">
  Optional title for the new session, shown in the dashboard.
</ParamField>

The response is `202 Accepted` with the run resource:

```json theme={null}
{
  "id": "run_id",
  "object": "agent.run",
  "agentId": "agent_id",
  "sessionId": "session_id",
  "status": "queued",
  "statusDetail": null,
  "origin": "api",
  "input": { "message": "Qualify this lead and reply with a short summary." },
  "output": null,
  "error": null,
  "metadata": { "leadId": "4821" },
  "createdAt": 1720000000000,
  "completedAt": null,
  "urls": { "self": "/api/v1/runs/run_id" }
}
```

<Note>
  Always send an `Idempotency-Key`. If your request is retried, you get the
  original run back instead of a duplicate. Details in the
  [API overview](/api/overview#idempotency).
</Note>

## Follow the run

Poll the URL from `urls.self` until the status is terminal:

```bash theme={null}
curl https://app.leme.ai/api/v1/runs/RUN_ID \
  -H "Authorization: Bearer leme_pat_v1_..."
```

| Status             | Meaning                                                                                            | Terminal |
| ------------------ | -------------------------------------------------------------------------------------------------- | -------- |
| `queued`           | Waiting to start                                                                                   | No       |
| `in_progress`      | The agent is working. `statusDetail: "delegated"` means it handed work to a longer-running process | No       |
| `waiting_approval` | Paused for a human approval in the dashboard                                                       | No       |
| `completed`        | Done — `output.text` has the agent's answer                                                        | Yes      |
| `failed`           | Something went wrong — see `error.code` and `error.message`                                        | Yes      |
| `canceled`         | Canceled before it started                                                                         | Yes      |

Non-terminal responses include a `retry-after` header with a suggested polling interval. When the run completes:

```json theme={null}
{
  "id": "run_id",
  "status": "completed",
  "output": { "text": "High-priority lead: decision maker at a 200-person company..." },
  "completedAt": 1720000042000
}
```

<Note>
  A run in `waiting_approval` resumes after someone approves the pending action
  in the dashboard. If you registered a `callbackUrl`, you also receive a
  `run.waiting_approval` event at that moment — useful to alert the approver.
</Note>

Prefer not to poll? Register a `callbackUrl` and receive a signed webhook on completion — see [Completion webhooks](/api/webhooks).

## List runs

```bash theme={null}
curl "https://app.leme.ai/api/v1/agents/AGENT_ID/runs?limit=20" \
  -H "Authorization: Bearer leme_pat_v1_..."
```

Returns `{ "runs": [...], "nextCursor": "..." }`, newest first. Pass `cursor` to fetch the next page and `status` to filter (for example `status=failed`).

## Cancel a run

```bash theme={null}
curl -X POST https://app.leme.ai/api/v1/runs/RUN_ID/cancel \
  -H "Authorization: Bearer leme_pat_v1_..."
```

Only runs still in `queued` can be canceled. A run already executing returns `409 not_cancellable`; canceling an already-finished run is harmless and returns the resource unchanged.

## Continue a conversation

Each run without a `sessionId` starts a fresh session. To keep context across runs — a back-and-forth with the same agent — reuse the `sessionId` returned by the first run:

```bash theme={null}
curl -X POST https://app.leme.ai/api/v1/agents/AGENT_ID/runs \
  -H "Authorization: Bearer leme_pat_v1_..." \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "SESSION_ID",
    "input": { "message": "Now draft a follow-up email for that lead." }
  }'
```

The session appears in the dashboard like any other conversation, so your team can read it and pick it up at any time.
