Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/phpaisdk/xai/llms.txt

Use this file to discover all available pages before exploring further.

Instead of waiting for an entire completion to arrive before displaying anything, streaming lets you print each token to the user as soon as xAI produces it. The aisdk/xai package exposes streaming through a native PHP Generator, so you can iterate over partial response chunks with a standard foreach loop without pulling in any additional dependencies.

Basic streaming

Replace ->run() with ->stream() to get a generator back. Iterate over it and echo each chunk as it arrives:
use AiSdk\Generate;
use AiSdk\XAI;

XAI::create(['apiKey' => 'xai-...']);

$stream = Generate::text()
    ->model(XAI::model('grok-4'))
    ->prompt('Write a short story about a robot.')
    ->stream();

foreach ($stream as $chunk) {
    echo $chunk->text;
    flush();
}
Call flush() (or ob_flush() followed by flush()) after each echo in a web context. PHP’s output buffer may otherwise hold partial output until the response ends, defeating the purpose of streaming.

How streaming works

Calling ->stream() on the builder invokes XAITextModel::stream(), which:
  1. Builds the chat completions request body with stream: true via ChatRequestBuilder.
  2. POSTs to /chat/completions on the xAI base URL (https://api.x.ai/v1 by default) using a streaming HTTP client.
  3. Returns a PHP Generator produced by ChatStreamParser::parse() from the aisdk/openai-compatible package.
Each iteration of the Generator yields one parsed server-sent event (SSE) frame from the API as a partial response object. The loop runs until the API sends the [DONE] sentinel.

Stream chunk fields

Every chunk yielded by the generator contains a partial response object with the following fields:
FieldDescription
$chunk->textThe incremental text fragment produced in this chunk. May be an empty string for the first and last frames.
Chunks do not carry token-usage data — the SDK does not accumulate partial usage across the stream. If you need final token counts, use ->run() instead.

Supported models

Streaming is declared as a first-class capability for every Grok text generation pattern in the model catalog:
Model patternStreaming supported
grok-4*✅ Yes
grok-3*✅ Yes
grok-2*✅ Yes
All three generation families list streaming in their capability set, so $model->supports(Capability::Streaming) returns true for any matching model ID.

HTTP implementation note

Under the hood XAITextModel::stream() sends a POST request to /chat/completions with "stream": true in the JSON body. The response is consumed as a chunked HTTP stream of newline-delimited SSE frames:
data: {"choices":[{"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"choices":[{"delta":{"content":" world"},"finish_reason":null}]}
data: [DONE]
Parsing is delegated entirely to ChatStreamParser from aisdk/openai-compatible, which means the xAI stream format is handled identically to any other OpenAI-compatible provider. You do not need to configure anything differently to enable streaming — xAI honours the standard SSE protocol.

Build docs developers (and LLMs) love