# HTTP API
URL: /docs/alineod/api-reference/http-api

Every alineod route — runs, agents, control actions, and results.



Base URL: `http://localhost:4600` by default. Request bodies are JSON. Errors are returned as
`{ "error": "<message>" }` with an appropriate status; an invalid body is `400` and names each failing field.

| Method   | Path                      | Description                           |
| -------- | ------------------------- | ------------------------------------- |
| `GET`    | `/health`                 | Liveness check.                       |
| `POST`   | `/runs`                   | Create a run and its root agent.      |
| `GET`    | `/runs/:runId`            | The run's spawn tree.                 |
| `DELETE` | `/runs/:runId`            | Stop every live agent in the run.     |
| `GET`    | `/runs/:runId/events`     | The run's event stream (SSE).         |
| `POST`   | `/runs/:runId/agents`     | Spawn a child agent.                  |
| `GET`    | `/agents/:agentId`        | One agent's state and session stats.  |
| `POST`   | `/agents/:agentId/prompt` | Start a new turn.                     |
| `POST`   | `/agents/:agentId/steer`  | Redirect the current turn.            |
| `POST`   | `/agents/:agentId/pause`  | Freeze the agent's container.         |
| `POST`   | `/agents/:agentId/resume` | Thaw a paused container.              |
| `POST`   | `/agents/:agentId/stop`   | Abort and close the agent.            |
| `GET`    | `/agents/:agentId/result` | Get, or wait for, the agent's result. |

## Runs [#runs]

### POST /runs [#post-runs]

Create a run with one root agent. Returns `202`; the sandbox is provisioned in the background and `prompt`, if
set, runs once it's ready.

| Field               | Type    | Description                                    |
| ------------------- | ------- | ---------------------------------------------- |
| `spec`              | object  | An agent spec, validated by the SDK. Required. |
| `prompt`            | string  | First turn to run on the root agent.           |
| `budget.spawnDepth` | integer | Overrides the spec's `spawnDepth`.             |
| `budget.maxAgents`  | integer | Overrides the spec's `maxAgents`.              |

```json
// 202
{ "runId": "r_3f9a1c20", "rootAgentId": "a_7b2e44d1", "state": "provisioning" }
```

If provisioning fails, the root ends with outcome `failed` and the error appears on its `agent_ended` event.

### GET /runs/:runId [#get-runsrunid]

The run's whole tree as a flat list with parent pointers. `asOf` is the highest ledger `seq` reflected in the
response — pass it as `Last-Event-ID` to stream everything after this snapshot.

```json
{
  "runId": "r_3f9a1c20",
  "rootAgentId": "a_7b2e44d1",
  "asOf": 42,
  "agents": [
    {
      "agentId": "a_7b2e44d1",
      "runId": "r_3f9a1c20",
      "parentAgentId": null,
      "depth": 0,
      "spawnIndex": 0,
      "state": "done",
      "specName": "coordinator",
      "sandboxId": "6a69afcb-7a00-437a-9819-e032022cc736",
      "createdAt": 1789000000000,
      "endedAt": 1789000071000,
      "outcome": "success"
    }
  ]
}
```

`404` if the run doesn't exist.

### DELETE /runs/:runId [#delete-runsrunid]

Aborts and closes every live agent in the run, ending each with outcome `aborted`. The run's ledger is kept, so
`GET /runs/:runId` and its event stream still work afterwards. Returns `204`; `404` if the run doesn't exist.

### GET /runs/:runId/events [#get-runsrunidevents]

A Server-Sent Events stream for the whole run. Send `Last-Event-ID` to replay persisted events after that `seq`.
See [Events](/docs/alineod/api-reference/events).

## Agents [#agents]

### POST /runs/:runId/agents [#post-runsrunidagents]

Spawn a child by forking a live parent's sandbox. Returns `202`.

| Field               | Type      | Description                                                                                                       |
| ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `parentAgentId`     | string    | A live agent in this run. Required.                                                                               |
| `spec`              | object    | The child's agent spec. Required.                                                                                 |
| `prompt`            | string    | Turn to run once the child is ready.                                                                              |
| `waitFor`           | string\[] | Agents in this run whose results must settle before the child is forked. Their results are written to `/inputs/`. |
| `budget.spawnDepth` | integer   | Overrides the parent's remaining `spawnDepth`.                                                                    |
| `budget.maxAgents`  | integer   | Overrides the parent's remaining `maxAgents`.                                                                     |
| `idempotencyKey`    | string    | A retry with the same key returns the original child instead of creating another.                                 |

```json
// 202
{ "agentId": "a_c01d9e3a", "state": "provisioning" }
```

`state` is `spawning` when `waitFor` is set.

| Status | When                                                       |
| ------ | ---------------------------------------------------------- |
| `400`  | Invalid body, or `waitFor` names an agent not in this run. |
| `404`  | `parentAgentId` isn't an agent in this run.                |
| `409`  | The parent isn't live.                                     |

A spawn refused by a budget still returns `202`; the child then ends with outcome `budget-exceeded` and a
`budget_denied` event is emitted. See [Fan-out and gather](/docs/alineod/guides/fan-out-gather).

### GET /agents/:agentId [#get-agentsagentid]

The agent's view (same fields as an entry in `GET /runs/:runId`) plus `sessionStats` from the harness when
available. `sessionStats` is omitted while the agent is paused, or if the harness doesn't answer within 2 seconds.
`404` if the agent doesn't exist.

### POST /agents/:agentId/prompt [#post-agentsagentidprompt]

```json
{ "text": "Now write tests for the fix." }
```

Starts a new turn and returns `202` immediately; follow it on the event stream or via the result route. `409` if
the agent isn't live.

### POST /agents/:agentId/steer [#post-agentsagentidsteer]

```json
{ "message": "Focus only on src/auth." }
```

Delivers a steering message to the current turn — after its running tool calls finish, before the next model call.
Returns `202` and emits `agent_steered`. Applies to this agent only.

| Status | When                                   |
| ------ | -------------------------------------- |
| `404`  | No such agent.                         |
| `409`  | The agent isn't live.                  |
| `502`  | The harness didn't accept the message. |

See [Steering and pausing](/docs/alineod/guides/steering-and-pausing#steer).

### POST /agents/:agentId/pause [#post-agentsagentidpause]

Freezes the agent's container. Returns `202` and emits `agent_state_changed` (`to: "paused"`). A no-op if already
paused. `404` if no such agent, `409` if not live, `502` if the sandbox couldn't be paused.

### POST /agents/:agentId/resume [#post-agentsagentidresume]

Thaws a paused container and returns the agent to `running`. Returns `202`. `404` if no such agent, `409` if the
agent isn't paused or isn't live, `502` if the sandbox couldn't be resumed.

### POST /agents/:agentId/stop [#post-agentsagentidstop]

```json
{ "mode": "abort" }
```

Aborts the current turn, closes the sandbox, and ends the agent with outcome `aborted`. The body is optional;
`mode` is `abort` (default) or `drain`, which currently behaves the same. Returns `202`; `404` if no such agent.

## Results [#results]

### GET /agents/:agentId/result [#get-agentsagentidresult]

| Query  | Description                                                                               |
| ------ | ----------------------------------------------------------------------------------------- |
| `wait` | Seconds to hold the request open while the result is pending. Maximum `240`. Default `0`. |

Settled — `200`:

```json
{
  "agentId": "a_e4b7d210",
  "state": "settled",
  "outcome": "success",
  "resultRef": "fs://a_e4b7d210/result.md",
  "result": "Three Landscapes\n\n..."
}
```

Still pending after `wait` — `202`:

```json
{ "agentId": "a_e4b7d210", "state": "pending", "outcome": null, "resultRef": null, "result": null }
```

`404` if the agent doesn't exist. `resultRef` is `null` when a turn failed without producing any text.
