Skip to content

[Bug]: MS Teams plugin drops all text blocks after the first in multi-block replies #29379

@Tranman324

Description

@Tranman324

Bug Description

When an agent produces multiple text blocks in a single turn (text → tool calls → text), only the first text block is delivered to the Teams user. All subsequent text blocks are silently dropped — no error, no retry, no log entry.

This means if the agent says "Let me check..." before running tools, the user sees that filler text but never receives the actual answer.

Steps to Reproduce

  1. Configure OpenClaw with MS Teams plugin (@openclaw/msteams v2026.2.23)
  2. Send a message to the bot that triggers tool use (e.g., a database lookup)
  3. The agent outputs:
    • Text block 1: "Good question, let me look that up..."
    • Tool call(s)
    • Text block 2: (the actual detailed answer)
  4. User only receives Text block 1 in Teams. Text block 2 never arrives.

Expected Behavior

All text blocks should be delivered to the user, either as separate messages or coalesced into a single message.

Actual Behavior

Only the first text block per turn is delivered. Subsequent blocks are silently dropped. No errors in gateway logs. The session log shows the full response was generated correctly.

Environment

  • OpenClaw: v2026.2.26
  • MS Teams plugin: @openclaw/msteams v2026.2.23
  • replyStyle: "top-level"
  • blockStreamingDefault: off (default)
  • Conversation type: personal (1:1 DM)
  • Single-tenant Azure Bot

Analysis

The deliver() callback in reply-dispatcher.ts is called once per text block. The first call succeeds via continueConversation() in messenger.ts. Subsequent calls appear to fail silently — possibly because the proactive messaging context (continueConversation with activityId: undefined) becomes invalid after the first send, or the webhook response cycle has already completed.

The sendMSTeamsMessages() function in messenger.ts handles multiple chunks within a single delivery correctly (iterating in a loop inside one continueConversation call). But multiple deliveries (separate deliver() invocations from the reply dispatcher) each create independent continueConversation calls, and only the first one succeeds.

Workaround

Instruct the agent to never output intermediate text between tool calls — run all tools silently, then respond once. This ensures only one deliver() call per turn.

Related

Possibly related to the block streaming delivery path. With blockStreamingDefault: on, the behavior may differ.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions