#13501: fix: extend assistant text dedup across message boundaries
agents
stale
Cluster:
Voice Call and TTS Improvements
## Summary
- Remove the message-scope guard in `shouldSkipAssistantText` so dedup works across all messages within the same agent run
- When a model produces text + `tool_use` in one turn and repeats the identical text after the tool result, the duplicate was being delivered to the channel because dedup state was reset between messages
### Root cause
`shouldSkipAssistantText` had an early return:
```ts
if (state.lastAssistantTextMessageIndex !== state.assistantMessageIndex) {
return false;
}
```
This meant dedup only worked within a single assistant message. Between messages (after `resetAssistantMessageState`), the guard allowed the same text through again.
### Reproduction
1. Configure an agent that calls a tool after every text response (e.g., state tracking via `exec`)
2. The model produces: `text + tool_use` → tool executes → model repeats the same text
3. Both copies are delivered to the channel (e.g., Telegram receives the message twice)
### Fix
Remove the message-index guard so the trimmed/normalized text comparison works across all messages in the agent run.
## Test plan
- [x] Verified on live Telegram bot — duplicates no longer delivered after tool_use round-trips
- [ ] Existing `normalizeTextForComparison` and `isMessagingToolDuplicate` tests unaffected
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR changes assistant text deduplication in `src/agents/pi-embedded-subscribe.ts` by removing the message-index guard inside `shouldSkipAssistantText`, with the goal of suppressing identical assistant text that can be repeated after tool round-trips (text + tool_use, then repeated text after tool_result).
The intent is to deduplicate repeated assistant output across assistant messages within a single agent run, particularly for messaging-channel delivery (e.g. Telegram). The dedup logic works by tracking the last emitted assistant text (trimmed and normalized) and skipping new text that compares equal.
<h3>Confidence Score: 2/5</h3>
- This PR likely does not achieve the intended cross-message dedup behavior and leaves behind inconsistent state.
- Although the guard removal is straightforward, dedup state (`lastAssistantTextTrimmed/Normalized`) is still cleared on each assistant `message_start`, which would allow identical text in the next assistant message through—the exact scenario the PR description targets. Additionally, `lastAssistantTextMessageIndex` becomes dead state and there’s no automated test covering the tool round-trip duplication case.
- src/agents/pi-embedded-subscribe.ts; src/agents/pi-embedded-subscribe.handlers.messages.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#18077: fix: deduplicate TTS audio delivered via tool results
by stakeswky · 2026-02-16
78.4%
#9416: fix: drop errored/aborted assistant tool pairs in transcript repair
by xandorklein · 2026-02-05
76.4%
#17552: fix(agents): suppress tool error warnings when assistant already re...
by AytuncYildizli · 2026-02-15
75.3%
#19932: feat(agents): suppressPreToolText config + onBlockReply buffering
by Milofax · 2026-02-18
75.3%
#4700: fix: deduplicate tool_use IDs and enable sanitization for Anthropic
by marcelomar21 · 2026-01-30
75.3%
#4844: fix(agents): skip error/aborted assistant messages in transcript re...
by lailoo · 2026-01-30
74.3%
#16966: fix: strip tool_use blocks from aborted/errored assistant messages
by StressTestor · 2026-02-15
74.1%
#3880: fix: drop assistant messages with stopReason 'error' to avoid orpha...
by SalimBinYousuf1 · 2026-01-29
74.0%
#13282: fix(agents): instruct agent not to retry lost tool results
by thebtf · 2026-02-10
73.8%
#22087: Preserve assistant reply when exec fails under suppressToolErrors
by graysurf · 2026-02-20
73.8%