# Handler commands

> The Handler commands routes of the LightHouse API: 8 operations, generated from the OpenAPI document.

Every request goes to your tenant’s own host, `https://<tenant id>.atlanticagenticlabs.com`, and is scoped to that tenant by row-level security. The examples read `AAL_TENANT`, `AAL_KEY` and your Access service token from the environment: see [Authentication](/api/authentication/).

## Agent Commands

`GET /api/v1/agents/{agent_id}/commands`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Parameter  | In   | Type   | Required |
| ---------- | ---- | ------ | -------- |
| `agent_id` | path | string | yes      |

| Status | Meaning                                                                                        |
| ------ | ---------------------------------------------------------------------------------------------- |
| 200    | OK: the JSON document this route reads.                                                        |
| 400    | Bad request, `bad_query`: a path or query parameter, or a body field, is missing or not valid. |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/).    |

**curl**

```bash
curl "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.get(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands", headers=headers)
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands`,
  {
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
    },
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## Issue Command

`POST /api/v1/agents/{agent_id}/commands`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Parameter  | In   | Type   | Required |
| ---------- | ---- | ------ | -------- |
| `agent_id` | path | string | yes      |

**Request body** (JSON):

```json
{
  "type": "agent.pause",
  "params": {
    "reason": "Supplier feed down"
  },
  "deployment": "example-air-prod",
  "ttl_s": 300
}
```

| Status | Meaning                                                                                        |
| ------ | ---------------------------------------------------------------------------------------------- |
| 202    | Accepted: recorded and queued. It is carried out after this answer, not before it.             |
| 400    | Bad request, `bad_query`: a path or query parameter, or a body field, is missing or not valid. |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/).    |

**202 response:**

```json
{
  "command_id": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
  "status": "queued",
  "agent": "research:summary",
  "deployment": "example-air-prod",
  "type": "agent.pause",
  "params": {
    "reason": "Supplier feed down"
  },
  "reason": null,
  "detail": null,
  "issued_by": {
    "email": "handler@example.test",
    "role": "handler",
    "kind": "client"
  },
  "flagged": false,
  "issued_at": "2026-10-30T09:00:00Z",
  "expires_at": "2026-10-30T09:05:00Z",
  "updated_at": "2026-10-30T09:00:00Z"
}
```

**curl**

```bash
curl -X POST "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"type":"agent.pause","params":{"reason":"Supplier feed down"},"deployment":"example-air-prod","ttl_s":300}'
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.post(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands", headers=headers, json={
      "type": "agent.pause",
      "params": {
        "reason": "Supplier feed down"
      },
      "deployment": "example-air-prod",
      "ttl_s": 300
    })
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "type": "agent.pause",
      "params": {
        "reason": "Supplier feed down"
      },
      "deployment": "example-air-prod",
      "ttl_s": 300
    }),
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## One Command

`GET /api/v1/agents/{agent_id}/commands/{command_id}`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Parameter    | In   | Type   | Required |
| ------------ | ---- | ------ | -------- |
| `agent_id`   | path | string | yes      |
| `command_id` | path | string | yes      |

| Status | Meaning                                                                                        |
| ------ | ---------------------------------------------------------------------------------------------- |
| 200    | OK: the JSON document this route reads.                                                        |
| 400    | Bad request, `bad_query`: a path or query parameter, or a body field, is missing or not valid. |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/).    |

**curl**

```bash
curl "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands/COMMAND_ID" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.get(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands/COMMAND_ID", headers=headers)
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/agents/AGENT_ID/commands/COMMAND_ID`,
  {
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
    },
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## Decide

`POST /api/v1/approvals/decisions`

An approval screen that is not per agent: the same command as `approval.decide` on `/agents/{agent}/commands`.

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

**Request body** (JSON):

```json
{
  "agent": "research:summary",
  "run_id": "run-0001",
  "decision": "approve",
  "reason": "Checked against the source pack",
  "evidence_sha256": "9f86d081884c7d65...",
  "deployment": "example-air-prod",
  "ttl_s": 300
}
```

| Status | Meaning                                                                                     |
| ------ | ------------------------------------------------------------------------------------------- |
| 202    | Accepted: recorded and queued. It is carried out after this answer, not before it.          |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/). |

**curl**

```bash
curl -X POST "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/approvals/decisions" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"agent":"research:summary","run_id":"run-0001","decision":"approve","reason":"Checked against the source pack","evidence_sha256":"9f86d081884c7d65...","deployment":"example-air-prod","ttl_s":300}'
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.post(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/approvals/decisions", headers=headers, json={
      "agent": "research:summary",
      "run_id": "run-0001",
      "decision": "approve",
      "reason": "Checked against the source pack",
      "evidence_sha256": "9f86d081884c7d65...",
      "deployment": "example-air-prod",
      "ttl_s": 300
    })
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/approvals/decisions`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "agent": "research:summary",
      "run_id": "run-0001",
      "decision": "approve",
      "reason": "Checked against the source pack",
      "evidence_sha256": "9f86d081884c7d65...",
      "deployment": "example-air-prod",
      "ttl_s": 300
    }),
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## Get Command Settings

`GET /api/v1/command-settings`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Status | Meaning                                                                                     |
| ------ | ------------------------------------------------------------------------------------------- |
| 200    | OK: the JSON document this route reads.                                                     |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/). |

**200 response:**

```json
{
  "enabled": true,
  "types": {
    "agent.pause": true,
    "approval.decide": true
  },
  "staff_may_issue": false,
  "version": "3",
  "available": true,
  "key_id": "cmd-2026-10",
  "types_known": [
    "agent.pause",
    "agent.resume",
    "approval.decide"
  ],
  "deployments": []
}
```

**curl**

```bash
curl "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/command-settings" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.get(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/command-settings", headers=headers)
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/command-settings`,
  {
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
    },
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## Put Command Settings

`PUT /api/v1/command-settings`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Status | Meaning                                                                                     |
| ------ | ------------------------------------------------------------------------------------------- |
| 200    | OK: the request was carried out. The answer is JSON.                                        |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/). |

**curl**

```bash
curl -X PUT "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/command-settings" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.put(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/command-settings", headers=headers)
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/command-settings`,
  {
    method: "PUT",
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
    },
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## All Commands

`GET /api/v1/commands`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Status | Meaning                                                                                     |
| ------ | ------------------------------------------------------------------------------------------- |
| 200    | OK: the JSON document this route reads.                                                     |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/). |

**curl**

```bash
curl "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/commands" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.get(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/commands", headers=headers)
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/commands`,
  {
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
    },
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

## A Command

`GET /api/v1/commands/{command_id}`

**Authentication:** A person’s session, or a machine key with your Access service token, as the route’s role allows. A route that approves, decides, pays or changes a limit refuses a machine key (`person_required`).

| Parameter    | In   | Type   | Required |
| ------------ | ---- | ------ | -------- |
| `command_id` | path | string | yes      |

| Status | Meaning                                                                                        |
| ------ | ---------------------------------------------------------------------------------------------- |
| 200    | OK: the JSON document this route reads.                                                        |
| 400    | Bad request, `bad_query`: a path or query parameter, or a body field, is missing or not valid. |
| 4XX    | Refused: `{error, message}` with a fixed `error` code, listed under [Errors](/api/errors/).    |

**curl**

```bash
curl "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/commands/COMMAND_ID" \
  -H "Authorization: Bearer $AAL_KEY" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"
```

**Python**

```python
import os

import httpx

headers = {
    "Authorization": f"Bearer {os.environ['AAL_KEY']}",
    "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"],
    "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],
}
r = httpx.get(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/commands/COMMAND_ID", headers=headers)
r.raise_for_status()
print(r.json())
```

**TypeScript**

```ts
const res = await fetch(
  `https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/commands/COMMAND_ID`,
  {
    headers: {
      Authorization: `Bearer ${process.env.AAL_KEY}`,
      "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!,
      "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!,
    },
  },
);
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
console.log(await res.json());
```

Source: https://docs.atlanticagenticlabs.com/api/reference/handler-commands/
