Skip to content

Direct @-mentions classified as room_event: mention fact diverges between classifier and prompt context, agent lurks instead of replying #99854

Description

@obviyus

What happened

On a production Telegram group deployment (message_tool_only, always-on group activation, ambient/isolated polling ingress), the agent frequently composes a full answer to a direct @-mention but never calls message(action=send), so the user sees silence. Log signature per occurrence: [source-reply/private-final] agent produced a long private final reply without calling the configured delivery tool.

Root cause

The per-turn delivery directive branches on inboundEventKind (src/auto-reply/reply/prompt-prelude.ts, resolvePerTurnDeliveryDirective):

  • user_request + message_tool_only → strong hint (MESSAGE_TOOL_ONLY_DELIVERY_HINT, src/plugin-sdk/message-tool-delivery-hints.ts): deliver via message(action=send).
  • room_event + message_tool_only → lurk directive: "Default: no reply; most room events need no response… your final text here stays private either way."

Production transcripts show every inbound turn classified room_eventuser_request count is zero across sessions (256:0, 73:0), including turns whose prompt context simultaneously carried ExplicitlyMentionedBot: true for the same message. The model is told "you probably shouldn't respond visibly" on every turn, including direct mentions; a private final is it obeying.

The classification chain is individually correct:

  • src/channels/inbound-event/classification.ts (classifyChannelInboundEvent): wasMentioned === trueuser_request. Correct.
  • src/channels/mention-gating.ts (resolveMentionDecisionCore): effectiveWasMentioned = wasMentioned || implicitMention || bypass. Correct.
  • extensions/telegram/src/bot-message-context.session.ts:441 passes effectiveWasMentioned into the classifier. Correct.

So the defect is in the wiring for this deployment shape: the mention fact that reaches the classifier disagrees with the mention fact that reaches the prompt (ExplicitlyMentionedBot). Two independently computed "was the bot addressed" facts diverge across the ambient/isolated-ingress path. This violates the repo rule that hot paths carry prepared facts forward instead of rediscovering them.

Expected

  • One canonical "addressed" fact per inbound message, computed once, carried to classification, prompt context, and delivery directives alike. ExplicitlyMentionedBot: true and inboundEventKind: room_event must be impossible for the same message.
  • A direct @-mention (or reply-to-bot) in a group classifies as user_request, so the strong message_tool_only delivery hint fires and the agent reliably posts via message(action=send).

Fix shape

  1. Trace the ambient/isolated polling ingress path for group messages and find where inboundEventKind is stamped (or defaulted) without the mention-gating facts — that divergence is the bug. Unify: classification input and ExplicitlyMentionedBot must derive from the same mention decision.
  2. Prefer carrying the resolved mention/addressing fact forward on the inbound context over recomputing it per consumer; delete duplicate derivations.
  3. Consider strengthening the room_event lurk directive when the resolved fact says directly-addressed (belt-and-suspenders), but the primary fix is classification.
  4. Fail-confirmed regression test mirroring production: group message with explicit bot @-mention through the ambient/always-on ingress → inboundEventKind: user_request and the strong delivery hint present; unmentioned group chatter → room_event and lurk directive.

Environment

main @ d0b84a9, Telegram group, unmentionedInbound: room_event policy, message_tool_only delivery, claude-cli backend.

Activity

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

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingchannel: telegramChannel integration: telegramclawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.maintainerMaintainer-authored PR

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions