Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions en/docs/ai-gateway/1.1.0/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ An MCP Proxy routes Model Context Protocol traffic to MCP servers. MCP is a prot
- Apply authentication and access control to MCP traffic
- Manage multiple MCP servers from a single control plane

### Streaming

When an upstream service streams its response, the gateway relays it to the client chunk by chunk instead of buffering the whole response. This holds for LLM providers, App LLM proxies, and MCP proxies, and needs no configuration. See [Streaming responses](streaming-responses.md).

## Default Ports

| Port | Service | Description |
Expand Down Expand Up @@ -115,6 +119,7 @@ You can extend the AI Gateway with custom guardrail policies by building a custo
|---------|-------------|
| [LLM](llm-proxy/quick-start-guide.md) | LLM provider configuration, guardrails, prompt management, and semantic caching |
| [MCP](mcp-proxy/quick-start-guide.md) | MCP proxy setup and policies |
| [Streaming](streaming-responses.md) | Streamed responses across providers and proxies, and how policies and analytics behave |
| [Observability](observability/logging.md) | Logging and tracing configuration |
| [Analytics](analytics/moesif-analytics.md) | Analytics integrations (Moesif) |
| [Policies and Guardrails](https://github.com/wso2/gateway-controllers/blob/main/docs/README.md) | Gateway policies and guardrails for AI traffic control |
Expand Down
108 changes: 108 additions & 0 deletions en/docs/ai-gateway/1.1.0/streaming-responses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: "Streaming Responses"
description: "Stream responses through API Platform AI Gateway chunk by chunk across LLM providers, LLM proxies, and MCP proxies, and understand how policies, analytics, and token usage behave."
canonical_url: https://wso2.com/api-platform/docs/ai-gateway/streaming-responses/
md_url: https://wso2.com/api-platform/docs/ai-gateway/streaming-responses.md
tags:
- ai-gateway
- llm
- mcp
- streaming
author: WSO2 API Platform Documentation Team
last_updated: 2026-08-04
content_type: "concept"
---

# Streaming responses

The AI Gateway forwards a streamed response to the client chunk by chunk, as each chunk arrives from the upstream service. The gateway doesn't hold the response until the upstream finishes generating it, so the first token reaches your application at about the same time it leaves the provider. Chat interfaces and agent loops keep their token-by-token behavior when they run through the gateway.

Streaming applies across the gateway's artifact types:

- **LLM providers** — a request sent straight to a provider endpoint, such as `/openai/latest/chat/completions`, streams when the upstream streams.
- **App LLM proxies** — a proxy inherits the streaming behavior of the provider it consumes.
- **MCP proxies** — request bodies stream, and responses are handled differently. See [MCP proxies](#mcp-proxies).

This page is for AI developers building on the gateway, and for platform administrators deciding which policies to attach.

## How the gateway detects a streaming response

Streaming needs no configuration on the `LlmProvider` or `Mcp` resource. The gateway decides per response, based on what the upstream sends:

- The response carries `Content-Type: text/event-stream`, which is how OpenAI-compatible providers return Server-Sent Events (SSE).
- The response carries `Transfer-Encoding: chunked`.

When either holds, the gateway switches the response body to full-duplex streaming and relays each chunk downstream as it arrives. The gateway applies the same two checks to request bodies, so a chunked or SSE request body also streams upstream.

To stream an LLM response, set `"stream": true` in the request body, exactly as you would when calling the provider directly. The following example calls an OpenAI provider deployed at `/openai/latest`:

```bash
curl -N -X POST "https://localhost:8443/openai/latest/chat/completions" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"stream": true,
"messages": [
{
"role": "user",
"content": "Write a haiku about API gateways."
}
]
}' -k
```

The same request works against an App LLM proxy. Replace `/openai/latest` with the proxy context, such as `/assistant`.

The `-N` flag turns off curl's own output buffering, so you see the SSE events as they arrive rather than all at once at the end.

## How policies behave on a streamed response

Whether a response streams depends on the policies attached to the route. A policy that reads the response body either supports chunk-by-chunk processing or requires the complete body.

**Every response-body policy on the chain must support streaming.** The gateway evaluates this per route, and it's all or nothing:

- If every response-body policy supports streaming, the gateway streams the response to the client.
- If one policy requires the complete body, the gateway buffers the entire response, runs the chain, and then sends the response in one piece. The result is still correct, but the client waits for the last token before it sees the first.

The chain spans both levels. For a request through an App LLM proxy, it covers the enterprise-wide policies the platform administrator attached to the `LlmProvider` and the application-specific policies the developer attached to the proxy. A buffered-only policy at either level buffers the response.

Policies that don't read the response body — authentication, request-side rate limiting, header policies, prompt management — never affect streaming.

### Gating policies

A streaming-capable policy can still hold bytes back when it has to. A guardrail that enforces a minimum, such as a minimum sentence count, can't rule on content it hasn't seen. Such a policy accumulates chunks silently until it has enough content to decide, releases what it has accumulated, and then processes each later chunk as it arrives. The client sees a pause at the start of the response rather than a wait for the whole response.

### MCP proxies

Response bodies on MCP proxies stay buffered, even when the MCP server replies with a chunked or SSE body. The gateway runs the response chain against the complete body and then sends it. Request bodies on MCP proxies stream under the same rules as any other route.

## Analytics on a streamed response

Analytics doesn't cost you the streaming behavior. As the gateway forwards each chunk to the client, it also keeps its own copy. At the end of the stream, it parses the accumulated SSE events and emits one analytics event for the request. The client receives every chunk at the time it arrives; the copy is only used after the stream closes.

## Token usage on a streamed response

Token counts drive analytics, cost tracking, and token-based rate limiting on LLM traffic. On a streamed response, the gateway reads them from the `usage` block that the provider sends in the stream, which arrives in the final events rather than in every chunk.

Providers differ in when they send that block:

- **OpenAI-compatible providers** omit `usage` unless the client asks for it. Add `stream_options` to the request:

```json
{
"model": "gpt-4o-mini",
"stream": true,
"stream_options": { "include_usage": true },
"messages": [{ "role": "user", "content": "Write a haiku about API gateways." }]
}
```

- **Anthropic** reports token counts in its `message_start` and `message_delta` events, so no extra request field is needed.

If a streamed response carries no `usage` block, the gateway has no token counts to record for that request. Analytics, cost calculation, and token-based rate limiting skip it. Set `stream_options` on OpenAI-compatible requests whenever you rely on any of those, including when the budget controls on the `LlmProvider` use token-based rate limiting.

## Related documentation

- [LLM Proxy Quick Start Guide](llm-proxy/quick-start-guide.md) — deploy a provider and a proxy, then send your first request
- [MCP Proxy Quick Start Guide](mcp-proxy/quick-start-guide.md) — deploy an MCP proxy
- [Sentence Count Guardrail](llm-proxy/guardrails/sentence-count.md) — a guardrail that gates a stream until it can evaluate the content
6 changes: 5 additions & 1 deletion en/docs/ai-gateway/next/llm-proxy/quick-start-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export ADMIN_USERNAME=admin
export ADMIN_PASSWORD='<the password scripts/setup.sh printed>'

# Start the complete stack
docker compose up -d
docker compose up

# Verify gateway controller admin endpoint is running
curl http://localhost:9094/api/admin/v1/health
Expand Down Expand Up @@ -182,6 +182,10 @@ curl -X POST "https://localhost:8443/assistant/chat/completions" \
}' -k
```

## View the LLM provider and proxy in AI Workspace

The gateway syncs the artifacts you deploy on it up to [AI Workspace](../../../next/ai-workspace/overview.md), the control plane for AI traffic across your organization. The OpenAI provider and the `openai-assistant` proxy you deployed above appear there without being re-declared. See [Manage Gateway-deployed AI artifacts in AI Workspace](../../../next/ai-workspace/sync-gateway-created-artifacts.md).

## Stopping the Gateway

When stopping the gateway, you have two options:
Expand Down
6 changes: 6 additions & 0 deletions en/docs/ai-gateway/next/mcp-proxy/quick-start-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ apiVersion: gateway.api-platform.wso2.com/v1
kind: Mcp
metadata:
name: everything-mcp-v1.0
annotations:
"gateway.api-platform.wso2.com/project-id": "default"
spec:
displayName: Everything
version: v1.0
Expand All @@ -127,6 +129,10 @@ To test MCP traffic routing through the gateway, add the following URL to your M
http://localhost:8080/everything/mcp
```

## View the MCP proxy in AI Workspace

The gateway syncs the artifacts you deploy on it up to [AI Workspace](../../../next/ai-workspace/overview.md), the control plane for AI traffic across your organization. The `everything-mcp-v1.0` proxy you deployed above appears there without being re-declared, in the `default` project named in its `project-id` annotation. See [Manage Gateway-deployed AI artifacts in AI Workspace](../../../next/ai-workspace/sync-gateway-created-artifacts.md).

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## Stopping the Gateway

Stop and remove the MCP backend first.
Expand Down
2 changes: 1 addition & 1 deletion en/docs/ai-gateway/next/observability/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ This starts:
To run only the core gateway services without the demonstration logging stack:

```bash
docker compose up -d
docker compose up
```

**Note:** The gateway components still log to stdout/stderr. You just won't have the centralized collection and visualization services running. You can still view logs using:
Expand Down
2 changes: 1 addition & 1 deletion en/docs/ai-gateway/next/observability/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ This starts:
To run only the core gateway services without the demonstration tracing stack:

```bash
docker compose up -d
docker compose up
```

**Note:** If tracing is enabled in the configuration but the OTLP collector is not running, components will log warnings about failed trace exports. To completely disable tracing, set `enabled = false` in the configuration.
Expand Down
5 changes: 5 additions & 0 deletions en/docs/ai-gateway/next/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ An MCP Proxy routes Model Context Protocol traffic to MCP servers. MCP is a prot
- Apply authentication and access control to MCP traffic
- Manage multiple MCP servers from a single control plane

### Streaming

When an upstream service streams its response, the gateway relays it to the client chunk by chunk instead of buffering the whole response. This holds for LLM providers, LLM proxies, and MCP proxies, and needs no configuration. See [Streaming responses](streaming-responses.md).

## Default Ports

| Port | Service | Description |
Expand Down Expand Up @@ -112,6 +116,7 @@ You can extend the AI Gateway with custom guardrail policies by building a custo
|---------|-------------|
| [LLM](llm-proxy/quick-start-guide.md) | LLM provider configuration, guardrails, prompt management, and semantic caching |
| [MCP](mcp-proxy/quick-start-guide.md) | MCP proxy setup and policies |
| [Streaming](streaming-responses.md) | Streamed responses across providers and proxies, and how policies and analytics behave |
| [Observability](observability/logging.md) | Logging and tracing configuration |
| [Analytics](analytics/moesif-analytics.md) | Analytics integrations (Moesif) |
| [Policies and Guardrails](https://github.com/wso2/gateway-controllers/blob/main/docs/README.md) | Gateway policies and guardrails for AI traffic control |
Expand Down
Loading