← Back to PRs

#13388: feat(session): Auto-prune consecutive NO_REPLY messages from context

by Masha-L open 2026-02-10 12:59 View on GitHub →
agents stale
Fixes #13387 ## Problem Accumulated `NO_REPLY` assistant messages in session transcripts cause the model to learn that "NO_REPLY is always correct" — a cascade of silence effect. This is particularly problematic after: - Extended periods of heartbeat-only activity - Tool failures or rate limits - Discussing NO_REPLY itself (#5191) The model sees its own history full of NO_REPLY responses and infers this is the expected behavior, leading to legitimate messages being suppressed. ## Solution Auto-prune consecutive `NO_REPLY` assistant messages from the context before sending to the model: ### New utility function ```typescript pruneConsecutiveNoReplies(messages, maxConsecutive = 1) ``` ### Example ``` Before: [user] [NO_REPLY] [user] [NO_REPLY] [NO_REPLY] [NO_REPLY] [user] After: [user] [NO_REPLY] [user] [NO_REPLY] [user] ``` Only consecutive NO_REPLY messages are pruned; isolated ones are kept as they represent legitimate "nothing to say" decisions. ### Configuration Added `agents.defaults.pruneConsecutiveNoReply`: - `true` / `undefined`: keep at most 1 consecutive NO_REPLY (default behavior) - `false`: disable pruning - `number`: keep at most N consecutive NO_REPLYs ## Implementation - New `src/agents/no-reply-pruning.ts` with `pruneConsecutiveNoReplies()` and `countNoReplies()` utilities - Integrated into `src/agents/pi-embedded-runner/run/attempt.ts` after `limitHistoryTurns()` - Added config type to `src/config/types.agent-defaults.ts` - Tests in `src/agents/no-reply-pruning.test.ts` ## Related - #5191 — NO_REPLY Cascade of Silence (describes the problem) - #13383 — Cron announce delivery fix (addresses one manifestation) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> Adds a message-history pruning step that collapses runs of consecutive `NO_REPLY` assistant messages before the session transcript is sent to the model. This is implemented via a new `pruneConsecutiveNoReplies()` utility (plus a `countNoReplies()` diagnostic helper), wired into `runEmbeddedAttempt()` after history validation/limiting, and exposed via a new `agents.defaults.pruneConsecutiveNoReply` config option (boolean/number). The change fits into the existing transcript sanitization pipeline (`sanitizeSessionHistory` → `validate*Turns` → `limitHistoryTurns`) by adding an additional pass to reduce repeated silent-reply artifacts that can bias the model toward continued silence. <h3>Confidence Score: 3/5</h3> - This PR is directionally correct but has a couple of behavioral edge cases that can prevent pruning from applying as intended. - Core integration point is sensible (post-validation/limiting), and tests cover basic pruning behavior. However, NO_REPLY detection is stricter than existing token detection elsewhere in the codebase, so consecutive silent replies may not be recognized/pruned in real transcripts, and negative numeric config values can silently disable pruning while producing a misleading trace stage. - src/agents/no-reply-pruning.ts, src/agents/pi-embedded-runner/run/attempt.ts <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> <!-- /greptile_comment -->

Most Similar PRs