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

# Streaming events

> How Karta streams turns across native sessions, the Managed Agents adapter, and the OpenAI-compatible Responses adapter.

Karta is streaming-first. A turn is a sequence of typed events. The native
session API, the CLI, the Python SDK, the widget, and the OpenAI-compatible
adapters all use that model, then shape it for the surface you called.

Use the native event stream when you want the fullest Karta contract. Use an
adapter stream when you need a client library that already speaks another wire
format.

## Choose the stream

| Surface                            | Stream event names                                                                                                       | Use when                                                             |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| Native sessions API and Python SDK | `text`, `tool_use`, `input_required`, `done`, and related raw event types                                                | You control the integration and want the complete Karta event model. |
| Managed Agents adapter and widget  | `session.status_running`, `agent.message`, `agent.tool_use`, `agent.tool_result`, `session.status_idle`, `session.error` | You are building an embedded or full-fidelity chat UI.               |
| OpenAI Responses adapter           | `response.created`, `response.output_text.delta`, `response.completed`, `response.failed`                                | You want to reuse OpenAI Responses client code.                      |

Non-streaming calls still run through the same turn. Karta accumulates the
stream and returns the final response object.

## Native event envelope

Native session streams use Server-Sent Events. The SSE `event:` name matches the
event object's `type`.

```text theme={null}
event: text
data: {"type":"text","source":"opencode","session_id":"ses_...","data":{"part":{"type":"text","text":"Quick"}}}

event: done
data: {"type":"done","source":"karta","session_id":"ses_...","data":{"usage":{"input_tokens":42,"output_tokens":128,"total_tokens":170}}}
```

In the SDK, iterate over the same event objects:

```python theme={null}
async for event in app.stream("Explain quicksort"):
    if event.type == "text":
        print(event.data['part']['text'], end="", flush=True)
    elif event.type == "tool_use":
        print(f"\n[tool] {event.data['tool_name']}")
    elif event.type == "done":
        print(f"\n[usage] {event.data['usage']}")
```

## Native event types

The native stream is the most detailed stream. Event payloads vary by harness,
but these event types are the public contract you should branch on.

### text

An agent text chunk. The text is at `event.data['part']['text']` (the Claude
SDK shape).

### tool\_use

The agent invoked a tool. Common payload fields include the tool name, input,
status, result, and tool-use id.

### reasoning

An extended-thinking / reasoning block, when the model is configured to emit it.

### step\_start

An agent step began. Payload includes a `step_index` and a description.

### step\_finish

An agent step completed, with its result.

### input\_required

The turn is paused awaiting an approval decision (tool use, file write, and
similar requests).
Payload includes `request_id`, `kind`, `tool`, `target`, `message`, and
`options`. Resolve it with `approve_once`, `approve_session`, or `deny`. See
[Inputs](/api-reference/inputs).

### error

An agent, model, or policy error. Payload includes a human-readable `message`
and may include a machine-readable `code`. In streaming mode, mid-turn failures
arrive as events rather than replacing the stream with a new HTTP response.

### done

The turn is complete. Payload carries `usage`
(`input_tokens`, `output_tokens`, `total_tokens`) and the assembled message. When
the effective model that ran the turn is known, the payload also carries `model`
(the resolved model id, e.g. `claude-sonnet-5`); it is omitted when unknown.

## Native API example

Create or resume a session, then stream a message:

```bash theme={null}
SID=$(curl -s https://api.karta.sh/v1/sessions \
  -H "Authorization: Bearer $KARTA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' | jq -r '.id')
```

```bash theme={null}
curl -N https://api.karta.sh/v1/sessions/$SID/messages \
  -H "Authorization: Bearer $KARTA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Explain quicksort","stream":true}'
```

## Managed Agents stream

The Managed Agents adapter is the full-fidelity browser and widget stream. It
maps native events into stable UI event names:

| Event                    | Meaning                                                                                                                                                                         |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `session.status_running` | The turn has started.                                                                                                                                                           |
| `agent.message`          | Agent text. Treat repeated events with the same `part_id` as replace-by-id text.                                                                                                |
| `agent.thinking`         | Reasoning text, when enabled and visible for this agent.                                                                                                                        |
| `agent.tool_use`         | A tool invocation started.                                                                                                                                                      |
| `agent.tool_result`      | A tool invocation completed or errored.                                                                                                                                         |
| `session.status_idle`    | The turn ended or paused. `stop_reason` tells you whether it ended normally or requires action. On normal completion it carries `usage` and, when known, the effective `model`. |
| `session.error`          | The turn failed.                                                                                                                                                                |

Approvals arrive as `session.status_idle` with
`stop_reason: "requires_action"`, plus the `request_id`, `tool`, `target`, and
`options` needed to render a decision UI.

## Responses stream

The OpenAI-compatible Responses adapter emits the portable Responses sequence:

```text theme={null}
event: response.created
data: {"type":"response.created","response":{"id":"resp_...","status":"in_progress"}}

event: response.output_text.delta
data: {"type":"response.output_text.delta","response_id":"resp_...","delta":"Quick"}

event: response.completed
data: {"type":"response.completed","response":{"id":"resp_...","status":"completed","output_text":"Quick..."}}
```

Use `previous_response_id` to continue the same Karta session through the
Responses API.

<CardGroup cols={2}>
  <Card title="Messages API" icon="paper-plane" href="/api-reference/messages">
    Send and stream over HTTP, with full SSE framing.
  </Card>

  <Card title="Consumer adapters" icon="plug" href="/api-reference/adapters/overview">
    The same stream, re-shaped into OpenAI and Anthropic wire formats.
  </Card>
</CardGroup>
