Context
Related to #45 (stream-json persistent session). If we stream Claude's output token-by-token via stream-json, we need a way to deliver partial responses to Telegram in real-time. Currently macroclaw sends one complete message per response.
Telegram Bot API 9.5 — sendMessageDraft
Telegram added sendMessageDraft in Bot API 9.3 (Dec 2025), opened to all bots in Bot API 9.5 (March 1, 2026). This is a purpose-built streaming method — it shows partial message content as an animated "draft" bubble while content is being generated.
API signature (from grammY)
```typescript
sendMessageDraft(
chat_id: number,
draft_id: number,
text: string,
other?: { parse_mode?, entities?, link_preview_options?, reply_parameters?, message_thread_id?, reply_markup? },
signal?: AbortSignal,
): Promise
```
How it works (expected flow)
- Call `sendMessageDraft(chat_id, draft_id, partial_text)` with incremental text as tokens arrive
- Telegram shows an animated draft bubble that updates in place
- When generation is complete, call `sendMessage` to finalize — the draft becomes a real message
grammY support
- grammY `^1.39.3` (our current version) has `sendMessageDraft` in its API types
- `@grammyjs/stream` plugin exists — provides `ctx.replyWithStream(asyncGenerator)` that handles chunking, auto-retry, and rate limiting
- Uses `@grammyjs/auto-retry` under the hood for rate limit handling
Comparison of approaches
| Approach |
Pros |
Cons |
| sendMessageDraft (new) |
Purpose-built for streaming, animated draft bubble, no message edit spam |
New API (March 2026), some reports of `TEXTDRAFT_PEER_INVALID` errors |
| sendMessage + editMessageText (current pattern) |
Well-understood, widely used |
Rate-limited (~1 edit/sec), edit flicker, multiple API calls |
| Just send final message (current macroclaw) |
Simplest, no complexity |
No real-time feedback, feels slow for long responses |
Known issues
- `TEXTDRAFT_PEER_INVALID` error reported by some bots using `sendMessageDraft` in private chats (OpenClaw issue #7803). May be resolved in newer Bot API versions or require specific bot settings.
- OpenClaw currently still uses the edit-loop approach with 1s throttle despite 9.5 being available — suggests the new API may not be fully stable yet.
Steps
References
Context
Related to #45 (stream-json persistent session). If we stream Claude's output token-by-token via stream-json, we need a way to deliver partial responses to Telegram in real-time. Currently macroclaw sends one complete message per response.
Telegram Bot API 9.5 — sendMessageDraft
Telegram added
sendMessageDraftin Bot API 9.3 (Dec 2025), opened to all bots in Bot API 9.5 (March 1, 2026). This is a purpose-built streaming method — it shows partial message content as an animated "draft" bubble while content is being generated.API signature (from grammY)
```typescript
sendMessageDraft(
chat_id: number,
draft_id: number,
text: string,
other?: { parse_mode?, entities?, link_preview_options?, reply_parameters?, message_thread_id?, reply_markup? },
signal?: AbortSignal,
): Promise
```
How it works (expected flow)
grammY support
Comparison of approaches
Known issues
Steps
References