Web Asset House Guides
Local AI

Ollama Streaming Responses: NDJSON Chunks, stream: false, and Handling Thinking and Tool Calls

By Web Asset House Studio ·

Note: Some future links on this site may be affiliate links. We never claim hands-on testing; guides are researched from the public sources listed in each article.

How we wrote this: A summary of Ollama's official Streaming (API reference), Streaming (capabilities) and Errors pages (linked below), checked October 29, 2026.

When you chat with a model in Ollama's app, words appear as they're generated. That's streaming. If you build on Ollama's local API, you choose whether to receive the answer piece by piece or all at once, and the defaults differ depending on how you call it.

The defaults

The docs give one rule that surprises people:

So a curl request that "returns a pile of JSON lines" and a library call that "returns one object" are both behaving as designed.

What a stream looks like

Streamed responses use newline-delimited JSON (content type application/x-ndjson): one JSON object per line, each carrying a small piece of the answer. In the docs' /api/generate example, each line has a response field with a token or two and "done": false. The last line has "done": true and a done_reason, such as "stop".

To rebuild the full answer, read line by line, parse each one, and append the text until you see done: true. With /api/chat, the text is in message.content instead of response.

Turning it off

Add "stream": false to the request body for any endpoint that supports streaming. The docs say you then get a single application/json object containing the complete text, with done: true.

Which to use

The docs' own guidance:

Streaming (default) Non-streaming
Real-time generation Simpler to process
Lower perceived latency Better for short responses
Better for long generations Better for structured outputs
Easier to handle in some applications

A chat interface almost always wants streaming. A script that classifies text or extracts JSON is usually simpler without it.

Streaming with thinking and tool calls

The capabilities page covers what else can show up in chunks:

The docs stress one thing: accumulate the partial fields. Add up the thinking text and the content text as they arrive, then append a single assistant message with both to your message history for the next request. For tool calling this matters even more, since the model's thinking, its tool call and the tool result all need to go back in the next request.

The docs' Python example loops over the stream, prints chunk.message.thinking under a "Thinking:" label and chunk.message.content under "Answer:", and adds each to a running string. The Python library guide and JavaScript library guide cover setup.

Errors in the middle of a stream

Ollama's Errors page explains a subtlety. Normally, an error comes back with an HTTP status such as 400 (bad request), 404 (model not found), 429 (rate limit), 500 (server error) or 502 (cloud model unreachable), with a JSON body like {"error": "..."}.

But if something fails after streaming has started, the status code has already been sent and won't change. The error arrives as one more NDJSON line with an error property. So your stream reader should check every line for an error key, not just the HTTP status. Our troubleshooting guide shows where to look in the server logs when that happens.

Quick checklist

Sources

← All Local AI guides · All guides