> For the complete documentation index, see [llms.txt](https://docs.umbraco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.umbraco.com/ai-in-umbraco/17.latest/add-ons/agent/streaming.md).

# Streaming

Agents expose two streaming endpoints that both return Server-Sent Events (SSE) with `Content-Type: text/event-stream`:

* [`POST /agents/{agentIdOrAlias}/stream`](/ai-in-umbraco/17.latest/add-ons/agent/api/stream.md) streams `AgentResponseUpdate` objects from Microsoft.Extensions.AI.
* [`POST /agents/{agentIdOrAlias}/stream-agui`](/ai-in-umbraco/17.latest/add-ons/agent/api/stream-agui.md) streams [AG-UI protocol](https://docs.ag-ui.com/) events.

This page describes the AG-UI event types. AG-UI event `type` values are `UPPER_SNAKE_CASE` strings that match the official AG-UI specification.

## SSE Format

Each event is serialised as a single SSE `data:` line containing the full event JSON, followed by a blank line. The event type is embedded in the JSON payload as the `type` property (via a polymorphic type discriminator) — there is no separate `event:` line.

```
data: {"type":"RUN_STARTED","threadId":"t-1","runId":"r-1"}

data: {"type":"TEXT_MESSAGE_START","messageId":"m-1","role":"assistant"}

data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"m-1","delta":"Hello"}

data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"m-1","delta":" world"}

data: {"type":"TEXT_MESSAGE_END","messageId":"m-1"}

data: {"type":"RUN_FINISHED","threadId":"t-1","runId":"r-1","outcome":"success"}
```

All events inherit from `BaseAGUIEvent` and therefore also carry two optional common fields:

| Property    | Type     | Description                                            |
| ----------- | -------- | ------------------------------------------------------ |
| `timestamp` | `number` | Optional Unix milliseconds timestamp.                  |
| `rawEvent`  | `object` | Optional passthrough of the underlying provider event. |

## Event Types

### Lifecycle Events

#### RUN\_STARTED

Sent when an agent run begins.

```json
{
    "type": "RUN_STARTED",
    "threadId": "t-1",
    "runId": "r-1",
    "parentRunId": "parent-r-0",
    "input": { "custom": "data" }
}
```

| Property      | Type          | Required | Description                                     |
| ------------- | ------------- | -------- | ----------------------------------------------- |
| `threadId`    | `string`      | Yes      | Conversation thread identifier.                 |
| `runId`       | `string`      | Yes      | Identifier for this run.                        |
| `parentRunId` | `string`      | No       | Set when this run is nested inside another run. |
| `input`       | `JsonElement` | No       | Optional input payload captured at the start.   |

#### RUN\_FINISHED

Sent when an agent run completes (successfully or via an interrupt).

```json
{
    "type": "RUN_FINISHED",
    "threadId": "t-1",
    "runId": "r-1",
    "outcome": "success"
}
```

| Property    | Type     | Required | Description                                      |
| ----------- | -------- | -------- | ------------------------------------------------ |
| `threadId`  | `string` | Yes      | Conversation thread identifier.                  |
| `runId`     | `string` | Yes      | Identifier for the completed run.                |
| `outcome`   | `string` | Yes      | `success` or `interrupt`. Defaults to `success`. |
| `interrupt` | `object` | No       | Set when `outcome` is `interrupt`.               |
| `error`     | `string` | No       | Optional error message string.                   |
| `result`    | `object` | No       | Optional result payload.                         |

#### RUN\_ERROR

Sent when an agent run fails.

```json
{
    "type": "RUN_ERROR",
    "message": "Rate limit exceeded",
    "code": "rate_limit"
}
```

| Property  | Type     | Required | Description                           |
| --------- | -------- | -------- | ------------------------------------- |
| `message` | `string` | Yes      | Human-readable error message.         |
| `code`    | `string` | No       | Optional machine-readable error code. |

#### STEP\_STARTED

Sent when a named step inside a run begins. Useful for orchestrated workflows that emit progress per sub-agent.

```json
{
    "type": "STEP_STARTED",
    "stepName": "Researcher"
}
```

#### STEP\_FINISHED

Sent when a named step inside a run completes.

```json
{
    "type": "STEP_FINISHED",
    "stepName": "Researcher"
}
```

### Text Message Events

#### TEXT\_MESSAGE\_START

Marks the start of a streaming text message.

```json
{
    "type": "TEXT_MESSAGE_START",
    "messageId": "m-1",
    "role": "assistant"
}
```

| Property    | Type     | Required | Description                                                |
| ----------- | -------- | -------- | ---------------------------------------------------------- |
| `messageId` | `string` | Yes      | Identifier of the message being streamed.                  |
| `role`      | `string` | Yes      | Message role (`user`, `assistant`, `system`, `tool`, etc.) |

#### TEXT\_MESSAGE\_CONTENT

Carries a text delta for the message.

```json
{
    "type": "TEXT_MESSAGE_CONTENT",
    "messageId": "m-1",
    "delta": "Here's how you can "
}
```

| Property    | Type     | Required | Description                              |
| ----------- | -------- | -------- | ---------------------------------------- |
| `messageId` | `string` | Yes      | Identifier of the message being streamed |
| `delta`     | `string` | Yes      | Text fragment to append to the message.  |

#### TEXT\_MESSAGE\_END

Marks the end of a streaming text message.

```json
{
    "type": "TEXT_MESSAGE_END",
    "messageId": "m-1"
}
```

#### TEXT\_MESSAGE\_CHUNK

Convenience event that combines start + content + end in a single event for simpler streaming scenarios. All fields are optional.

```json
{
    "type": "TEXT_MESSAGE_CHUNK",
    "messageId": "m-1",
    "role": "assistant",
    "delta": "Hello world"
}
```

### Tool Events

#### TOOL\_CALL\_START

Sent when the agent begins calling a tool.

```json
{
    "type": "TOOL_CALL_START",
    "toolCallId": "tc-1",
    "toolCallName": "insert_content",
    "parentMessageId": "m-1"
}
```

| Property          | Type     | Required | Description                                                |
| ----------------- | -------- | -------- | ---------------------------------------------------------- |
| `toolCallId`      | `string` | Yes      | Unique identifier for this tool call.                      |
| `toolCallName`    | `string` | Yes      | Name of the tool being invoked.                            |
| `parentMessageId` | `string` | No       | Optional ID of the assistant message this call belongs to. |

#### TOOL\_CALL\_ARGS

Streams argument deltas for a tool call. Arguments are typically a JSON object streamed as string fragments; clients concatenate the deltas and parse the final string.

```json
{
    "type": "TOOL_CALL_ARGS",
    "toolCallId": "tc-1",
    "delta": "{\"content\":"
}
```

#### TOOL\_CALL\_END

Signals that the tool call arguments are complete. Clients should now execute the tool with the accumulated arguments.

```json
{
    "type": "TOOL_CALL_END",
    "toolCallId": "tc-1"
}
```

#### TOOL\_CALL\_RESULT

Carries the result of a tool execution (typically emitted by the backend for server-side tools).

```json
{
    "type": "TOOL_CALL_RESULT",
    "messageId": "m-2",
    "toolCallId": "tc-1",
    "content": "{\"status\":\"ok\"}",
    "role": "tool"
}
```

| Property     | Type     | Required | Description                                 |
| ------------ | -------- | -------- | ------------------------------------------- |
| `messageId`  | `string` | Yes      | Identifier of the tool result message.      |
| `toolCallId` | `string` | Yes      | Identifier of the tool call being answered. |
| `content`    | `string` | Yes      | Serialised result content.                  |
| `role`       | `string` | No       | Role for the result (typically `"tool"`).   |

#### TOOL\_CALL\_CHUNK

Convenience event combining tool call start + args + end. All fields are optional.

```json
{
    "type": "TOOL_CALL_CHUNK",
    "toolCallId": "tc-1",
    "toolCallName": "insert_content",
    "delta": "{\"content\":\"Hello\"}"
}
```

### State Events

#### STATE\_SNAPSHOT

Carries a full snapshot of the current agent state. Consumers should replace their local state with this snapshot.

```json
{
    "type": "STATE_SNAPSHOT",
    "snapshot": {
        "status": "thinking",
        "currentStep": "Researcher"
    }
}
```

#### STATE\_DELTA

Carries a JSON Patch (RFC 6902) to apply to the current state.

```json
{
    "type": "STATE_DELTA",
    "delta": [
        { "op": "replace", "path": "/status", "value": "executing" }
    ]
}
```

#### MESSAGES\_SNAPSHOT

Carries the full list of messages (useful after reconnect or recovery).

```json
{
    "type": "MESSAGES_SNAPSHOT",
    "messages": [
        { "id": "m-1", "role": "user", "content": "Hello" }
    ]
}
```

### Activity Events

Activity messages are frontend-only UI updates (such as "thinking", "searching", "processing") that do not become part of the conversation history.

#### ACTIVITY\_SNAPSHOT

```json
{
    "type": "ACTIVITY_SNAPSHOT",
    "messageId": "act-1",
    "activityType": "thinking",
    "content": "Analysing the request...",
    "replace": true
}
```

| Property       | Type      | Required | Description                                                            |
| -------------- | --------- | -------- | ---------------------------------------------------------------------- |
| `messageId`    | `string`  | Yes      | Identifier of the activity message.                                    |
| `activityType` | `string`  | Yes      | Activity category (e.g., `thinking`, `searching`, `processing`).       |
| `content`      | `string`  | Yes      | Activity content to display.                                           |
| `replace`      | `boolean` | No       | When `true`, replaces any existing activity with the same `messageId`. |

#### ACTIVITY\_DELTA

Applies incremental updates to an activity snapshot using JSON Patch.

```json
{
    "type": "ACTIVITY_DELTA",
    "messageId": "act-1",
    "activityType": "thinking",
    "patch": [
        { "op": "replace", "path": "/content", "value": "Updated thinking..." }
    ]
}
```

### Special Events

#### CUSTOM

An application-specific event. The `name` identifies the custom event and `value` carries arbitrary data.

```json
{
    "type": "CUSTOM",
    "name": "confetti",
    "value": { "intensity": "high" }
}
```

#### RAW

Passes an unprocessed provider event through to the client.

```json
{
    "type": "RAW",
    "event": { "originalType": "x", "data": "..." },
    "source": "provider-name"
}
```

## Related

* [Concepts](/ai-in-umbraco/17.latest/add-ons/agent/concepts.md) - AG-UI protocol overview
* [Frontend Tools](/ai-in-umbraco/17.latest/add-ons/agent/frontend-tools.md) - Handling tool calls
* [Frontend Client](/ai-in-umbraco/17.latest/add-ons/agent/frontend-client.md) - `UaiAgentClient` for consuming these events


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.umbraco.com/ai-in-umbraco/17.latest/add-ons/agent/streaming.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
