Keyboards and triggers
Keyboards and triggers
Reply vs Inline, Text vs Callback
Keyboards and triggers
Reply vs Inline, Text vs Callback
Keyboards and Triggers
The most common mistake when building Telegram bots is confusing standard Reply Keyboards (at the bottom) with Inline Keyboards (attached to messages). This section clears that up once and for all.
Note
Core rule: - Reply Keyboards (replacing the user's mobile keyboard) just send plain text. To catch them, use a Text Trigger. - Callback Triggers are ONLY for Inline buttons (the ones attached directly under a message bot sends).
Quick rules
- 1) If the button is below the user input field, it is Reply.
- 2) If the button is attached under a bot message, it is Inline.
- 3) Reply button sends text as if user typed it manually.
- 4) Inline callback button does not post text to chat, it sends callback event.
- 5) For Reply, use
Text Triggeror branch withCondition/Routerby text. - 6) For Inline callback, use
Callback Triggerwith callback_data filter. - 7) If callback_data is empty or wrong, expected branch will not run.
- 8) For mixed Reply/Inline flows, keep branches explicit and verify event type in logs.
Debug checklist
- Check actual update type in logs:
messageorcallback_query. - Confirm button type in UI: reply button or inline button.
- Verify exact callback_data value and
Callback Triggerfilter. - Make sure changes are saved before
Testrun. - Check duplicate triggers with overlapping conditions.
- Check that trigger has outgoing edge to next node.
- If unclear, reduce flow to one button + one trigger, then scale back up.
- After each fix, repeat:
Save -> Test -> logs.
| Topic | Reply Keyboard | Inline Keyboard |
|---|---|---|
| Location | Under input (global Telegram keyboard) | Under a specific bot message |
| Press result | Regular user text message | callback_data / URL / web_app action |
| Trigger to handle it | Text Trigger (or Condition/Router by message.text) | Callback Trigger |
| Configured in | System -> Reply Keyboard or Reply Keyboard node | Message node (inline buttons) |
| Best use case | Persistent menus/navigation | Context actions inside a message step |
| Button lifetime | Usually persistent until hidden or replaced | Bound to a specific message |
| Runtime event shape | update.message.text = "..." | update.callback_query.data = "..." |
| Typical mistake | Trying to catch with Callback Trigger | Missing callback_data but expecting callback event |
| What to inspect in logs | Look for message event and text | Look for callback event and exact callback_data match |
Practical setup scenarios
1. Scenario 1: Persistent menu via Reply Keyboard
When to use: When you need always-visible menu buttons like Catalog, Help, Contacts.
- In
System -> Reply Keyboard, create base menu buttons. - Add
Text Triggernodes with patterns matching button text. - Connect each
Text Triggerto the required branch (Message,Router,Condition). - Run
Testand click buttons in real Telegram chat.
Expected result
Each reply button press runs the correct text-based branch.
Runtime signal
Logs show
update message followed by Trigger matched: text.Common mistakes
Using
Expecting callback_data from reply buttons.
Callback Trigger instead of Text Trigger.Expecting callback_data from reply buttons.
2. Scenario 2: Inline actions under a message
When to use: When action must belong to a specific message: Confirm, Cancel, Details.
- In
Message, add inline buttons and set callback_data for each. - Create
Callback Triggerwith matching callback_data (or one general callback trigger). - Connect trigger to branch that must run after click.
- Test repeated clicks and click order across different buttons.
Expected result
Each inline button consistently triggers its callback branch.
Runtime signal
Logs show
update callback and Trigger matched: callbackQuery.Common mistakes
Different buttons share the same callback_data unintentionally.
Button is URL type but callback behavior is expected.
Button is URL type but callback behavior is expected.
3. Scenario 3: Mixed flow (Reply + Inline)
When to use: When bot has both persistent menu and per-message inline actions.
- Handle Reply paths through
Text Trigger. - Handle Inline paths through
Callback Trigger. - Do not merge reply text and callback_data matching into one trigger filter.
- Use
Router/Conditionafter trigger, not instead of trigger separation.
Expected result
System keeps event handling stable even in complex mixed scenarios.
Runtime signal
Logs always show correct event type for each branch: message or callback.
Common mistakes
One branch accidentally catches both event types and becomes unstable.
No fallback branch for unexpected user text.
No fallback branch for unexpected user text.
4. Scenario 4: Safety fallback for unexpected input
When to use: When user can type arbitrary text and bot must stay controlled.
- Keep explicit
Text Triggernodes for main menu commands. - Add fallback
Text Triggerwithout strict pattern or fallback branch viaRouter. - Fallback message should return user to menu and show available options.
- If needed, switch or clear keyboard via
Reply Keyboardnode.
Expected result
Unexpected text no longer breaks flow; user returns to a valid path.
Runtime signal
Logs show fallback branch execution for unmatched text.
Common mistakes
Only exact triggers exist with no fallback branch.
Fallback sends text but does not restore a clear keyboard state.
Fallback sends text but does not restore a clear keyboard state.
Anti-patterns (what to avoid)
- Catching Reply Keyboard presses via
Callback Trigger. - Using same callback_data for unrelated actions.
- Running
Testwithout saving and expecting latest behavior. - Leaving buttons without explicit handling branch.
- Mixing
message.textandcallback_query.datalogic in one ambiguous branch. - Ignoring logs and trying to debug by guesswork only.
Documentation navigation
Move through pages step by step as a guided learning path.