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

# Agent Runs

> Start, stream, and govern headless agent runs programmatically

# Agent Runs

An **agent run** executes a configured agent headlessly — no chat UI, no human
at the keyboard. Runs are the programmatic core of NexSpace Headless AI: the
same durable path backs API-initiated runs, [automations](/concepts/automations)
(schedule/event triggers), and the [`nexspace agents run`](/cli/commands) CLI
command.

Every run requires the `agents:run` scope on the API key.

## Lifecycle

```
create ──▶ running ──┬─▶ completed
                     ├─▶ error
                     ├─▶ rejected
                     └─▶ pending_approval ──(approve)──▶ running ──▶ completed
                                           └─(reject)───▶ rejected
```

| Status             | Meaning                                                                        |
| ------------------ | ------------------------------------------------------------------------------ |
| `running`          | The agent loop is executing.                                                   |
| `completed`        | The run finished; `content` + `toolsInvoked` are populated.                    |
| `pending_approval` | A risky (`require_approval`) tool paused the run. See [Approvals](#approvals). |
| `error`            | The run failed; `error` carries the reason.                                    |
| `rejected`         | A pending action was rejected, ending the run.                                 |

Runs are **persisted durably** (`headless_agent_runs`) — state survives server
restarts and is readable across instances. Orphaned runs are reconciled and old
runs are pruned on a schedule.

## Start a run

```bash theme={null}
curl -X POST https://api.nexspace365.com/api/agents/42/runs \
  -H "Authorization: Bearer nex_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "seedMessage": "Summarize open shifts for facility 3 and flag coverage gaps." }'
# → 202 { "runId": "run_abc", "status": "running" }
```

A second run started while one is already executing for the same agent returns
`409 AGENT_BUSY` — the **one-run-per-agent** guard prevents overlapping runs.

### Run identity

Each run acts as `runAsUserId`, which drives tool scope and RBAC — a run can
never do more than that user is permitted. It defaults to the caller; binding a
**different** user is restricted to internal operators (otherwise
`403 RUN_AS_FORBIDDEN`).

## Poll, list, and cancel

```bash theme={null}
# Current state
curl https://api.nexspace365.com/api/agents/42/runs/run_abc \
  -H "Authorization: Bearer nex_live_YOUR_KEY"

# Recent runs for an agent (newest first; optional ?status= and ?limit=)
curl https://api.nexspace365.com/api/agents/42/runs \
  -H "Authorization: Bearer nex_live_YOUR_KEY"

# Soft-cancel an executing run
curl -X DELETE https://api.nexspace365.com/api/agents/42/runs/run_abc \
  -H "Authorization: Bearer nex_live_YOUR_KEY"
```

## Stream a run

Stream run events as they happen over Server-Sent Events:

```bash theme={null}
curl -N https://api.nexspace365.com/api/agents/42/runs/run_abc/stream \
  -H "Authorization: Bearer nex_live_YOUR_KEY" \
  -H "Accept: text/event-stream"
```

Each SSE frame carries a monotonic `id`. If the connection drops, reconnect with
a `Last-Event-ID` header to replay the frames you missed — the same resumable
transport described in [MCP](/concepts/mcp#streaming-a-tool-call-streamable-http).
The CLI does this for you: `nexspace agents run 42 --output-format stream-json`.

## Approvals

When a run invokes a tool that requires approval (see
[autonomy](#autonomy)), it transitions to `pending_approval` and exposes
`pendingApprovalIds` instead of executing unattended. List the pending actions,
then approve or reject — approving **resumes the agent loop**, it does not merely
run the one tool.

```bash theme={null}
# What is this run waiting on?
curl https://api.nexspace365.com/api/agents/42/runs/run_abc/approvals \
  -H "Authorization: Bearer nex_live_YOUR_KEY"

# Approve (requires the agents:approve scope) → run resumes
curl -X POST https://api.nexspace365.com/api/approvals/1001/approve \
  -H "Authorization: Bearer nex_live_YOUR_KEY"

# …or reject → run ends as rejected
curl -X POST https://api.nexspace365.com/api/approvals/1001/reject \
  -H "Authorization: Bearer nex_live_YOUR_KEY"
```

## Autonomy

An agent's autonomy setting decides what happens on a risky write:

* **`require_approval`** — pause at `pending_approval` and wait for a human (or
  an approver workflow wired to the webhook below).
* **`auto_execute`** — perform the write unattended (use only when the writes
  are safe to run without review).

## Lifecycle webhooks

Subscribe to run lifecycle events instead of polling (see
[Webhooks](/concepts/webhooks)):

* `agent_run.pending_approval`
* `agent_run.completed`
* `agent_run.failed`

## See also

* [Automations](/concepts/automations) — fire runs on a schedule or business event.
* [MCP](/concepts/mcp) — the tool layer runs invoke.
* [CLI commands](/cli/commands) — `nexspace agents run`.
