Skip to main content

Events

Render live output and replay durable session state.

At a glance

Endpoint
GET /v1/sessions/{id}/events/stream
Replay
Last-Event-ID
Deltas
Ephemeral
Keep alive
15 seconds

Connect​

From this release, run_id is 32 hex characters in responses and stream events alike.

Set event_deltas to true for live text and reasoning deltas.

Terminal
curl -N -sS \
  "$PANTHEON_BASE_URL/v1/sessions/$SESSION_ID/events/stream?event_deltas=true" \
  -H "Authorization: Bearer $PANTHEON_API_KEY" \
  -H "Last-Event-ID: $LAST_EVENT_ID"

The server sends a keep-alive comment every 15 seconds.

Durable events​

Durable events have an SSE id and JSON sequence. Save the SSE id as your replay cursor.

SSE
event: tool.started
id: evt_101
data: {"id":"evt_101","sequence":7,"type":"tool.started","workspace_id":"workspace_123","session_id":"session_123","run_id":"0123456789abcdef0123456789abcdef","created_at":"2026-09-03T12:00:01Z","content":{"tool_call_id":"call_123","name":"echo_tool","input":{"message":"hello"}},"data":{"tool_call_id":"call_123","name":"echo_tool"}}

Text event content is a list of blocks. Structured event content is a JSON object.

Ephemeral events​

Ephemeral events have no SSE id.

SSE
event: message.delta
data: {"type":"message.delta","run_id":"0123456789abcdef0123456789abcdef","delta":{"text":"Hello"}}

Pantheon does not persist or replay these events.

Event catalog​

ValueMeaning
run.startedA worker started the run.
run.completedThe run finished successfully.
run.failedThe run stopped with an error.
run.cancelledA client cancelled the run.
message.startedAssistant message generation started.
message.deltaA live assistant text fragment arrived.
message.completedPantheon stored the final assistant message.
reasoning.deltaA live reasoning fragment arrived.
reasoning.messagePantheon stored a durable reasoning message.
intermediate.deltaA live intermediate output fragment arrived.
tool.policyWhat the agent was granted and what was withheld, once per run.
tool.startedThe agent started a tool call.
agent.custom_tool_useYour application must execute an application tool.
tool.completedA tool call completed.
tool.failedA tool call failed.
tool.refusedThe agent called a tool its revision does not grant.
session.status_idleThe session returned to idle.
session.errorA session error occurred.
sandbox.recreatedPantheon replaced a missing sandbox.
stream.resyncThe client must replay and reconnect with backoff.

The application tool lifecycle events share one tool_call_id.

Read Application tools for correlation and resume steps.

Every run opens with one tool.policy event naming the agent revision that governed it, the built-in tools it granted, and each tool it withheld with the reason. A call to a tool the revision does not grant is never executed and arrives as tool.refused, not tool.failed, so a policy decision is never mistaken for a broken tool.

Handle stream.resync​

If live subscription or barrier startup fails, the connection stays open and delivers persisted events with ids. The response header X-Pantheon-Live-Events: unavailable identifies this mode; otherwise its value is live, including when deltas were not requested. Startup degradation sends no resync frame. A live delivery failure mid-stream sends one resync frame without an id, then closes the connection.

1

Save the cursor

Keep the last durable SSE id.

2

Reconnect with backoff

Send that id in Last-Event-ID. If a resync arrives again within seconds of connecting, wait before the next attempt (500 ms doubling to 30 s) and cap the attempts, so a server that keeps resyncing never sees a tight loop.

3

Read the replay

Pantheon replays persisted events before live output resumes.

Pitfalls​

  • Deltas repeat after reconnect: Use only the SSE id from durable events as the cursor.
  • Live text is missing: Include event_deltas=true. Final durable message events still arrive.
  • Two tool pills appear: Merge every tool lifecycle event by tool_call_id.

Search docs

Esc

Ask Bami

Bami answers inside your signed-in dashboard. Write your question here, then paste it into Bami with Cmd/Ctrl+/.