# Agent: Logs

**Page:** api/agent/logs

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

---

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



The agent logs API exposes the active-supervisor log stream: query historical entries, read individual redacted entries, list log sources/facets, fetch volume statistics, and tail the log stream over Server-Sent Events. All routes are **active-only** — they have no realm dimension, and any `X-Hoody-Realm` header (or `?realm=` query alias) is rejected with `400 realm_scope_unsupported`. Use these endpoints from `client.agent.logs.*`.


All log responses are ALWAYS redacted. The log stream paginates by cursor (`since_seq` / `before_seq`), not by page, and `?limit=N` caps the result set (daemon default 200). A non-numeric `limit` is rejected with `400 bad_request`.


## `GET /api/v1/agent/logs`

Query the active-supervisor log stream. Filters ride as query params (`source`, `level`, `host`, `since`, `until`); `?limit=N` caps the result set.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `source` | query | string | No | Filter to a log source/facet (see `logsSources`). |
| `level` | query | string | No | Filter to a minimum log level. |
| `host` | query | string | No | Filter to a host. |
| `since` | query | string | No | Lower time/cursor bound (`since_seq` cursor passes through verbatim). |
| `until` | query | string | No | Upper time bound. |
| `limit` | query | integer | No | Caps the result set (daemon default 200). A non-numeric value is rejected `400`. |
| `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). Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |
| `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). 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. Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |



```bash
curl -G "https://api.hoody.com/api/v1/agent/logs" \
  -H "X-Hoody-Cwd: /home/user/project" \
  --data-urlencode "source=supervisor" \
  --data-urlencode "level=warn" \
  --data-urlencode "host=worker-01" \
  --data-urlencode "since=2025-01-15T10:00:00Z" \
  --data-urlencode "limit=100"
```


```ts
const { data } = await client.agent.logs.queryLogs({
  source: "supervisor",
  level: "warn",
  host: "worker-01",
  since: "2025-01-15T10:00:00Z",
  limit: 100,
  "X-Hoody-Cwd": "/home/user/project"
});
```



### Responses



```json
{
  "entries": [
    {
      "ref": "lg_01HMK3Q8Y3P9X7C2N5B6J8F4DA",
      "seq": 12340,
      "source": "supervisor",
      "level": "warn",
      "host": "worker-01",
      "ts": "2025-01-15T10:23:17.482Z",
      "message": "container heartbeat missed"
    },
    {
      "ref": "lg_01HMK3Q8Y3P9X7C2N5B6J8F4DB",
      "seq": 12341,
      "source": "supervisor",
      "level": "error",
      "host": "worker-01",
      "ts": "2025-01-15T10:23:18.011Z",
      "message": "tool run aborted by gate"
    }
  ],
  "next_seq": 12342,
  "has_more": false
}
```


```json
{
  "code": "realm_scope_unsupported",
  "message": "realm scope not supported on this route"
}
```

| 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). | 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/logs/entries/{ref}`

Read a single log entry by `ref`. Entries are ALWAYS redacted.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `ref` | path | string | Yes | Path identifier. |
| `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). Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |
| `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). 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. Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |



```bash
curl "https://api.hoody.com/api/v1/agent/logs/entries/lg_01HMK3Q8Y3P9X7C2N5B6J8F4DA" \
  -H "X-Hoody-Cwd: /home/user/project"
```


```ts
const { data } = await client.agent.logs.readLogEntry({
  ref: "lg_01HMK3Q8Y3P9X7C2N5B6J8F4DA",
  "X-Hoody-Cwd": "/home/user/project"
});
```



### Responses



```json
{
  "ref": "lg_01HMK3Q8Y3P9X7C2N5B6J8F4DA",
  "seq": 12340,
  "source": "supervisor",
  "level": "warn",
  "host": "worker-01",
  "ts": "2025-01-15T10:23:17.482Z",
  "message": "container heartbeat missed",
  "fields": {
    "container_id": "cnt_01HMK3Q8Y3P9X7C2N5B6J8F4DX"
  }
}
```


```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). | 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/logs/sources`

List the available log sources/facets that can be passed to the `source` query filter on `queryLogs` and `streamLogs`.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `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). Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |
| `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). 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. Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |



```bash
curl "https://api.hoody.com/api/v1/agent/logs/sources" \
  -H "X-Hoody-Cwd: /home/user/project"
```


```ts
const { data } = await client.agent.logs.logsSources({
  "X-Hoody-Cwd": "/home/user/project"
});
```



### Responses



```json
{
  "sources": [
    { "id": "supervisor", "label": "Supervisor", "count": 5432 },
    { "id": "workflow",   "label": "Workflow",   "count": 8110 },
    { "id": "tool",       "label": "Tool runs",  "count":  345 },
    { "id": "system",     "label": "System",     "count":   73 }
  ]
}
```


```json
{
  "code": "realm_scope_unsupported",
  "message": "realm scope not supported on this route"
}
```

| 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). | 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/logs/stats`

Return log volume and level statistics.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `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). Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |
| `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). 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. Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |



```bash
curl "https://api.hoody.com/api/v1/agent/logs/stats" \
  -H "X-Hoody-Cwd: /home/user/project"
```


```ts
const { data } = await client.agent.logs.logsStats({
  "X-Hoody-Cwd": "/home/user/project"
});
```



### Responses



```json
{
  "total": 13960,
  "by_level": {
    "debug": 1024,
    "info":  9120,
    "warn":  3380,
    "error":  436
  },
  "by_source": {
    "supervisor": 5432,
    "workflow":   8110,
    "tool":        345,
    "system":       73
  },
  "window": {
    "from": "2025-01-15T00:00:00Z",
    "to":   "2025-01-15T10:30:00Z"
  }
}
```


```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). | 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/logs/stream`

Tail the active-supervisor log stream over Server-Sent Events. The gateway forward-pages the daemon with a cursor it advances each round (`since_seq` = the previous reply's `next_seq`) and DRAINS capped pages before idling, so no row is skipped under load.

The tail rides the same `seq` / replay convention the session stream uses:

- An `entry` frame per redacted row CARRYING `id: &lt;seq&gt;` — a reconnecting client resumes via the `Last-Event-ID` header, which overrides `?since_seq`.
- A `lagged` `{code:replay_gap}` frame when the caller's cursor fell behind the ring.
- Periodic heartbeats.
- `end` on disconnect.

Filters ride query params (`source`, `level`, `host`, `since_seq`, ...); `?limit` caps each poll batch. Local sources only.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `source` | query | string | No | Filter the tail to a log source/facet. |
| `level` | query | string | No | Filter to a minimum log level. |
| `host` | query | string | No | Filter to a host. |
| `since_seq` | query | integer | No | Initial resume cursor (the `Last-Event-ID` header overrides it). A non-numeric value is rejected `400`. |
| `limit` | query | integer | No | Caps each poll batch. A non-numeric value is rejected `400`. |
| `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). Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |
| `Last-Event-ID` | header | string | No | SSE resume cursor — the gateway `int64` seq to resume from; OVERRIDES the `?since_seq` query param. Sent automatically by an SSE client on reconnect. |
| `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). 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. Rejected (`400 realm_scope_unsupported`) on active-only / no-realm routes. |



```bash
curl -N "https://api.hoody.com/api/v1/agent/logs/stream?source=supervisor&level=info&since_seq=12340&limit=200" \
  -H "X-Hoody-Cwd: /home/user/project" \
  -H "Accept: text/event-stream"
```


```ts
// The SDK returns an AsyncIterable of decoded SSE frames.
const stream = client.agent.logs.streamLogs({
  source: "supervisor",
  level: "info",
  since_seq: 12340,
  limit: 200,
  "X-Hoody-Cwd": "/home/user/project"
});

for await (const frame of stream) {
  if (frame.event === "entry") console.log(frame.data);
  if (frame.event === "lagged") console.warn("replay gap — reset cursor");
}
```



### Responses



```
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

id: 12340
event: entry
data: {"ref":"lg_01HMK3Q8Y3P9X7C2N5B6J8F4DA","seq":12340,"source":"supervisor","level":"info","host":"worker-01","ts":"2025-01-15T10:30:00.114Z","message":"tool run started"}

id: 12341
event: entry
data: {"ref":"lg_01HMK3Q8Y3P9X7C2N5B6J8F4DB","seq":12341,"source":"supervisor","level":"warn","host":"worker-01","ts":"2025-01-15T10:30:00.842Z","message":"rate limit approached"}

: heartbeat

id: 12342
event: entry
data: {"ref":"lg_01HMK3Q8Y3P9X7C2N5B6J8F4DC","seq":12342,"source":"supervisor","level":"info","host":"worker-01","ts":"2025-01-15T10:30:01.077Z","message":"tool run finished"}
```


```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). | 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. |


```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. |