Skip to content

fix(pulse/telegram): drop SDK session resume to prevent empty responses#1284

Open
catchingknives wants to merge 1 commit into
danielmiessler:mainfrom
catchingknives:fix/telegram-empty-response-drop-resume
Open

fix(pulse/telegram): drop SDK session resume to prevent empty responses#1284
catchingknives wants to merge 1 commit into
danielmiessler:mainfrom
catchingknives:fix/telegram-empty-response-drop-resume

Conversation

@catchingknives
Copy link
Copy Markdown

@catchingknives catchingknives commented May 18, 2026

Fixes #1143.

Problem

After a handful of messages on a long-lived Pulse process, the Telegram bot stops replying and ships the canned fallback "Sorry, I wasn't able to generate a response. Try again?". Affects any PAI user with the Telegram module enabled long enough to hit it. Most reliably reproduced (per #1143) by sending a short acknowledgment like "Agreed" or "OK" after a content-rich previous turn.

Root cause

startTelegram carries conversation state on two redundant channels:

  1. Last 10 exchanges spliced into the prompt as Previous conversation: … (lines 180–188).
  2. resume: lastSessionId passed to the SDK's query() (the removed block).

The SDK gets the same history twice. For long messages it muddles through; for short acknowledgments the resumed session short-circuits in 2–3 s with numTurns: 0, cost: 0, empty result — and fullText stays empty, triggering the fallback. #1143 has the same diagnosis and explicitly recommends "Option A — drop resume" as the predictable fix. This PR is that fix.

Evidence from a real session, all turns on the same sessionId:

Time (UTC) numTurns cost result
14:43 1 $0.42 OK
15:42 1 $0.31 OK
15:58 0 $0 empty
18:04 0 $0 empty
18:07 0 $0 empty

(Independent receipts in #1143 from a different user — same pattern, different session IDs.)

Fix

Drop the resume pass. The in-prompt history already carries conversational context (the last 10 exchanges — what users perceive as "memory"), so removing SDK-side resume is a no-op for user experience and removes the saturation failure mode. lastSessionId capture is kept for log correlation.

Compatibility

No config changes. Behavior identical from the user's perspective except that responses no longer go empty.

Relationship to #1281

#1281 (v2 — per-thread sessions, live tool reactions, empty-response recovery) addresses the same symptom but bundles it with a thread-aware rewrite (+575/-143). It keeps resume and wraps an empty response in a retry-with-fresh-session recovery layer. That works, but treats the symptom rather than the cause — and ships a much larger surface to review.

This PR is offered as a complementary minimal-diff path: 12 lines, addresses #1143's specific recommendation, doesn't preclude #1281's broader threading/observability work. If #1281 lands first, this PR's change is subsumed (the v2 runner no longer passes resume either, modulo its own design). If this PR lands first, #1281 rebases cleanly on top since the removed lines are not part of its retained code path.

After a handful of messages on a long-lived Pulse process, the Telegram
bot starts returning the canned fallback "Sorry, I wasn't able to
generate a response. Try again?". Affects any PAI user with the
Telegram module enabled long enough to hit it.

Root cause: startTelegram carries conversation state on two redundant
channels — the last 10 exchanges spliced into the prompt as
"Previous conversation: …" (lines 180-188) AND `resume: lastSessionId`
passed to the SDK's query() (the removed block). The SDK-side resume
saturates after a few turns; once tripped, query() short-circuits in
2-3 s with numTurns:0, cost:0, empty result — and fullText stays empty,
triggering the fallback.

Real-session evidence (all turns on the same sessionId):
  14:43  numTurns=1  cost=$0.42  OK
  15:42  numTurns=1  cost=$0.31  OK
  15:58  numTurns=0  cost=$0     empty
  18:04  numTurns=0  cost=$0     empty
  18:07  numTurns=0  cost=$0     empty

Fix: drop the `resume` pass. The in-prompt history already carries
conversational context (the last 10 exchanges — what users perceive as
"memory"), so removing SDK-side resume is a no-op for UX and removes
the saturation failure mode. `lastSessionId` capture is kept for log
correlation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PAI/PULSE/modules/telegram.ts: short messages produce empty replies (numTurns=0); literal {{DA_NAME}}/{{PRINCIPAL_NAME}} reach SDK and chat-log

1 participant