Skip to content

Telegram group chat: model responses silently dropped when message tool not called #84327

Description

@billehunt

Summary

In Telegram group chats, when the model generates a text response but does not call the message tool, the response is silently discarded and the user sees nothing. This happens because sourceReplyDeliveryMode: "message_tool_only" (the default for group/channel chats) causes dispatch-from-config.ts to suppress all payloads that lack deliverDespiteSourceReplySuppression metadata.

The model intermittently skips calling the message tool — especially after long idle periods when the Anthropic prompt cache goes cold — even though the delivery hint ("Delivery: to send a message, use the message tool.") is present in every prompt.

Reproduction

  1. Configure a Telegram bot with default settings (queue mode: steer)
  2. Have an active group chat session with working message tool usage
  3. Wait 90+ minutes (long enough for the prompt cache to go cold)
  4. Send a message to the bot in the group chat
  5. The model generates a relevant response but may not call the message tool
  6. The response is silently dropped — no error, no delivery, no log indication

Evidence from trajectory data

Three consecutive broken turns in topic:2027 session, all with the same pattern:

Time (UTC) outputTokens toolMetas didSend assistantTexts messagingToolSentTexts
20:16 196 [] false "Plan A from the playbook. 150g chicken + 150g roasted veg..." []
20:17 96 [] false "Hey — did you see the lunch rec?..." []
20:19 56 [] false "Lunch: 150g chicken + 150g roasted veg..." []

Every working turn in the same session had toolMetas containing {"toolName":"message"}, didSend: true, and non-empty messagingToolSentTexts. A separate session (topic:1) broke at the same time with the same pattern.

Root cause

Two-part problem:

  1. Model behavior: claude-opus-4-7 intermittently generates direct text without calling the message tool, particularly after long idle gaps.

  2. Runtime suppression: In dispatch-from-config.ts (~line 1608):

    if (suppressDelivery && !shouldDeliverDespiteSourceReplySuppression(reply)) {
        continue; // payload silently skipped
    }

    When sourceReplyDeliveryMode is "message_tool_only", suppressDelivery is true. Only payloads marked with deliverDespiteSourceReplySuppression (set by markReplyPayloadForSourceSuppressionDelivery) survive. Plain assistant text payloads from buildEmbeddedRunPayloads never get this flag, so they are silently dropped.

Proposed fix

In agent-runner.ts, after the agent run completes: when sourceReplyDeliveryMode is "message_tool_only" and the model produced text payloads but no side-effect delivery occurred (no message tool, no block streaming), mark those payloads with deliverDespiteSourceReplySuppression so they bypass the dispatch suppression and the user still sees the response.

PR incoming.

Environment

  • OpenClaw v2026.5.12
  • Model: claude-opus-4-7 via Anthropic API
  • Channel: Telegram (group chat, queue mode: steer)
  • Block streaming enabled for Telegram

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions