Logs API
The Logs API provides a real-time Server-Sent Events stream of agent execution logs. Logs are polled from the database every 500ms and delivered incrementally, with 15-second keepalive heartbeats to maintain the connection. Use this endpoint to build live dashboards, monitor running tasks, or pipe agent output into external observability tools.
Quick Start
Connect to the log stream, filter by event type, and handle reconnection gracefully:
// 1. Connect to the SSE log stream for a specific task
const taskId: string = 'task-9d4e-a1b2';
const source: EventSource = new EventSource(`/api/logs/stream?taskId=${taskId}`);
// 2. Filter and handle logs by event type
interface LogEntry {
id: string;
taskId: string;
agentType: string;
event: string;
payload: string;
timestamp: string;
}
source.onmessage = (event: MessageEvent) => {
const log: LogEntry = JSON.parse(event.data);
// Route logs based on event type
switch (log.event) {
case 'tool_use':
console.log(`[TOOL] ${log.payload}`);
break;
case 'assistant_message':
console.log(`[AGENT] ${log.payload}`);
break;
case 'error':
console.error(`[ERROR] ${log.payload}`);
break;
default:
console.log(`[${log.event}] ${log.payload}`);
}
};
// 3. Handle reconnection on connection loss
source.onerror = () => {
console.warn('SSE connection lost — browser will auto-reconnect');
// EventSource auto-reconnects by default.
// To stop retrying, call source.close() here.
};
// 4. Clean up when done (e.g. when navigating away)
function stopStreaming(): void {
source.close();
console.log('Log stream closed');
} Base URL
/api/logs/stream
Endpoints
Stream Logs
/api/logs/stream Open a persistent SSE connection that streams agent log entries in real time. Supports optional filtering by task ID and event type. Polls every 500ms with 15-second keepalive heartbeats.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| taskId | string | — | Filter logs to a specific task UUID |
| eventType | string | — | Filter logs by event type (e.g. tool_use, assistant_message, error) |
Response — text/event-stream with JSON log objects
Log Object
| Field | Type | Req | Description |
|---|---|---|---|
| id | string (UUID) | * | Log entry identifier |
| taskId | string (UUID) | — | Associated task ID |
| agentType | string | * | Agent runtime that produced the log |
| event | string | * | Event type (e.g. tool_use, assistant_message, error) |
| payload | string (JSON) | — | Event-specific data as serialized JSON |
| timestamp | ISO 8601 | * | When the log entry was recorded |
Each SSE message is a data: frame containing a single JSON log object. On database errors, an error event is emitted and the stream backs off for 2 seconds before retrying.
Stream all logs for a running task — each SSE message contains a single JSON log object:
// Stream logs for a specific task
interface LogEntry {
id: string;
agentType: string;
event: string;
payload: string;
timestamp: string;
}
const source: EventSource = new EventSource('/api/logs/stream?taskId=task-9d4e-a1b2');
source.onmessage = (event: MessageEvent) => {
const log: LogEntry = JSON.parse(event.data);
const time: string = new Date(log.timestamp).toLocaleTimeString();
console.log(`[${time}] [${log.agentType}] ${log.event}: ${log.payload}`);
};
source.onerror = () => {
console.warn('SSE connection lost — browser will auto-reconnect');
}; Filter by event type to only receive tool usage events — useful for tracking file operations:
// Only stream tool_use events for a task
const source: EventSource = new EventSource(
'/api/logs/stream?taskId=task-9d4e-a1b2&eventType=tool_use'
);
source.onmessage = (event: MessageEvent) => {
const log: { payload: string } = JSON.parse(event.data);
console.log(`Tool: ${log.payload}`);
}; Example stream events:
data: {"id":"log-a1b2c3d4","taskId":"task-9d4e-a1b2","agentType":"claude-code","event":"tool_use","payload":"{\"tool\":\"Read\",\"file\":\"src/data/revenue.csv\"}","timestamp":"2026-04-03T10:31:16.000Z"}
data: {"id":"log-e5f6a7b8","taskId":"task-9d4e-a1b2","agentType":"claude-code","event":"assistant_message","payload":"{\"message\":\"Analyzing quarterly revenue trends...\"}","timestamp":"2026-04-03T10:31:18.000Z"}
data: {"id":"log-c9d0e1f2","taskId":"task-9d4e-a1b2","agentType":"claude-code","event":"tool_use","payload":"{\"tool\":\"Write\",\"file\":\"/reports/q4-analysis.md\"}","timestamp":"2026-04-03T10:31:22.000Z"} Connection Behavior
| Behavior | Detail |
|---|---|
| Poll interval | 500ms between database queries |
| Keepalive | : keepalive comment every 15 seconds |
| Batch size | Up to 50 log entries per poll cycle |
| Error recovery | 2-second backoff on database errors, then resume |
| Client disconnect | Detected via AbortSignal; stream and intervals are cleaned up |
Response Headers
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive