
n8n AI Agent Streaming Not Working (2026 Fixes)
Streaming in n8n is two switches, not one. The trigger has to be in streaming response mode, and the AI Agent node has to still have its own streaming option on. Turn off either one and n8n doesn't complain — it quietly falls back to request/response and hands you the entire answer in one payload at the end, which from the browser looks identical to a broken stream. That's most of these. The rest are a node in the response path, a buffering proxy, a sub-workflow, or an old image.
How Streaming Actually Works in n8n
There are exactly two ends to this. The producing end is a node that can emit fragments as it generates them — the AI Agent node, or a Respond to Webhook node. The delivering end is the trigger: a Chat Trigger set to Streaming response, or a Webhook node set to stream under Respond. Both have to agree.
n8n's own documentation says it plainly: “Even with streaming enabled on the trigger, you need at least one node configured to stream data. Otherwise, your workflow will send no data.” In practice you don't get nothing — you get the normal end-of-run response, which is worse, because nothing looks broken until a user tells you the chatbot “feels slow.”
Worth saying early: this is not a paid feature. Streaming is documented as available on all plans, so a self-hosted community instance can do it. That puts it in a different bucket from the things that genuinely are license-gated, which I went through in n8n Cloud vs self-hosted.
What streaming does and doesn't buy you:
It does not make the agent faster. An agent that takes nine seconds to finish still takes nine seconds. What changes is that the first words land in well under a second instead of at second nine. Same total, completely different product — and the same token bill either way.
Cause 1: Only One End Is Streaming
This is the answer most of the time, and it is boring in the best way. Someone flips the Chat Trigger to streaming, tests, sees one blob, and starts rewriting frontend code. The AI Agent node still has streaming switched off.
It catches people because the default is on, so nobody thinks to look. But the option is switchable, and it survives export/import — so any workflow you pulled from a template, inherited from a contractor, or restored from a JSON backup can arrive with it off and no visual indication on the canvas. Open the node, open Options, confirm.
The 30-second test: hit the chat URL with curl -N and watch the terminal. If lines trickle in, streaming works and your problem is in the browser. If one big response lands at the end, streaming never started and your problem is in the workflow. Do this before you touch any client code — it splits the search space in half and costs nothing.
Cause 2: Something Sits Between the Agent and the Response
You wired Agent → Guardrail → Respond to Webhook, or Agent → Set → Respond, because you wanted to sanitize the output. Now everything “streams” and the client still receives it all at once.
This is exactly what happened in issue #25982: an output guardrail between the agent and the response node, and the client gets a single item message carrying the complete output instead of many partial ones. It was closed as not planned, which is the correct call — it isn't really a bug. A node that inspects the whole answer has to wait for the whole answer. Buffering is the feature.
So pick one. Either the agent streams straight to the trigger and you accept unvalidated text on the wire, or you validate and give up streaming. If you need both, do it in the right order: stream to the user for perceived speed, and run validation on a separate branch that fires a correction or a takedown if it fails. Ugly, but honest — you cannot check a sentence you haven't finished reading.
Cause 3: You Expected Tool Calls to Stream
Different failure, same symptom: nothing appears for eight seconds while the agent calls two tools, then the answer streams beautifully. Streaming is working. It just has nothing to say yet.
For a long time only the final text streamed, and issue #28271 — asking for intermediate steps over webhook streaming — was closed as not planned. Tool-call chunk types have since been added to the protocol, so newer builds can emit tool-call-start and tool-call-end events alongside the text. Whether yours does depends on your version.
Don't design a “thinking” UI on faith. Log every chunk type you receive across one real run, then build against that list. This is the same discipline as instrumenting an n8n agent properly: the run tells you what it does, the docs tell you what it was supposed to do, and the gap between those two is where your evening goes.
If your version stays silent during tool calls, send a status line yourself before the agent node — even a static “Checking your order…” beats a blank box, because the thing users actually hate is not latency, it's uncertainty.
Cause 4: Your Proxy Is Buffering the Stream
My favorite one, because n8n is completely innocent and the logs are completely clean. It works on localhost:5678. It does not work on your domain. Nothing errors anywhere.
A streaming response is just a long chunked HTTP response held open. A reverse proxy with default settings will happily collect the entire body before forwarding it — that's normally a good thing, it protects your upstream from slow clients. Here it silently reassembles your stream into the exact blob you were trying to avoid.
The three usual suspects, in the order I check them:
1. NGINX buffering. Set proxy_buffering off; on the location that serves your webhook or chat path. Also set proxy_read_timeouthigh enough that a long agent run isn't cut off mid-answer.
2. Compression. gzip or brotli applied to the response will buffer to get something worth compressing. Turn it off for that route — gzip off;, or the equivalent middleware exclusion in Traefik or Caddy. A stream of tiny text chunks doesn't compress meaningfully anyway.
3. The layer you forgot about. An ingress controller, an API gateway, a CDN rule, a tunnel. If you front n8n with anything — and if you followed my setup for putting n8n webhooks behind Cloudflare Access you do — that layer gets a vote on whether bytes move.
The bisect that ends the argument
Run curl -N http://localhost:5678/webhook/<path> on the host, then the same request against the public URL. Chunks on one and not the other means the fault is in the middle, and you can stop reading n8n's source at 1am. If NGINX config is out of your hands, have n8n's response carry X-Accel-Buffering: no — NGINX honors it per-response.
Cause 5: The Agent Lives in a Sub-Workflow
You refactored. The chat trigger is in the parent workflow, the agent got moved into a child called by Execute Workflow, and streaming stopped the day you did it.
Streaming is a property of a live HTTP response bound to oneexecution. A sub-workflow is a separate execution that returns its result to the parent when it's done — that boundary is a buffer by construction. The child finishes, hands back the finished output, and the parent sends it. Nothing to stream.
If the response has to stream, the agent belongs in the same workflow as the trigger. Keep sub-workflows for the work that happens after you've replied, or for tools whose output the agent will summarize anyway. That trade-off is the same one I laid out in tool vs sub-workflow, with one extra rule bolted on: the response path cannot cross an execution boundary.
Cause 6: The Option Isn't There Yet
If you have read this far and cannot even find a streaming response mode on the Chat Trigger, stop debugging. You're on an old image.
Streaming landed in the 1.106 line and the protocol has kept growing since — the tool-call chunk types are newer than the text ones. Self-hosted instances drift; I've opened client stacks pinned eleven months back because an upgrade broke something once in 2025 and nobody revisited it. Check your version in the UI before you spend an hour on a feature your build doesn't have.
Pull a current image, verify your workflows still run, and then debug. And if you're running queue mode, upgrade main and workers together — a version skew between them produces failures far stranger than a missing checkbox.
What the Stream Actually Looks Like
If you're building a custom frontend instead of using the hosted chat, you need this. n8n sends newline-delimited JSON — one object per line, over a single chunked response. Each object carries a type and a metadata block naming the node that produced it:
{"type":"begin","metadata":{"nodeId":"a1","nodeName":"AI Agent","runIndex":0}}
{"type":"item","content":"Your ","metadata":{"nodeId":"a1","nodeName":"AI Agent"}}
{"type":"item","content":"order ","metadata":{"nodeId":"a1","nodeName":"AI Agent"}}
{"type":"item","content":"shipped.","metadata":{"nodeId":"a1","nodeName":"AI Agent"}}
{"type":"end","metadata":{"nodeId":"a1","nodeName":"AI Agent","runIndex":0}}The core four are begin, item, end and error. Node-execution and tool-call events ride the same channel with their own types. Consuming it is unremarkable, and the only part people get wrong is line buffering:
const res = await fetch(CHAT_URL, { method: "POST", body: JSON.stringify(payload) });
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buf = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
const lines = buf.split("\n");
buf = lines.pop() ?? ""; // keep the partial line for next round
for (const line of lines) {
if (!line.trim()) continue;
const chunk = JSON.parse(line);
if (chunk.type === "item") append(chunk.content);
if (chunk.type === "error") showError(chunk);
}
}That buf = lines.pop()line is the whole trick. TCP does not respect your line breaks — a read can hand you half a JSON object, and code that parses every fragment immediately throws intermittently under exactly the conditions you can't reproduce locally: real network, real latency, longer answers.
What Streaming Changes Operationally
Errors get worse, not better. Once you've sent bytes you cannot un-send them. A failure at second six can't become a clean 500 with a friendly message — the user is already looking at half a sentence. Handle errorchunks explicitly in the client and decide what a truncated answer should look like, because “the text just stops” is the default and it's awful.
Cost is identical. Same prompt, same tokens, same bill. You are changing delivery, not consumption. Anyone selling streaming as an optimization is selling you a UX change with a performance word attached.
Connections are held open longer. Every streaming chat is a live socket for the duration of the run. That's fine at ten concurrent users and it is a capacity question at a thousand — worth pairing with a real look at how you scale n8n, plus timeouts at every proxy hop that are longer than your worst-case agent run.
Approvals and streaming don't mix. If a human-in-the-loop step can pause the run, you now have an HTTP response hanging open while somebody reads Slack. Reply first, act after approval, and notify separately.
The Order I Actually Check Things
Roughly ten minutes, and it has never taken me past step four:
1. Version.If the option isn't in the node, nothing else matters.
2. Both switches. Trigger in streaming response mode, AI Agent streaming still enabled. This is the answer most of the time.
3. The response path. Nothing between the agent and the trigger. No guardrail, no Set, no Code, no sub-workflow.
4. curl -N on the host, then on the domain.Different results means the proxy is buffering. Same results means it's the workflow.
5. The client's line buffering. Only after all of the above, and only if the terminal already shows chunks arriving.
If you do one thing today:
Run curl -N against your chat webhook from the n8n host itself. Ten seconds of typing tells you which half of the stack to stop suspecting — and that single fact is worth more than every config change you were about to make blind.
Frequently Asked Questions
Why is my n8n AI agent not streaming?
Almost always because streaming is enabled on only one end. n8n needs the trigger set to a streaming response mode and at least one node in the workflow actually configured to stream, normally the AI Agent node. If the trigger streams and the agent does not, n8n opens a stream, waits for chunks that never arrive, and falls back to sending the whole response at once. It does not raise an error, which is why this reads as a frontend bug when it is a two-checkbox problem. Check the AI Agent node options first: streaming is on by default but it is switchable, and imported or templated workflows frequently have it off.
Does n8n streaming work with self-hosted community edition?
Yes. n8n documents streaming responses as available on all plans, including self-hosted community, so there is no license gate the way there is for external secrets or environments. The real constraint is version. Streaming shipped in the 1.106 line and the chunk protocol has kept growing since, so a self-hosted instance pinned to an older image simply will not show the option in the node. If you cannot find a streaming response mode on the Chat Trigger, do not go looking for a setting: pull a newer image first.
Why does streaming work locally but not behind my domain?
Because something between n8n and the browser is buffering. Streaming is a long-lived chunked HTTP response, and a default reverse proxy config will happily collect the whole body before forwarding it, which converts your stream back into one delivery. Prove it with curl -N straight against the n8n port on the host. If chunks appear there and not through the public URL, fix the proxy: proxy_buffering off on the NGINX location, gzip off for that route, or an X-Accel-Buffering: no response header. Response compression middleware on a CDN or ingress does the same thing for the same reason.
Can n8n stream the agent's tool calls and intermediate steps?
Historically no. For a long time only the final answer streamed, and users who expected to watch the agent think reported it as a bug; the issue asking for intermediate steps over webhook streaming was closed as not planned. Support for tool-call chunk types has since been added to the streaming protocol, so newer versions can emit tool-call-start and tool-call-end alongside the text chunks. Check what your instance actually sends before you design a UI around it: log every chunk type you receive for one run and build against that, not against a blog post.
What format does n8n send streaming chunks in?
Newline-delimited JSON objects, one per line, over a single chunked HTTP response. Each object has a type and a metadata block identifying which node produced it. The core types are begin, item, end and error: begin marks a node starting to stream, each item carries a content string holding a fragment of the answer, and end closes that node's output. Node execution and tool call events use their own types. A client reads the body as a stream, buffers partial lines, and parses each complete line, appending content whenever the type is item.
Building a chat agent your customers will actually wait for?
I build n8n agent stacks that hold up in production — streaming responses that survive the proxy, error paths that degrade gracefully mid-answer, and observability that shows you what the agent did instead of what it claimed. If your chatbot works on localhost and disappoints on the domain, I can find the layer that's eating it.
Related Posts
n8n
n8n Human-in-the-Loop AI Agent Approvals (2026)
n8n's human-in-the-loop step pauses an agent before a tool runs and waits for a person to click Approve or Deny. It works, and it breaks in five specific ways: the approval link is a bearer token so possession is authority, the gate belongs to the tool rather than the agent, an unanswered approval waits forever unless you set a limit, the pending execution is only as durable as your database, and a Deny is just a string the model is free to ignore. The five failure modes and the gate I run instead.
n8n
n8n Cloud vs Self-Hosted in 2026: The Real Math
n8n removed active-workflow limits from every plan in 2026, so the old reason to self-host is gone. What you buy now is a monthly execution allowance and a concurrency ceiling — and the jump from Pro to Business is 4x the executions for 13x the price. Measured numbers from my own instance: 179 workflows, ~5,600 executions a month, a median run under one second, and why AI agent workflows break the concurrency assumption entirely.
n8n
n8n MCP Server vs MCP Server Trigger: Which One You Actually Need
n8n ships two features named some version of "MCP server" and they do opposite jobs. The built-in server is instance-level — one connection lets an AI client list, build, update and run workflows across your whole n8n, and since April 29 2026 it can author workflows from scratch. The MCP Server Trigger node is workflow-level, exposing only the tools you attach. Pick by blast radius, plus the queue-mode routing gotcha that silently breaks SSE.