> ## Documentation Index
> Fetch the complete documentation index at: https://docs.powabase.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming & SSE

> The platform uses Server-Sent Events (SSE) for real-time streaming of agent responses, orchestration flows, and workflow executions. This page covers the event format, event types, and consumption patterns.

## SSE Overview

Server-Sent Events (SSE) provide a one-directional stream from server to client over a single HTTP connection. When you call a streaming endpoint (e.g. /api/agents/\{id}/run/stream), the response is a text/event-stream with individual events sent as they occur. Each event is a JSON object prefixed with 'data: ' on a single line, separated by blank lines.

## Agent Streaming Events

| Event                     | Key Fields                   | Description                                                                                                                                                   |
| ------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `start`                   | `run_id`, `session_id`       | Agent run has started — save `session_id` for multi-turn                                                                                                      |
| `step_started`            | `step`                       | Agent is beginning a new reasoning step                                                                                                                       |
| `content_delta`           | `delta`                      | A per-token piece of the agent's text response. Accumulated server-side into the persisted run; the platform forwards each delta as it arrives.               |
| `chunk`                   | `content`                    | Terminal text event with the final assembled response — emitted at the end of a non-ReAct (sync-style) generation                                             |
| `tool_call`               | `tool_name`, `arguments`     | Agent is calling a tool with the given arguments                                                                                                              |
| `tool_result`             | `tool_name`, `result`        | Tool execution completed with this result                                                                                                                     |
| `reasoning_delta`         | `delta`                      | Per-token piece of the model's reasoning trace (only when `reasoning_requested=true`). Forwarded but NOT persisted — use `reasoning` for the persisted trace. |
| `reasoning`               | `text`                       | Persisted reasoning segment — the canonical "what the model thought" event for replay                                                                         |
| `reasoning_summary`       | `summary`                    | Final summarised reasoning trace at the end of the step                                                                                                       |
| `step_completed`          | `step`                       | Agent finished a reasoning step                                                                                                                               |
| `approval_requested`      | `tool_name`, `tool_input`    | Tool call paused — waiting for approval via the approve endpoint                                                                                              |
| `context_handler_created` | `context_handler_id`         | A context handler was created mid-run (e.g. by a knowledge\_search tool call). Lets you display the citation panel for the run.                               |
| `complete`                | `run_id`, `content`, `usage` | Agent run finished                                                                                                                                            |
| `error`                   | `message`                    | An error occurred during execution                                                                                                                            |

### Keepalive

If no event has been emitted for 30 seconds, the stream sends `: keepalive\n\n` (an SSE comment line). Most SSE clients ignore comment lines automatically. If you're rolling your own parser, drop any line that starts with `:`.

### Persisted vs. forwarded-only

The platform distinguishes events that get written to the run record from events that are forwarded for UI ergonomics but not persisted:

* **Forwarded only**: `content_delta`, `reasoning_delta`. These are per-token deltas; the assembled content / reasoning is persisted as one piece on `complete`.
* **Persisted + forwarded**: everything else.

If you replay a run via `GET /api/agents/runs/{run_id}`, you'll see the assembled content but not the individual deltas.

## Consuming SSE in Python

<CodeGroup>
  ```python Python theme={null}
  import requests
  import json

  response = requests.post(
      f"{BASE_URL}/api/agents/{agent_id}/run/stream",
      headers=headers,
      json={"message": "What can you help me with?"},
      stream=True,
  )

  for line in response.iter_lines():
      if not line:
          continue
      text = line.decode("utf-8")
      if text.startswith("data: "):
          event = json.loads(text[6:])
          event_type = event["event"]

          if event_type == "start":
              print(f"Session: {event['session_id']}")
          elif event_type == "chunk":
              print(event["content"], end="", flush=True)
          elif event_type == "tool_call":
              print(f"\n[Calling {event['tool_name']}...]")
          elif event_type == "tool_result":
              print(f"[Tool returned result]")
          elif event_type == "error":
              print(f"\nError: {event['message']}")
          elif event_type == "complete":
              print("\nDone.")
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(`${BASE_URL}/api/agents/${agentId}/run/stream`, {
    method: "POST",
    headers,
    body: JSON.stringify({ message: "What can you help me with?" }),
  });

  const reader = response.body!.getReader();
  const decoder = new TextDecoder();
  let buffer = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });

    const lines = buffer.split("\n");
    buffer = lines.pop() || "";

    for (const line of lines) {
      if (line.startsWith("data: ")) {
        const event = JSON.parse(line.slice(6));
        switch (event.event) {
          case "start":
            console.log("Session:", event.session_id);
            break;
          case "chunk":
            process.stdout.write(event.content);
            break;
          case "tool_call":
            console.log(`\n[Calling ${event.tool_name}...]`);
            break;
          case "complete":
            console.log("\nDone.");
            break;
        }
      }
    }
  }
  ```

  ```bash cURL theme={null}
  # Stream events to terminal (each line is a JSON event)
  curl -N -X POST '{BASE_URL}/api/agents/{agent_id}/run/stream' \
    -H "apikey: {API_KEY}" \
    -H "Authorization: Bearer {API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{"message": "What can you help me with?"}'
  ```
</CodeGroup>

## Orchestration Events

Orchestration streaming extends the agent event model with delegation events. You see the coordinator reasoning, delegating to entity agents, each entity's response, and the coordinator's final synthesis. Events like delegation\_start and entity\_chunk let you show which agent is currently working.

## Workflow Streaming

Workflow streaming sends per-block events as the engine traverses the DAG. The agent-block and orchestration-block streams interleave their own content\_delta / reasoning\_delta events directly into the workflow stream, so a downstream client can render the agent's tokens live while still seeing block-level structure:

| Event                               | Key Fields               | When                                                                                                           |
| ----------------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `workflow_start`                    | `execution_id`           | The workflow execution has begun                                                                               |
| `block_started`                     | `block_id`, `block_type` | The engine is about to execute a block                                                                         |
| `block_chunk`                       | `block_id`, `delta`      | A streaming block (agent / orchestration) produced output                                                      |
| `content_delta` / `reasoning_delta` | `block_id`, `delta`      | Forwarded from an agent/orchestration block inside the workflow — lets the UI render tokens live               |
| `block_output`                      | `block_id`, `output`     | A block finished with this output, which downstream blocks may reference                                       |
| `block_completed`                   | `block_id`               | A block has fully finished (including any post-processing)                                                     |
| `block_error`                       | `block_id`, `error`      | A block failed — by default, the workflow short-circuits unless the next block is in an error-handler position |
| `workflow_complete`                 | `execution_id`, `result` | The whole execution finished                                                                                   |
| `workflow_error`                    | `execution_id`, `error`  | The execution failed at the top level                                                                          |

The block-level events let you build a step indicator that updates as the DAG advances, and the forwarded content/reasoning deltas let you stream the agent's response within the same UI surface.

<Tip>
  **Buffer handling**

  SSE data may arrive in partial chunks: a single read() call might contain half an event or multiple events. Always buffer incoming data and split on newlines to ensure you process complete events.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Streaming Responses Guide" href="/guides/streaming-guide">
    Hands-on guide to consuming streaming events.
  </Card>

  <Card title="Build an Agent" href="/guides/build-agent">
    Create an agent with streaming support.
  </Card>

  <Card title="Agents API Reference" href="/api-reference/agents">
    Streaming endpoint documentation.
  </Card>
</CardGroup>
