A reset upstream stream drops the turn into a silent non-streaming fallback, which the idle watchdog then kills at 900s #276
Loading…
Reference in a new issue
No description provided.
Delete branch "claude/wi-019faa3e-a-reset-upstream-stream-drops-the-turn-i"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Anima work item
019faa3e-5966-7d22-923d-251ae96b6e30.The chain, measured end to end on 2026-07-28 (workspace
tecton, glm-5.2 via ollama.com)shell_exectool calls in 90s, inter-event gaps 3–19snarrativedelta — the idle watchdog's clock starts hereWARN agentic_chat: streaming chat failed (chat backend "ollama" turn failed: Ollama server unreachable at https://ollama.com/api/chat: Network Error: Connection reset by peer (os error 104)); falling back to non-streaming agent_id="tecton"idle_secs=900 last_step="narrative" last_step_age_secs=900 stop_reason=Refusal, and the complete assistant message lands in the same secondThree stalls with this identical signature inside five minutes.
Two defects, one visible symptom
1. The fallback is a liveness black hole.
chat_with_tools_streamingfailing drops the round intochat_with_tools(src/agent/agentic_chat.rs:493-506). That path emits nothing until the whole response is complete — the code's own comment says so: "in which case nothing was streamed and we emit the result ourselves". So any long response after a stream reset is guaranteed to trip the idle watchdog, no matter how healthy the model is. The turn is then killed at the moment its answer arrives, and all the work in it is discarded.The
tracing::warn!on that path goes to the daemon log only — it is not asink.emit, so it does not reset the watchdog and the operator sees nothing in the thread.2. The upstream stream is being reset mid-generation.
Connection reset by peer (os error 104)againsthttps://ollama.com/api/chaton a long-lived streaming request. Not a quota or provider-health problem: the ollama.com account was at 43.5% of its 5h window, and in the same period the opencode lane — same API key, same model — ran 623 events at a 2s cadence. The distinguishing factor is request duration: tecton's generations are long enough for something (provider, or an intermediary) to drop the connection; opencode's finish first.Ask
sink.emitaSystemmessage naming the transport error. That resets the idle timer, puts the cause in the thread, and turns a silent 15-minute death into a visible one-line degradation.src/agent/ollama.rs:519-521).keep_alive, and determine whether an intermediary or ollama.com itself is dropping long streams. If it is duration-bound, that is a hard ceiling on how long any single akh turn can generate.Notes
reasoning_effort = "high"was set on tecton the same day and is a large, separate win (first useful step 140s → 8s; avg gap 123s → 9s; 33 tool calls in the first 90s vs 1 thought). It does not address this defect — all three stalls above happened with it enabled.9da2ea8("Turns die quietly"), which addedlast_stepto the stall line andStopReason::Refusal. The daemon had been running an image built 2h before that commit.docker logsonly retains the current container's output. An earlier grep for these fallback warnings returned zero purely because the container had just been recreated.WIP: A reset upstream stream drops the turn into a silent non-streaming fallback, which the idle watchdog then kills at 900sto A reset upstream stream drops the turn into a silent non-streaming fallback, which the idle watchdog then kills at 900s