Skip to content

Implement Telegram message reactions for agent lifecycle feedback #435

@houko

Description

@houko

Summary

When a user sends a message via Telegram, there is no immediate visual feedback that the agent has received and is processing it. The only indicator is the typing action (sendChatAction), which is subtle and easily missed.

Proposed Behavior

Implement Telegram setMessageReaction API to provide emoji-based lifecycle feedback on the user's message, similar to how OpenClaw handles this:

Phase Emoji When
Queued Immediately on message receipt
Thinking 🤔 When LLM call starts
Tool Use ⚙️ When executing a tool
Done After successful response
Error On failure

Implementation Details

The infrastructure is already in place:

  • LifecycleReaction struct and AgentPhase enum exist in types.rs
  • send_reaction() trait method is defined on ChannelAdapter with a default no-op
  • ALLOWED_REACTION_EMOJI and default_phase_emoji() are ready to use

Changes needed:

1. crates/openfang-channels/src/telegram.rs

  • Add api_set_reaction() method calling Telegram Bot API setMessageReaction
  • Implement send_reaction() on the ChannelAdapter trait for TelegramAdapter

2. crates/openfang-channels/src/bridge.rs

  • In dispatch_message(), send ⏳ reaction immediately after receiving a message
  • Update to ✅ on success or ❌ on error

Example setMessageReaction API call:

POST /bot{token}/setMessageReaction
{
  "chat_id": 12345,
  "message_id": 42,
  "reaction": [{"type": "emoji", "emoji": ""}]
}

Why

  • Users currently have no way to know if the bot received their message until the full response arrives (which can take 10-30s)
  • This matches the UX pattern established by OpenClaw and other modern bot frameworks
  • The Telegram Bot API has supported setMessageReaction since API v7.0

Notes

  • Reactions should be best-effort (fire-and-forget, don't block on failure)
  • Only works in private chats and groups where the bot has appropriate permissions
  • Consider making this configurable via channel config (e.g. status_reactions = true)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions