Skip to content
Hoody.com

The Agent Logs API exposes the daemon’s redacted log stream for query, single-entry fetch, source listing, volume statistics, SSE tailing, and filtered file export. All log entries returned by these routes are ALWAYS redacted at the gateway before reaching the client. These endpoints are active-only: there is no realm dimension to scope, so any per-request X-Hoody-Realm header or ?realm= query parameter is rejected with realm_scope_unsupported. Local sources export a point-in-time-consistent snapshot of the in-daemon ring; platform sources export a single query page and mark the export partial when more rows remained.


GET /api/v1/agent/logs

Queries the active log stream (logs.query). Filters ride on query parameters (source, level, host, since, until, …). ?limit=N caps the result set (the daemon default is 200) and is forwarded; the stream paginates by cursor (since_seq / before_seq), not by page.

NameInTypeRequiredDescription
sourcequerystringNoFilter to a log source/facet (see logsSources).
levelquerystringNoFilter to a minimum log level.
hostquerystringNoFilter to a host.
sincequerystringNoLower time/cursor bound (since_seq cursor passes through verbatim).
untilquerystringNoUpper time bound.
limitqueryintegerNoCaps the result set (daemon default 200). A non-numeric value is rejected 400.
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — 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.
{
"rows": [
{
"seq": 18421,
"ts": "2025-01-15T14:32:08.117Z",
"level": "info",
"source": "daemon",
"host": "agent-1",
"message": "session resumed",
"attrs": { "session_id": "5f3e1c0d9b2a4f1e8c7d6b5a" }
},
{
"seq": 18422,
"ts": "2025-01-15T14:32:08.243Z",
"level": "debug",
"source": "tool",
"host": "agent-1",
"message": "tool invoked",
"attrs": {
"session_id": "5f3e1c0d9b2a4f1e8c7d6b5a",
"tool": "bash",
"status": "ok"
}
}
],
"next_seq": 18423
}
await client.agent.logs.queryLogs({ source: "daemon", level: "info", limit: 50 });
Terminal window
curl -G "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/logs" \
--data-urlencode "source=daemon" \
--data-urlencode "level=info" \
--data-urlencode "limit=50"

GET /api/v1/agent/logs/entries/{ref}

Reads one log entry by ref. Entries are ALWAYS redacted. Active-only: a realm header is rejected.

NameInTypeRequiredDescription
refpathstringYesPath identifier.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector. Rejected (400 realm_scope_unsupported).
realmquerystringNoPer-request realm selector — query alias of X-Hoody-Realm. Rejected (400 realm_scope_unsupported).
{
"seq": 18421,
"ts": "2025-01-15T14:32:08.117Z",
"level": "info",
"source": "daemon",
"host": "agent-1",
"message": "session resumed",
"attrs": { "session_id": "5f3e1c0d9b2a4f1e8c7d6b5a" }
}
await client.agent.logs.readLogEntry("18421");
Terminal window
curl "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/logs/entries/18421"

GET /api/v1/agent/logs/sources

Lists the available log sources / facets (logs.sources). Active-only: a realm header is rejected.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector. Rejected (400 realm_scope_unsupported).
realmquerystringNoPer-request realm selector — query alias of X-Hoody-Realm. Rejected (400 realm_scope_unsupported).
{
"sources": [
{ "id": "daemon", "label": "Daemon", "local": true },
{ "id": "session", "label": "Session", "local": true },
{ "id": "tool", "label": "Tool", "local": true },
{ "id": "llm", "label": "LLM", "local": true },
{ "id": "activity","label": "Activity", "local": false },
{ "id": "events", "label": "Events", "local": false },
{ "id": "proxy", "label": "Proxy", "local": false }
]
}
await client.agent.logs.logsSources();
Terminal window
curl "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/logs/sources"

GET /api/v1/agent/logs/stats

Returns log volume / level statistics (logs.stats). Active-only: a realm header is rejected.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector. Rejected (400 realm_scope_unsupported).
realmquerystringNoPer-request realm selector — query alias of X-Hoody-Realm. Rejected (400 realm_scope_unsupported).
{
"by_source": {
"daemon": 18421,
"session": 472,
"tool": 9381,
"llm": 1102
},
"by_level": {
"debug": 14218,
"info": 12073,
"warn": 1984,
"error": 101
},
"window": { "since": "2025-01-15T00:00:00Z", "until": "2025-01-15T23:59:59Z" }
}
await client.agent.logs.logsStats();
Terminal window
curl "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/logs/stats"

GET /api/v1/agent/logs/stream

Tails the active log stream over Server-Sent Events (logs.tail). The stream paginates with a cursor it advances each round (since_seq = the previous reply’s next_seq), 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: <seq> (a reconnecting client resumes via the Last-Event-ID header, which overrides ?since_seq)
  • a lagged frame with {code: "replay_gap"} when the caller’s cursor fell behind the ring
  • periodic heartbeats
  • end on disconnect

Filters ride query parameters (source, level, host, since_seq, …); ?limit caps each poll batch. Local sources only. Active-only: a realm header returns 400 realm_scope_unsupported. Entries are ALWAYS redacted.

NameInTypeRequiredDescription
sourcequerystringNoFilter the tail to a log source/facet.
levelquerystringNoFilter to a minimum log level.
hostquerystringNoFilter to a host.
since_seqqueryintegerNoInitial resume cursor (the Last-Event-ID header overrides it). A non-numeric value is rejected 400.
limitqueryintegerNoCaps each poll batch. A non-numeric value is rejected 400.
Last-Event-IDheaderstringNoSSE 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-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector. Rejected (400 realm_scope_unsupported).
realmquerystringNoPer-request realm selector — query alias of X-Hoody-Realm. Rejected (400 realm_scope_unsupported).
event: entry
id: 18421
data: {"seq":18421,"ts":"2025-01-15T14:32:08.117Z","level":"info","source":"daemon","host":"agent-1","message":"session resumed","attrs":{"session_id":"5f3e1c0d9b2a4f1e8c7d6b5a"}}
event: entry
id: 18422
data: {"seq":18422,"ts":"2025-01-15T14:32:08.243Z","level":"debug","source":"tool","host":"agent-1","message":"tool invoked","attrs":{"session_id":"5f3e1c0d9b2a4f1e8c7d6b5a","tool":"bash","status":"ok"}}
event: lagged
data: {"code":"replay_gap","from_seq":18001,"head_seq":18399}
: hb
event: end
data: {"reason":"client_disconnect"}
await client.agent.logs.streamLogs({ source: "daemon", level: "info", limit: 100 });
Terminal window
curl -N "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/logs/stream?source=daemon&level=info&limit=100"

GET /api/v1/agent/logs/export

Streams the filtered, ALWAYS-redacted log set as a download (Content-Disposition: attachment).

  • format=jsonl (default, one wire row per line) or txt (human-readable).
  • Local sources export a point-in-time-consistent snapshot of the in-daemon ring (bounded at the seq observed when the export starts).
  • source=activity|events|proxy exports ONE platform query page (default limit=2000) and marks the export partial when more remained.
  • Every export ends with an in-band terminatorjsonl emits a final {"_hoody_export":{...}} line and txt emits a trailing # export: … comment carrying rows / gap / partial. Its absence means the download was truncated.

Filters mirror the Logs tab exactly (source, min_level, comp, session_id, text, since, until, event, tool, model, status, method, min_status, max_status, errors_only, event_type, resource_type, container_id, kind, host); ?since_seq exports incrementally; ?limit caps total rows; ?filename overrides the download name (reduced to a safe basename). Active-only: a realm header returns 400 realm_scope_unsupported.

NameInTypeRequiredDescription
sourcequerystringNoLog source to export (see logsSources; one local source, one platform source, or omitted for all local sources).
min_levelquerystringNoMinimum log level (debug|info|warn|error).
compquerystringNoComponent filter (daemon source).
session_idquerystringNoSession id filter.
textquerystringNoCase-insensitive substring filter over message + attrs.
sincequerystringNoLower time bound (RFC3339 or relative like 1h/7d).
untilquerystringNoUpper time bound (RFC3339 or relative).
eventquerystringNoSession lifecycle event filter (session source).
toolquerystringNoTool name filter (tool source).
modelquerystringNoModel filter (llm source).
statusquerystringNoTool outcome filter: ok|error|cancelled (tool source).
methodquerystringNoHTTP method filter (activity source).
min_statusqueryintegerNoMinimum HTTP status (activity source).
max_statusqueryintegerNoMaximum HTTP status (activity source).
errors_onlyquerybooleanNoOnly error rows (activity source; true/false).
event_typequerystringNoEvent type filter (events source).
resource_typequerystringNoResource type filter (events source).
containerquerystringNoContainer filter (proxy source; empty = all running realm containers). Maps to the daemon’s container_id filter.
kindquerystringNoProxy row kind: request|response|event (proxy source).
hostquerystringNoProxy URL host filter (exact or dot-aligned suffix).
since_seqqueryintegerNoExclusive lower seq bound for incremental exports (local sources).
limitqueryintegerNoTOTAL row cap across the export (default: everything the snapshot matches; platform default 2000).
formatquerystringNoExport format: jsonl (default) or txt.
filenamequerystringNoDownload filename override (reduced to a safe basename).
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector. Rejected (400 realm_scope_unsupported).
realmquerystringNoPer-request realm selector — query alias of X-Hoody-Realm. Rejected (400 realm_scope_unsupported).
{"seq":18421,"ts":"2025-01-15T14:32:08.117Z","level":"info","source":"daemon","host":"agent-1","message":"session resumed","attrs":{"session_id":"5f3e1c0d9b2a4f1e8c7d6b5a"}}
{"seq":18422,"ts":"2025-01-15T14:32:08.243Z","level":"debug","source":"tool","host":"agent-1","message":"tool invoked","attrs":{"session_id":"5f3e1c0d9b2a4f1e8c7d6b5a","tool":"bash","status":"ok"}}
{"_hoody_export":{"rows":2,"gap":false,"partial":false,"head_seq":18422,"format":"jsonl"}}
await client.agent.exportLogs({
source: "daemon",
min_level: "info",
format: "jsonl",
filename: "agent-daemon-info.jsonl"
});
Terminal window
curl -OJ \
"https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/logs/export?source=daemon&min_level=info&format=jsonl&filename=agent-daemon-info.jsonl"