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

# TypeScript SDK - Stream Method

> Complete guide to the stream() method in the TypeScript SDK.

The `stream()` method is used to make streaming chat completion requests to the Edgee AI Gateway. It returns an `AsyncGenerator<StreamChunk>` that yields response chunks as they arrive from the API.

## Arguments

The `stream()` method accepts two arguments:

| Parameter | Type | Description |
| - | - | - |
| `model` (The field is required.) | `string` | The model identifier to use (e.g., `"openai/gpt-5.2"`) |
| `input` (The field is required.) | `string \| InputObject` | The input for the completion. Can be a simple string or a structured `InputObject` |

### Input Types

#### String Input

When `input` is a string, it's automatically converted to a user message:

```typescript theme={"dark"}
for await (const chunk of edgee.stream('gpt-5.2', 'Tell me a story')) {
  if (chunk.text) {
    process.stdout.write(chunk.text);
  }

  if (chunk.finishReason) {
    console.log(`\nFinished: ${chunk.finishReason}`);
  }
}
// Equivalent to: input: { messages: [{ role: 'user', content: 'Tell me a story' }] }
```

#### InputObject

When `input` is an `InputObject`, you have full control over the conversation:

| Property | Type | Description |
| - | - | - |
| `messages` (The field is required.) | `Message[]` | Array of conversation messages |
| `tools` | `Tool[]` | Array of function tools available to the model |
| `tool_choice` | `ToolChoice` | Controls which tool (if any) the model should call. See [Tools documentation](https://www.edgee.ai/docs/llm-router/sdk/typescript/tools.md) for details |
| `tags` | `string[]` | Optional tags to categorize and label the request for analytics and filtering. Can also be sent via the `x-edgee-tags` header (comma-separated) |
| `compression_model` | `string` | Compression model for this request: `"claude"`, `"codex"`, `"opencode"`, `"cursor"`. Each model is a bundle of compression strategies. Overrides API key settings when present. |

For details about `Message` type, see the [Send Method documentation](https://www.edgee.ai/docs/llm-router/sdk/typescript/send.md#message-object).
For details about `Tool` and `ToolChoice` types, see the [Tools documentation](https://www.edgee.ai/docs/llm-router/sdk/typescript/tools.md).

**Example - Streaming with Messages:**

```typescript theme={"dark"}
for await (const chunk of edgee.stream('gpt-5.2', {
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'Write a poem about coding' }
  ]
})) {
  if (chunk.text) {
    process.stdout.write(chunk.text);
  }
}
```

## Return Value

The `stream()` method returns an `AsyncGenerator<StreamChunk>`. Each chunk contains incremental updates to the response.

### StreamChunk Object

Each chunk yielded by the generator has the following structure:

| Property | Type | Description |
| - | - | - |
| `choices` | `StreamChoice[]` | Array of streaming choices (typically one) |
| `compression` | `Compression \| null` | Token compression metrics (if compression was applied) |

### StreamChoice Object

Each choice in the `choices` array contains:

| Property | Type | Description |
| - | - | - |
| `index` | `number` | The index of this choice in the array |
| `delta` | `StreamDelta` | The incremental update to the message |
| `finish_reason` | `string \| null \| undefined` | Reason why the generation stopped. Only present in the final chunk. Possible values: `"stop"`, `"length"`, `"tool_calls"`, `"content_filter"`, or `null` |

**Example - Handling Multiple Choices:**

```typescript theme={"dark"}
for await (const chunk of edgee.stream('gpt-5.2', 'Give me creative ideas')) {
  chunk.choices.forEach((choice, index) => {
    if (choice.delta.content) {
      console.log(`Choice ${index}: ${choice.delta.content}`);
    }
  });
}
```

### StreamDelta Object

The `delta` object contains incremental updates:

| Property | Type | Description |
| - | - | - |
| `role` | `string \| undefined` | The role of the message (typically `"assistant"`). Only present in the **first chunk** |
| `content` | `string \| undefined` | Incremental text content. Each chunk contains a portion of the full response |
| `tool_calls` | `ToolCall[] \| undefined` | Array of tool calls (if any). See [Tools documentation](https://www.edgee.ai/docs/llm-router/sdk/typescript/tools.md) for details |

## Convenience Properties

The `StreamChunk` class provides convenience getters for easier access:

| Property | Type | Description |
| - | - | - |
| `text` | `string \| null` | Shortcut to `choices[0].delta.content` - the incremental text content |
| `role` | `string \| null` | Shortcut to `choices[0].delta.role` - the message role (first chunk only) |
| `finishReason` | `string \| null` | Shortcut to `choices[0].finish_reason` - the finish reason (final chunk only) |

**Example - Using Convenience Properties:**

```typescript theme={"dark"}
for await (const chunk of edgee.stream('gpt-5.2', 'Explain quantum computing')) {
  // Content chunks
  if (chunk.text) {
    process.stdout.write(chunk.text);
  }

  // First chunk contains the role
  if (chunk.role) {
    console.log(`Role: ${chunk.role}`);
  }

  // Last chunk contains finish reason
  if (chunk.finishReason) {
    console.log(`\nFinish reason: ${chunk.finishReason}`);
  }
}
```

## Understanding Streaming Behavior

### Chunk Structure

1. **First chunk**: Contains `role` (typically `"assistant"`) and may contain initial `content`
2. **Content chunks**: Contain incremental `content` updates
3. **Final chunk**: Contains `finish_reason` indicating why generation stopped

**Example - Collecting Full Response:**

```typescript theme={"dark"}
let fullText = '';

for await (const chunk of edgee.stream('gpt-5.2', 'Tell me a story')) {
  if (chunk.text) {
    fullText += chunk.text;
    process.stdout.write(chunk.text); // Also display as it streams
  }
}

console.log(`\n\nFull response (${fullText.length} characters):`);
console.log(fullText);
```

### Finish Reasons

| Value | Description |
| - | - |
| `"stop"` | Model generated a complete response and stopped naturally |
| `"length"` | Response was cut off due to token limit |
| `"tool_calls"` | Model requested tool/function calls |
| `"content_filter"` | Content was filtered by safety systems |
| `null` | Generation is still in progress (not the final chunk) |

### Empty Chunks

Some chunks may not contain `content`. This is normal and can happen when:

* The chunk only contains metadata (role, finish\_reason)
* The chunk is part of tool call processing
* Network buffering creates empty chunks

Always check for `chunk.text` before using it:

```typescript theme={"dark"}
for await (const chunk of edgee.stream('gpt-5.2', 'Hello')) {
  if (chunk.text) {  // ✅ Good: Check before using
    console.log(chunk.text);
  }
  // ❌ Bad: console.log(chunk.text) - may log null
}
```

## Error Handling

The `stream()` method can throw errors:

```typescript theme={"dark"}
try {
  for await (const chunk of edgee.stream('gpt-5.2', 'Hello!')) {
    if (chunk.text) {
      process.stdout.write(chunk.text);
    }
  }
} catch (error) {
  if (error instanceof Error) {
    // API errors: "API error {status}: {message}"
    // Network errors: Standard fetch errors
    console.error('Stream failed:', error.message);
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.