# Agent: Todos

**Page:** api/agent/todos

[Download Raw Markdown](./api/agent/todos.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



The Agent: Todos endpoints let you file, read, update, claim, run, snooze, and archive master todos in the agent's per-cwd todo store. You can also approve or deny run proposals, post comments to a todo's timeline (with or without kicking an orchestrator turn), kick autonomous worker runs, and trigger an LLM triage pass over the inbox. Every operation that targets a single todo uses the todo's `{id}` in the path; proposal sub-resources add `{pid}`.

These routes resolve the daemon's `todos.*` JSON-RPC actions. The gateway holds no service-level auth of its own — `hoody-proxy` is the network boundary (kit network-position trust) — and forwards the body plus request-scope headers (cwd, config_dir, container, realm) to the daemon. Several of these routes are **J-class ops** (run, approve_proposal, triage, purge): they spend model budget on autonomous LLM activity with no `_machine_confirmed` gate on the daemon RPC, and the daemon's own `systemAdminGate` may still `403 admin_unauthorized` when a Unix-socket admin capability is configured.

## Reading and listing

### `GET /api/v1/agent/todos`

Lists master todos for the requesting cwd/config_dir, with the current CAS revision. Filters ride the request body (`states`, `tags`, `query`, `open_only`, `all`) — there is no query-param filter alias (the daemon applies typed filters a flat query string cannot supply). Active-realm-scoped: a per-request realm header is rejected.



```bash
curl -X GET 'https://api.hoody.com/api/v1/agent/todos?page=1&limit=50' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{"states":["open"],"open_only":true}'
```


```ts
const page = await client.agent.todos.listTodosIterator({
  page: 1,
  limit: 50,
  XHoodyCwd: '/Users/me/projects/my-app',
  data: { states: ['open'], open_only: true },
});

for await (const todo of page) {
  console.log(todo.id, todo.title);
}
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `page` | query | integer | No | 1-based page number for pagination. |
| `limit` | query | integer | No | Maximum items per page (`0` = no pagination). |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1): the `.hoody` project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. `POST /todos`; `createTodo` also accepts a body `cwd`). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1) selecting which on-disk `.hoody` install a stateless read/write resolves (HoodyPaths). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id (also accepted as `?realm=`). Rejected (400 `realm_scope_unsupported`) on active-only / no-realm routes. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of the `X-Hoody-Realm` header (read only when the header is absent): `"global"` or a 24-hex id. Rejected (400 `realm_scope_unsupported`) on active-only / no-realm routes. |

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `states` | array | No | Filter to these todo states (array of strings). |
| `tags` | array | No | Filter to todos carrying these tags (array of strings). |
| `query` | string | No | Free-text filter over title/body. |
| `open_only` | boolean | No | When true, only open (non-terminal) todos. |
| `all` | boolean | No | When true, include archived/closed todos. |

```json
{
  "states": ["open"],
  "tags": ["bug"],
  "query": "crash on startup",
  "open_only": true,
  "all": false
}
```

### Responses



```json
{
  "items": [
    {
      "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
      "title": "Investigate crash on startup",
      "body": "Reproduces on macOS 14 only.",
      "state": "open",
      "priority": 2,
      "tags": ["bug", "p1"],
      "cwd": "/Users/me/projects/my-app",
      "created_at": "2026-01-15T10:32:11Z",
      "revision": 4
    }
  ],
  "meta": {
    "total": 137,
    "page": 1,
    "limit": 50
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`: its source IP is private/local (in-container loopback, the bridge, the host, or a sibling container). The gateway has no service-level auth — authorization is owned by `hoody-proxy`, which is the only party that can reach it (TPROXY preserves the real public client IP). Kit network-position trust. | Reach the agent through `hoody-proxy` (e.g. `hoody agent …` → platform → proxy), not by connecting to the container directly. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |



### `GET /api/v1/agent/todos/revision`

Returns the current CAS revision token of the todo store (`todos.revision`) for optimistic concurrency on updates. Pass the returned `revision` on `PATCH /todos/{id}` to guard against concurrent updates.



```bash
curl -X GET 'https://api.hoody.com/api/v1/agent/todos/revision' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app'
```


```ts
const rev = await client.agent.todos.getTodosRevision({
  XHoodyCwd: '/Users/me/projects/my-app',
});

console.log('current revision:', rev.revision);
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Responses



```json
{
  "revision": 42
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy` (e.g. `hoody agent …` → platform → proxy). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |



### `GET /api/v1/agent/todos/{id}`

Returns the full todo record including timeline and proposals (`todos.read`).



```bash
curl -X GET 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app'
```


```ts
const todo = await client.agent.todos.getTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
});

console.log(todo.title, todo.timeline.length, 'events');
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "title": "Investigate crash on startup",
  "body": "Reproduces on macOS 14 only.",
  "state": "open",
  "priority": 2,
  "tags": ["bug", "p1"],
  "cwd": "/Users/me/projects/my-app",
  "revision": 4,
  "timeline": [
    {
      "kind": "create",
      "at": "2026-01-15T10:32:11Z",
      "by": "user"
    },
    {
      "kind": "comment",
      "at": "2026-01-15T11:02:48Z",
      "by": "user",
      "text": "Confirmed on 14.3 with the production build."
    }
  ],
  "proposals": [
    {
      "id": "p1",
      "kind": "run",
      "summary": "Patch the macOS-specific path resolver",
      "status": "pending"
    }
  ]
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



## Creating and updating

### `POST /api/v1/agent/todos`

Files a new master todo (`todos.create`). Deterministic triage (normalize, fingerprint-dedupe, defaults) runs server-side. The todo's working directory is taken from the body `cwd` OR, if omitted, the `X-Hoody-Cwd` request-scope header; one of the two is required (`todos.create` rejects an empty cwd).



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Investigate crash on startup",
    "body": "Reproduces on macOS 14 only.",
    "priority": 2,
    "tags": ["bug", "p1"]
  }'
```


```ts
const filed = await client.agent.todos.createTodo({
  XHoodyCwd: '/Users/me/projects/my-app',
  data: {
    title: 'Investigate crash on startup',
    body: 'Reproduces on macOS 14 only.',
    priority: 2,
    tags: ['bug', 'p1'],
  },
});

console.log(filed.id, 'deduped:', filed.deduped);
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `title` | string | Yes | Todo title. |
| `body` | string | No | Todo body / description. |
| `priority` | integer | No | Optional priority band `0..4` (`0` = P0 urgent … `4` = P4 someday); defaults to `2`. The daemon reads a JSON number — a string value is NOT accepted (it silently defaults), so send an integer. |
| `tags` | array | No | Optional tags. |
| `cwd` | string | No | The todo's working directory (labels the record's `computer`/`path`). Defaults to the `X-Hoody-Cwd` request-scope header when omitted; one of the two must be set. |

```json
{
  "title": "Investigate crash on startup",
  "body": "Reproduces on macOS 14 only.",
  "priority": 2,
  "tags": ["bug", "p1"],
  "cwd": "/Users/me/projects/my-app"
}
```

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "deduped": false,
  "revision": 1
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). The gateway rejects an oversized body at the edge (`http.MaxBytesReader`) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `PATCH /api/v1/agent/todos/{id}`

Applies a CAS-guarded field patch / state transition to a todo (`todos.update`). Pass the current revision; a stale revision is rejected with `409 todo_conflict` and you must refetch via `getTodosRevision` and retry.



```bash
curl -X PATCH 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{
    "revision": 4,
    "state": "in_progress",
    "priority": 1
  }'
```


```ts
const updated = await client.agent.todos.updateTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
  data: {
    revision: 4,
    state: 'in_progress',
    priority: 1,
  },
});

console.log('new revision:', updated.revision);
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `revision` | integer | Yes | The current store revision (CAS token from `getTodosRevision`); a stale value is rejected. |
| `title` | string | No | New title. |
| `body` | string | No | New body. |
| `state` | string | No | New state transition. |
| `priority` | integer | No | New priority. |
| `rank` | integer | No | New ordering rank. |
| `tags` | array | No | New tag set. |
| `cwd` | string | No | Retarget the todo's working directory. |

```json
{
  "revision": 4,
  "state": "in_progress",
  "priority": 1
}
```

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "revision": 5,
  "state": "in_progress"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "todo_conflict",
  "message": "todo_conflict: revision mismatch (refetch and retry)"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `todo_conflict` | Todo revision conflict | The supplied revision is stale (a concurrent update advanced the store). Refetch the current revision and retry. | `GET` the todo's current revision (`getTodosRevision`) and re-issue the update. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



## Lifecycle actions

### `POST /api/v1/agent/todos/{id}/archive`

Archives a todo (`todos.archive`). The `{id}` comes from the path; the body is optional and forwarded verbatim to `todos.archive`.



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/archive' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.archiveTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.archive` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch.

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "archived": true
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/{id}/claim`

Claims a todo for the caller (`todos.claim`).



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/claim' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.claimTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.claim` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch.

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "claimed_by": "session-9a7b3c",
  "claimed_at": "2026-01-15T12:14:02Z"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/{id}/release`

Releases a claimed todo (`todos.release`).



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/release' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.releaseTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.release` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch.

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "released": true
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/{id}/snooze`

Snoozes a todo until a wake time (`todos.snooze`).



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/snooze' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{"until": "2h"}'
```


```ts
await client.agent.todos.snoozeTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
  data: { until: '2h' },
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `until` | string | No | Wake time (duration-from-now or timestamp token). |

```json
{
  "until": "2h"
}
```

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "snoozed_until": "2026-01-15T14:14:02Z"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



## Orchestrator runs and triage

### `POST /api/v1/agent/todos/{id}/run`

Dispatches a background worker to autonomously work a todo (`todos.run`) and returns `{job_id, session_id}`. The daemon treats reaching the `todos.run` RPC as the human approval itself (issued by the TUI Run action or the CLI, both human-driven) — it has NO `_machine_confirmed` gate; that denial lives only on the model-facing `run_todo` tool. The minted job is bound to the worker `session_id` so its `{job_id}`→status lifecycle completes when the worker turn ends. Observe progress on the todo worker's stream.

This is a **J-class op**: it spends model budget on an autonomous LLM run with no `_machine_confirmed` gate on the daemon RPC. The daemon's own `systemAdminGate` may still `403 admin_unauthorized` when a Unix-socket admin capability is configured.



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/run' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
const { job_id, session_id } = await client.agent.todos.runTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
});

console.log('dispatched job:', job_id, 'on session:', session_id);
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.run` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch.

### Responses



```json
{
  "job_id": "job-2f9b1e7a",
  "session_id": "session-9a7b3c2d"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket `memAdminGate` / `systemAdminGate` refused the request. The HTTP edge has no service-level auth (`hoody-proxy` is the boundary, kit network-position trust), but the daemon retains its OWN socket-side admin gate: when an admin capability is configured on the daemon WITHOUT a matching forwarded `admin_token`, the daemon refuses. In the standard HTTP deployment the daemon runs with socket auth and no admin capability, so this gate allows the request and this code is not emitted. | Run the daemon with socket auth (`--auth-token-path`) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon's configured Memory-admin token. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/{id}/cancel-run`

Cancels an in-flight orchestrator run for a todo (`todos.cancel_run`).



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/cancel-run' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.cancelTodoRun({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.cancel_run` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch.

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "run_cancelled": true
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/triage`

Kicks an LLM triage pass over the inbox (`todos.triage`) and returns `{job_id}`. This is a **J-class op**: it spends model budget on an autonomous LLM run with no `_machine_confirmed` gate on the daemon RPC — the same property that makes `todos.run` a privileged op. Optional triage scoping in the body; an empty body triages the whole inbox.



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/triage' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
const { job_id } = await client.agent.todos.triageTodos({
  XHoodyCwd: '/Users/me/projects/my-app',
});

console.log('triage dispatched as job:', job_id);
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.triage` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch. An empty body triages the whole inbox.

### Responses



```json
{
  "job_id": "job-2f9b1e7a"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket `memAdminGate` / `systemAdminGate` refused the request. The HTTP edge has no service-level auth (`hoody-proxy` is the boundary, kit network-position trust), but the daemon retains its OWN socket-side admin gate: when an admin capability is configured on the daemon WITHOUT a matching forwarded `admin_token`, the daemon refuses. In the standard HTTP deployment the daemon runs with socket auth and no admin capability, so this gate allows the request and this code is not emitted. | Run the daemon with socket auth (`--auth-token-path`) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon's configured Memory-admin token. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



## Comments and messages

### `POST /api/v1/agent/todos/{id}/message`

Posts a comment AND kicks an orchestrator turn on the todo (`todos.message`). Returns `{job_id}`; observe the orchestrator on the todo worker's stream.


If you only want to comment without kicking an orchestrator turn, use `POST /todos/{id}/messages` (plural) instead — it appends a comment without dispatching a turn.




```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/message' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Please reproduce on a fresh checkout and attach the stack trace."
  }'
```


```ts
const { job_id } = await client.agent.todos.messageTodo({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
  data: {
    text: 'Please reproduce on a fresh checkout and attach the stack trace.',
  },
});

console.log('comment + turn dispatched as job:', job_id);
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `text` | string | Yes | The message that both comments and prompts the orchestrator. |

```json
{
  "text": "Please reproduce on a fresh checkout and attach the stack trace."
}
```

### Responses



```json
{
  "job_id": "job-2f9b1e7a"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/{id}/messages`

Posts a comment onto a todo's timeline WITHOUT triggering an orchestrator turn (`todos.post_message`).



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/messages' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "FYI — confirmed on 14.3 with the production build."
  }'
```


```ts
await client.agent.todos.postTodoComment({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  XHoodyCwd: '/Users/me/projects/my-app',
  data: {
    text: 'FYI — confirmed on 14.3 with the production build.',
  },
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `text` | string | Yes | The comment body to append to the todo timeline. |

```json
{
  "text": "FYI — confirmed on 14.3 with the production build."
}
```

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "commented_at": "2026-01-15T11:02:48Z"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



## Run proposals

### `POST /api/v1/agent/todos/{id}/proposals/{pid}/approve`

Approves a run proposal on a todo (`todos.approve_proposal`). Approval is NOT inert: the daemon hands the approved proposal to `startApprovedProposal`, which spawns a background worker session equivalent to `todos.run` — a J-class autonomous run with no `_machine_confirmed` gate on the daemon RPC. The paired `denyTodoProposal` spawns no worker.

The HTTP edge has no service-level auth (`hoody-proxy` is the boundary, kit network-position trust); the daemon's own `systemAdminGate` may still `403 admin_unauthorized` when a Unix-socket admin capability is configured.



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/proposals/p1/approve' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.approveTodoProposal({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  pid: 'p1',
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `pid` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.approve_proposal` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch. The todo `{id}` and proposal `{pid}` come from the path.

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "proposal_id": "p1",
  "approved": true
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket `memAdminGate` / `systemAdminGate` refused the request. The HTTP edge has no service-level auth (`hoody-proxy` is the boundary, kit network-position trust), but the daemon retains its OWN socket-side admin gate: when an admin capability is configured on the daemon WITHOUT a matching forwarded `admin_token`, the daemon refuses. In the standard HTTP deployment the daemon runs with socket auth and no admin capability, so this gate allows the request and this code is not emitted. | Run the daemon with socket auth (`--auth-token-path`) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon's configured Memory-admin token. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/todos/{id}/proposals/{pid}/deny`

Denies a run proposal on a todo (`todos.deny_proposal`). Deny does not spawn a worker.



```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789/proposals/p1/deny' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.denyTodoProposal({
  id: '7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789',
  pid: 'p1',
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `pid` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.deny_proposal` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch. The todo `{id}` and proposal `{pid}` come from the path.

### Responses



```json
{
  "id": "7c4f1a0b9d2e4f8c8a1b2c3d4e5f6789",
  "proposal_id": "p1",
  "denied": true
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |



## Maintenance

### `POST /api/v1/agent/todos/purge`

Permanently and irreversibly removes archived todos (`todos.purge`) — the tombstones are destroyed with no `_machine_confirmed` gate on the daemon RPC. This is a **J-class op** on the same axis as `run` and `triage`: it can spend budget on autonomous activity. The daemon's own `systemAdminGate` may still `403 admin_unauthorized` when a Unix-socket admin capability is configured. Optional filters in the body scope which archived todos to purge; an empty body purges all archived tombstones for the cwd.


`purge` is irreversible. The tombstones of archived todos are destroyed; there is no soft-delete and no recovery path. The daemon has no `_machine_confirmed` gate on this RPC.




```bash
curl -X POST 'https://api.hoody.com/api/v1/agent/todos/purge' \
  -H 'X-Hoody-Cwd: /Users/me/projects/my-app' \
  -H 'Content-Type: application/json' \
  -d '{}'
```


```ts
await client.agent.todos.purgeTodos({
  XHoodyCwd: '/Users/me/projects/my-app',
});
```



### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the `in:query` alias of `X-Hoody-Realm`. |

This endpoint accepts an optional JSON body. The body is forwarded to the daemon `todos.purge` RPC; the gateway scrubs every `_`-prefixed key and folds in the request scope (cwd, config_dir) before dispatch. An empty body purges all archived tombstones for the cwd.

### Responses



```json
{
  "purged": 12
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket `memAdminGate` / `systemAdminGate` refused the request. The HTTP edge has no service-level auth (`hoody-proxy` is the boundary, kit network-position trust), but the daemon retains its OWN socket-side admin gate: when an admin capability is configured on the daemon WITHOUT a matching forwarded `admin_token`, the daemon refuses. In the standard HTTP deployment the daemon runs with socket auth and no admin capability, so this gate allows the request and this code is not emitted. | Run the daemon with socket auth (`--auth-token-path`) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon's configured Memory-admin token. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through `hoody-proxy`. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit). | Honor `Retry-After` and retry. |