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:
Code
export HYPHEN_API_KEY="sk-..."
OpenAI surface, Python
Code
pip install openai
Code
import osfrom openai import OpenAIclient = 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
Code
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.
Code
pip install anthropic
Code
import osfrom anthropic import Anthropicclient = 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
Code
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.
-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.