Skip to content

[matrix-channel] Silent turns are labelled 「已完成」 ("Done") — a false completion signal in rooms #1320

Closed

Description

@LUOSENGWA

[matrix-channel] Silent turns are labelled 「已完成」 ("Done") — a false completion signal in rooms

Problem

When an agent turn ends with no visible final text, the Matrix channel edits the
per-turn placeholder (「处理中...」) to 「已完成」("Done") — unconditionally.

There are two very different situations behind "no visible text", and the current code
conflates them:

  1. Quiet completion — the turn did real work (tool calls) and simply had nothing to
    say. Marking it done is reasonable.
  2. Silent/empty turn — the model produced no tool calls and no meaningful output at
    all (observed failure mode: a long reasoning-only response that ends without any
    tool call or final text; e.g. generation truncated at the output budget). The turn
    did nothing, yet the room is told 「已完成」.

In a production incident, five such silent turns (each ending with tens of KB of
reasoning-only output, zero tool calls) terminated with the 「已完成」 marker. Room
observers and the coordination layer treated them as successful completions — the
silence was upgraded from "invisible" to "believed done", and the failures were only
caught by human intervention hours later.

Where (code chain)

plugins/agentteams-matrix-channel/agentteams_matrix/channel.py →
_on_process_completed() (current main, ~L4450–4510):

  • placeholder branch pops _MATRIX_PLACEHOLDER_THREAD_ROOT_KEY and edits the thread
    root with:
    • "已处理" when the final output is the NO_REPLY control line (good, L4472/L4490);
    • "已完成" whenever there is no visible text — three paths:
      • streaming text present but empty after control-text stripping (L4478);
      • pending final message present but empty after stripping (L4502);
      • no final text at all (L4506).
  • The discriminator that distinguishes "quiet completion" from "did nothing" does not
    exist anywhere in the path.

(Historical note: the completion marker was introduced with the QwenPaw 2.0 adaptation,
fb3a40be.)

Impact

  • False completion signal: room observers (team leader / humans / coordinating
    agents) see 「已完成」 and move on; a turn that produced nothing is recorded as done.
  • Silent automation: no retry, no escalation, no alert — the failure is masked by
    the success marker, and rooms can stay silent for hours.
  • Observability loss: the marker is the only per-turn outcome the room gets in
    the no-output case; it currently always says "done".

Proposal

Keep the marker, make it honest:

  1. Track per-turn activity in the channel's per-turn state (send_meta):
    • whether any tool call / tool output message was routed during the turn
      (the channel already observes these events — they drive tool-message rendering);
    • whether any visible text (final or streamed) was produced.
  2. In the placeholder-finalization branch, when the turn ends with
    zero tool calls && visible text ≤ ~10 chars (or empty) → post an explicit
    no-output marker (e.g. 「本回合无产出」) instead of 「已完成」.
    • NO_REPLY continues to map to 「已处理」 (unchanged);
    • turns with tool activity keep the current 「已完成」 behavior.
  3. (Optional, follow-up) emit a machine-readable signal alongside the marker so the
    dispatching party can be re-woken automatically — turning multi-hour silent stalls
    into seconds-visible events.

Tests

  • Unit: empty turn (no tool message + no text) → thread root edited to the no-output
    marker, not 「已完成」;
  • Unit: tool-only turn with no text → 「已完成」 (unchanged);
  • Unit: NO_REPLY → 「已处理」 (unchanged);
  • Regression: normal final-text edit unchanged.

空转回合被标「已完成」——房间里的假完成信号

问题:回合结束时若「可见最终文本」为空,Matrix 频道会把占位消息(「处理中...」)无条件改成**「已完成」。但"没有可见文本"背后是两种完全不同的情况:①安静完成**(真干了活、调了工具、只是没话说)——标"已完成"合理;②空转回合(模型零工具调用、无有意义输出——已观测形态:整回合只有超长思维流、无任何工具调用与最终文本,如生成撞输出预算被截断)——什么也没做,房间却收到「已完成」。在生产事故中,5 个此类空转回合均以「已完成」收口:房间观察者与协调层把它当成功完成,静默从"不可见"升级为"被误认为已完成",数小时后才被人工发现。

链条:plugins/agentteams-matrix-channel/agentteams_matrix/channel.py → _on_process_completed()(当前 main ~L4450–4510):占位分支编辑线程根——NO_REPLY → 「已处理」(正确,L4472/L4490);凡无可见文本 → 「已完成」(三条路径:L4478 / L4502 / L4506)。整条路径没有任何"做了事 vs 什么都没做"的判别。

影响:假完成信号 → 观察者(Leader/人类/协调 Agent)以为完成直接走开;无重试、无升级、无告警,房间可静默数小时;每回合唯一的产出标记永远说"完成"。

提案:把标记做诚实——① 在回合状态(send_meta)里记录:本回合是否路由过工具调用/工具输出消息(频道本就观察这些事件)、是否有过可见文本;② 占位收口分支:零工具 且 可见文本 ≤约 10 字(或为空) → 发明确的无产出标记(如「本回合无产出」)而非「已完成」;NO_REPLY 维持「已处理」;有工具活动的回合维持「已完成」。③(可选跟进)随标记发一个机器可读信号,供派发方自动重唤醒——把数小时静默压回秒级可见。

测试:空回合 → 无产出标记(非「已完成」);无文本的工具回合 → 「已完成」不变;NO_REPLY → 「已处理」不变;正常文本收口回归不变。

Activity

  1. added this to the 1.2.5 milestone on Oct 4, 2026
  2. shiyiyue1102 commented on Oct 16, 2026

    @shiyiyue1102
    Collaborator

    Released in v1.2.5. PR #1328 distinguishes an empty turn from tool-only completion and preserves NO_REPLY handling.

    The fix is included in the released tag; related regression evidence and required release checks have passed. Closing as delivered.


    已随 v1.2.5 正式发布。PR #1328 已区分空转回合与仅调用工具的完成回合,并保留 NO_REPLY 处理。

    已核对修复包含于发布标签,相关回归证据及必需发布检查均通过,现按已交付关闭。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions