GET /api/v1/agent/status/stream

Agent Status Stream (SSE)

Server-Sent Events stream of real-time agent state changes. Receives a full snapshot on connect and on every meaningful state transition.

Overview

Opens a Server-Sent Events (SSE) connection that pushes agent status snapshots in real time. The stream sends an initial snapshot on connect, then sends updates only when the agent state meaningfully changes (e.g. idle to active, tool switches, sessions starting or ending).

Events are debounced at 1 second to avoid flooding during rapid tool sequences. A keepalive comment is sent every 30 seconds when idle.

Info

If POCKETPAW_STATUS_API_KEY is set, requests must include the key via the X-Status-Key header or ?key= query parameter.

Event Format

The stream uses the standard SSE protocol. Each event has the type status with a JSON data payload matching the GET /api/v1/agent/status response schema.

event: status
data: {"global":{"state":"active","active_sessions":1,...},"sessions":[...]}
event: status
data: {"global":{"state":"idle","active_sessions":0,...},"sessions":[]}
: keepalive

Deduplication

The stream only sends events when the agent state actually changes. Repeated snapshots with the same global state, session states, and tool names are suppressed. Timing fields like duration_seconds and uptime_seconds do not trigger new events on their own.

Terminal window
curl -N http://localhost:8000/api/v1/agent/status/stream \
-H "X-Status-Key: your-key"
const evtSource = new EventSource(
"http://localhost:8000/api/v1/agent/status/stream?key=your-key"
);
evtSource.addEventListener("status", (event) => {
const status = JSON.parse(event.data);
console.log(status.global.state);
for (const session of status.sessions) {
console.log(`${session.channel}: ${session.state}`);
if (session.tool_name) {
console.log(` Running: ${session.tool_name}`);
}
}
});
import json
import httpx
with httpx.stream(
"GET",
"http://localhost:8000/api/v1/agent/status/stream",
headers={"X-Status-Key": "your-key"},
) as response:
for line in response.iter_lines():
if line.startswith("data: "):
status = json.loads(line[6:])
print(status["global"]["state"])
event: status
data: {"global":{"state":"idle","active_sessions":0,"max_concurrent":5,"uptime_seconds":120},"sessions":[]}
event: status
data: {"global":{"state":"active","active_sessions":1,"max_concurrent":5,"uptime_seconds":125},"sessions":[{"session_key":"websocket:abc123","session_id":"abc123","channel":"websocket","title":null,"state":"thinking","tool_name":null,"duration_seconds":0.5,"token_usage":null,"error_message":null}]}
event: status
data: {"global":{"state":"active","active_sessions":1,"max_concurrent":5,"uptime_seconds":128},"sessions":[{"session_key":"websocket:abc123","session_id":"abc123","channel":"websocket","title":null,"state":"tool_running","tool_name":"bash","duration_seconds":1.2,"token_usage":{"input":500,"output":100},"error_message":null}]}
: keepalive
event: status
data: {"global":{"state":"idle","active_sessions":0,"max_concurrent":5,"uptime_seconds":140},"sessions":[]}
Request
curl -X GET "http://localhost:8000/api/v1/agent/status/stream" \
  -H "Content-Type: application/json"
const response = await fetch("http://localhost:8000/api/v1/agent/status/stream", {
  method: "GET",
  headers: {
    "Content-Type": "application/json"
},
});

const data = await response.json();
console.log(data);
import requests

response = requests.get(
    "http://localhost:8000/api/v1/agent/status/stream",
    headers={'Content-Type':'application/json'},
)

print(response.json())
package main

import (
    "fmt"
    "net/http"
    "io"
)

func main() {
    req, _ := http.NewRequest("GET", "http://localhost:8000/api/v1/agent/status/stream", nil)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}
Response
Send a request to see the response