← Back to PRs

#23184: fix(auto-reply): prevent reminder guard note from leaking into channel messages

by lailoo open 2026-02-22 03:03 View on GitHub →
size: XS experienced-contributor
## Summary - **Bug**: Internal reminder guardrail note leaks into user-visible Telegram/channel messages - **Root cause**: `appendUnscheduledReminderNote()` in `agent-runner.ts` appends the note directly to `payload.text`, which flows to channel delivery - **Fix**: Move the note to a new `systemNote` field on `ReplyPayload` that channels don't render Fixes #23124 ## Problem When the agent makes a reminder commitment (e.g. "I'll remind you tomorrow morning") but doesn't actually schedule a cron job, the system appends an internal guardrail note: > Note: I did not schedule a reminder in this turn, so this will not trigger automatically. This note was appended directly to `payload.text` in `appendUnscheduledReminderNote()` at `agent-runner.ts:87-90`. Since all channel delivery code (Telegram, Slack, Discord, etc.) reads `payload.text` to send messages, the note was visible to end users. **Before fix:** Input: Agent says "I'll remind you tomorrow morning." (no cron.add) Output: "I'll remind you tomorrow morning.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically." ## Changes - `src/auto-reply/types.ts` — Add `systemNote?: string` field to `ReplyPayload` for internal annotations - `src/auto-reply/reply/agent-runner.ts` — Set `systemNote` instead of modifying `text` in `appendUnscheduledReminderNote()` - `src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts` — Update existing test + add regression test **After fix:** Input: Agent says "I'll remind you tomorrow morning." (no cron.add) Output text: "I'll remind you tomorrow morning." Output systemNote: "Note: I did not schedule a reminder in this turn, so this will not trigger automatically." ## Test plan - [x] Updated test: guard note now asserts `systemNote` field instead of `text` concatenation - [x] New test: "does not leak guard note into visible text" — explicitly verifies `text` does not contain the note - [x] All 21 existing tests in `agent-runner.misc.runreplyagent.test.ts` pass - [x] All 36 tests in `agent-runner.runreplyagent.test.ts` pass - [x] Format check passes (`pnpm format:check`) ## Effect on User Experience **Before:** Users see an internal system note ("Note: I did not schedule a reminder...") appended to the agent's message in Telegram and other channels. **After:** The agent's message is clean. The guardrail note is preserved internally in `systemNote` for diagnostics but never shown to users. <!-- greptile_comment --> <h3>Greptile Summary</h3> Clean, focused bugfix that moves the unscheduled-reminder guardrail note from `payload.text` (visible to users in all channels) to a new `systemNote` field on `ReplyPayload` that no channel adapter reads. - **`src/auto-reply/types.ts`**: Adds `systemNote?: string` to `ReplyPayload` with clear JSDoc annotation - **`src/auto-reply/reply/agent-runner.ts`**: `appendUnscheduledReminderNote()` now sets `systemNote` instead of concatenating to `text`, also removing the `trimEnd()` call that is no longer needed - **Tests**: Updated existing assertion to check `systemNote` instead of `text` concatenation, plus a new regression test explicitly verifying the note does not appear in `text` - **`CHANGELOG.md`**: Entry added under Fixes The fix is safe because all channel delivery paths (Telegram, Slack, Discord, Signal, WhatsApp, iMessage) only read `text`, `mediaUrl`/`mediaUrls`, and `channelData` from payloads — none read `systemNote`. The `normalizeReplyPayloadsForDelivery` function does carry `systemNote` through via spread, but downstream channel adapters destructure only the fields they need. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it's a minimal, well-tested fix that moves an internal note out of user-visible text. - The change is small and surgical (3 lines of logic changed). All channel delivery paths were verified to only read `text`/`mediaUrl`/`mediaUrls`/`channelData` — none read `systemNote`. Tests cover both the positive case (note goes into `systemNote`) and the negative regression case (note does not appear in `text`). No new risk is introduced. - No files require special attention. <sub>Last reviewed commit: 03d22d1</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs