HyphenHyphen
HomeConsole
  • Get Started
  • Connect your coding agent
  • Build with Hyphen
  • Chat UIs & automation
  • Recipes
  • Guides
  • API Reference
Streaming chatTool callingStructured JSONAgent loopHandling 429Long context
powered by Zudoku
Recipes

Streaming chat

Streaming works on both surfaces. Set stream: true on /v1/chat/completions, or use the Anthropic SDK's streaming helper against /v1/messages. You get server-sent events back.

Every snippet below reads the key from HYPHEN_API_KEY:

TerminalCode
export HYPHEN_API_KEY="sk-..."

OpenAI surface, Python

TerminalCode
pip install openai
Code
import os from openai import OpenAI client = OpenAI( base_url="https://api.hyphen-solution.com/v1", api_key=os.environ["HYPHEN_API_KEY"], ) stream = client.chat.completions.create( model="minimax-m3", messages=[{"role": "user", "content": "Explain a Bloom filter in three sentences."}], max_tokens=2000, stream=True, ) for chunk in stream: if not chunk.choices: continue delta = chunk.choices[0].delta.content if delta: print(delta, end="", flush=True) print()

The if not chunk.choices guard matters. The final usage chunk can arrive with an empty choices array, and indexing it blindly throws.

Getting token counts out of a stream

Ask for them. The counts arrive in a final chunk after the content is done.

Code
stream = client.chat.completions.create( model="minimax-m3", messages=[{"role": "user", "content": "Explain a Bloom filter in three sentences."}], max_tokens=2000, stream=True, stream_options={"include_usage": True}, ) for chunk in stream: if chunk.usage: print("\n", chunk.usage) elif chunk.choices and chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="", flush=True)

OpenAI surface, Node

TerminalCode
npm install openai
Code
import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.hyphen-solution.com/v1", apiKey: process.env.HYPHEN_API_KEY, }); const stream = await client.chat.completions.create({ model: "minimax-m3", messages: [{ role: "user", content: "Explain a Bloom filter in three sentences." }], max_tokens: 2000, stream: true, }); for await (const chunk of stream) { const delta = chunk.choices[0]?.delta?.content; if (delta) process.stdout.write(delta); } process.stdout.write("\n");

Save as stream.mjs and run node stream.mjs. The ?. chain does the same job as the Python guard above.

Anthropic surface, Python

The Anthropic SDK appends /v1/messages itself, so the base URL has no /v1 on it.

TerminalCode
pip install anthropic
Code
import os from anthropic import Anthropic client = Anthropic( base_url="https://api.hyphen-solution.com", api_key=os.environ["HYPHEN_API_KEY"], ) with client.messages.stream( model="minimax-m3", max_tokens=2000, system="You are terse. No preamble.", messages=[{"role": "user", "content": "Explain a Bloom filter in three sentences."}], ) as stream: for text in stream.text_stream: print(text, end="", flush=True) final = stream.get_final_message() print() print(final.usage)

stream.text_stream yields only the text deltas. Use stream.get_final_message() after the loop when you need the assembled message and the token counts.

Anthropic surface, Node

TerminalCode
npm install @anthropic-ai/sdk
Code
import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic({ baseURL: "https://api.hyphen-solution.com", apiKey: process.env.HYPHEN_API_KEY, }); const stream = client.messages.stream({ model: "minimax-m3", max_tokens: 2000, messages: [{ role: "user", content: "Explain a Bloom filter in three sentences." }], }); stream.on("text", (text) => process.stdout.write(text)); const final = await stream.finalMessage(); process.stdout.write("\n"); console.log(final.usage);

Raw SSE with curl

Useful when you are debugging a proxy and want to see the wire format.

TerminalCode
curl -N https://api.hyphen-solution.com/v1/chat/completions \ -H "Authorization: Bearer $HYPHEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "minimax-m3", "messages": [{ "role": "user", "content": "Count to five." }], "max_tokens": 2000, "stream": true }'

-N disables curl's output buffering. Without it you will sit and stare at nothing until the whole response lands. The stream ends with data: [DONE].

Nothing came out

If the stream finishes and you printed an empty string, you almost certainly set max_tokens too low. The M-series are reasoning models and internal reasoning spends the same budget as the answer. Use 2000 or more. See Choosing a model.

Related

  • Tool calling: functions on both surfaces.
  • Handling the 429 cap: what to do when the budget runs out.
  • API Reference: every parameter.
Last modified on July 28, 2026
Tool calling
On this page
  • OpenAI surface, Python
    • Getting token counts out of a stream
  • OpenAI surface, Node
  • Anthropic surface, Python
  • Anthropic surface, Node
  • Raw SSE with curl
  • Nothing came out
  • Related
Javascript
Javascript