Repository navigation
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复 / I searched existing issues and confirmed this isn't a duplicate.
- 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category
对话 / Agent 交互 · Agent chat
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
影响体验 · Major (work is possible but turns are unusable and must be cancelled)
复现频率 · Reproducibility
偶现 · Sometimes (~22 degenerate reasoning blocks / a few hundred reasoning blocks in one long session; 5 turns had to be manually cancelled)
问题描述 · Description
Model: GLM-5.3-Flash, served by the Start plan provider (providerId: account:zai-start-plan, providerKind: anthropic, transport SSE).
What happens: during agent turns, the assistant's reasoning (thinking) stream starts out fully coherent, then within the first few hundred words collapses into an endless, never-recovering repetition loop of the tokens the = the = the = the = ... (the model's telegraphic "X = Y" thinking style apparently degenerates into a low-entropy sampler loop). The loop runs for many minutes, never produces a final answer or a tool call, and the turn can only be stopped by the user pressing cancel. When cancelled, the turn ends with:
"error": { "name": "AiSdkModelAdapterError",
"data": { "message": "Model request was cancelled.",
"code": "model_request_cancelled",
"attribution": { "providerId": "account:zai-start-plan",
"modelId": "GLM-5.3-Flash", "errorPhase": "stream" } } }with 0 output tokens — the entire generation is wasted.
Quantitative evidence extracted from the local ZCode session DB (~/.zcode/cli/db/db.sqlite), session sess_5ca12dff-db19-4016-9582-6a5ae09d2ba1 (agent core v0.17.1):
| Metric | Value |
|---|---|
| Assistant turns in session | 394 |
| Turns manually cancelled because of the loop | 5 → ~34 min of wall time lost |
| Reasoning blocks containing a >60 % filler-word window | 22 (most near 100 %) |
| Worst case | one reasoning block of 324,894 chars (~117k words) streamed over 23.6 min; coherent for only the first ~800 words, the remaining ~99 % is the loop; ended with model_request_cancelled |
| Sibling repeat | a second block of 61,197 chars / 210 s, also collapsed, also cancelled |
Nothing after the collapse point ever self-recovers: I repeated the analysis over every degenerate block — recovery count = 0 / 22.
复现步骤 · Steps to reproduce
- Start a ZCode session with GLM-5.3-Flash (Start plan).
- Give it a task that requires long dense thinking with heavy notation (in my case reverse-engineering / disassembly analysis, where the thinking alternates hex addresses, register values and prose — a good ignition for the " = " style loop).
- Watch the thinking stream: coherent at first, then
the =/= =tokens start repeating. - The loop continues for minutes with no content change and no step-finish; the turn must be cancelled.
期望表现 · Expected behavior
The reasoning stream should not degenerate into an unrecoverable repetition loop. Ideally the server detects degenerate sampling (e.g. growing n-gram repetition score on the reasoning channel) and stops/retries or ends the turn with a retryable error, instead of looping indefinitely until the end user interrupts — even better, a loop guard on the client could detect token-sim > 0.95 sliding window and surface a "reasoning loop detected, retrying" state similar to the ordinary retry path.
实际表现 · Actual behavior
Stream spins in the = the = the = ... for many minutes, zero final tokens, user must cancel, turn wasted (see numbers above).
ZCode 版本 · ZCode version
v3.17.2 (desktop; agent core 0.17.1)
设备 / 系统 / 浏览器 · Device / OS / Browser
Linux x86-64 (Arch / Omarchy), ZCode desktop app with integrated agent
截图 / 录屏 / 日志 · Screenshots / Recordings / Logs
Minimal anonymized excerpts from the worst block (turn msg_mw2i61b5_…, streamed 2026-11-04 20:21–20:45 UTC; timings from the local session DB):
Coherent start (first ~800 words, truncated):
... the base = 0x1664ec4 = the string START minus 8 = "SignalLightEvent" at 0x1664ecc means the string starts there, but the dynstr base = where? My cands = the bases = A - name_off for the entries scanned in [0x1390000, 0x13b5000) — 27 entries shared the base 0x1664ec4. But then extracting names from start = 0x13b2c18 gave 0 nn imports — so either:
1. The block start = wrong (the name_off=0 walkback = landed somewhere wrong)
2. The base = wrong
Transition into the collapse (verbatim, right before the loop):
OK let me just find the dynstr extent: the strings = = the = = the = the = the FOCUS. The practical path: 1. Find the dynstr base: scan back from 0x1664ecc in 1-byte steps = the longest run of the printable/\0 = the = the = the = the = the dynstr = = the = = ... MUCH SIMPLER AND ROBUST: the dynsym entries = = the = the = the name_off = = the = = for the = = = the = the = = the = = the = the = = the = = the = = the = = the = = the = = the = = the = = the = = the = = the = = the = = the = = the = = the
Everything after that point for ~230,000 more characters:
the = the = the = = the = the = the = = the = the = the = = the = the = the = = the = the = the = ...
Related issue: #819 — same failure family (GLM 5.3 token collapse / repetition during streaming, different trigger token pattern and chat context), so this looks like a sampling/degeneration guard gap in GLM 5.3-family long-thinking generation rather than a ZCode UI bug.
Activity
github-actions commentedon Nov 4, 2026
👋 感谢你的反馈,我们已经收到。
status: 待评估,你可以随时补充信息。needs: 更多信息标签并 @ 你。👋 Thanks — we've received your issue.
status: 待评估(Triage); feel free to add context.needs: 更多信息and ping you.