---
title: "Streaming"
description: "Server-Sent Events for real-time agent execution."
---

## Overview

ntrp uses a persistent SSE connection per session. Connect to `GET /chat/events/{session_id}` to receive all events (agent responses, tool calls, background task results). Messages are sent via `POST /chat/message` as fire-and-forget — the response arrives on the SSE stream.

Each event has a `type` field indicating what happened.

## Event types

### `thinking`

Agent is processing. Includes a status message.

```json
{"type": "thinking", "content": "Searching memory..."}
```

### `text`

Complete response text block.

```json
{"type": "text", "content": "Based on your calendar, you have 3 meetings today."}
```

### `text_delta`

Streamed token-level text delta. Only sent when streaming is enabled (pass `?stream=true` on the SSE connection, or enable in **Settings > Connection**).

```json
{"type": "text_delta", "content": "Based"}
```

Deltas arrive as individual tokens. Accumulate them to build the full response. A final `text` event is also sent as a complete fallback.

### `tool_call`

Agent invoked a tool.

```json
{
  "type": "tool_call",
  "name": "recall",
  "args": {"query": "meeting notes"},
  "tool_id": "tc_abc123",
  "depth": 0
}
```

### `tool_result`

Tool execution completed.

```json
{
  "type": "tool_result",
  "tool_id": "tc_abc123",
  "content": "Found 3 relevant facts...",
  "preview": "3 facts found",
  "duration": 0.45
}
```

### `approval_needed`

Tool requires user approval before executing.

```json
{
  "type": "approval_needed",
  "tool_id": "tc_abc123",
  "name": "send_email",
  "args": {"to": "alice@example.com", "subject": "..."},
  "description": "Send email to alice@example.com"
}
```

Respond with `POST /tools/result` to approve or reject.

### `session_info`

Session metadata update.

```json
{
  "type": "session_info",
  "session_id": "abc-123",
  "session_name": "Work planning"
}
```

### `done`

Execution complete. Includes token usage.

```json
{
  "type": "done",
  "usage": {
    "prompt_tokens": 1500,
    "completion_tokens": 200,
    "cache_read_tokens": 800,
    "cost": 0.012
  }
}
```

### `error`

An error occurred.

```json
{"type": "error", "content": "Rate limit exceeded", "fatal": false}
```

### `background_task`

A background task changed state (started, completed, failed, or cancelled).

```json
{"type": "background_task", "task_id": "bg_abc123", "command": "research(deep): research topic", "status": "completed"}
```

### `backgrounded`

A running agent was moved to background mode.

```json
{"type": "backgrounded", "run_id": "run_abc"}
```

### `cancelled`

User cancelled the run.

```json
{"type": "cancelled", "run_id": "run_abc"}
```

## Approval flow

When `approval_needed` is received:

1. Display the tool call to the user
2. Collect their decision (approve/reject)
3. Submit via `POST /tools/result`:

```bash
curl -X POST http://localhost:6877/tools/result \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "run_id": "run_abc",
    "tool_id": "tc_abc123",
    "result": "Approved",
    "approved": true
  }'
```

The stream continues after approval.
