5.4 KiB
reply-end-controls - Telegram V1 Design
Scope
This project is Telegram-only.
No Discord, Slack, or cross-channel abstraction is part of V1.
However, the internal architecture should still be plugin-oriented and reusable so that multiple agents can adopt the same reply-end-controls behavior later without rewriting the logic.
Product behavior
At the end of every assistant reply sent to Telegram, attach two inline buttons:
A. 繼續B. 就這樣吧,不需要額外處理
Button selection must be captured and stored in conversation/session state.
If the user types a new message instead of pressing a button, the typed message takes priority.
V1 rules
Rule 1
Every assistant reply gets reply-end buttons.
Rule 2
If the user taps 繼續:
- store
lastChoice=continue - allow follow-up behavior on later turns
Rule 3
If the user taps 就這樣吧,不需要額外處理:
- store
lastChoice=stop - suppress unnecessary continuation behavior on later turns
Rule 4
If the user sends a new typed message, that input overrides the button state.
Rule 5
After a button is clicked, the original message buttons should be updated so the selection is visually resolved and repeated clicks are reduced.
State model
Store this in Telegram conversation/session state:
{
"replyEndControls": {
"lastChoice": "continue | stop",
"lastChoiceAt": "ISO timestamp",
"sourceMessageId": "telegram message id",
"sourceCallbackId": "telegram callback query id",
"active": true
}
}
Telegram callback payloads
Suggested callback data format:
rec:continuerec:stop
If message-scoped state is needed later, extend to:
rec:continue:<messageId>rec:stop:<messageId>
Technical flow
Outbound reply flow
- Assistant reply text is produced.
- Telegram reply payload is decorated with inline keyboard.
- Message is sent to Telegram.
Callback flow
- User clicks button.
- Telegram sends callback query.
- Callback handler parses
continueorstop. - State is persisted.
- Original message buttons are updated to reflect the chosen option.
Next-turn behavior
- A later turn begins.
- Runtime checks
replyEndControls.lastChoice. - If
stop, do not proactively extend or continue the previous thread unless the user explicitly asks. - If
continue, normal continuation behavior is allowed.
Suggested implementation modules
1. Reply decorator
Responsibility:
- append Telegram inline keyboard to every assistant reply
2. Callback handler
Responsibility:
- receive Telegram callback queries
- parse reply-end action
- update state
3. State storage helper
Responsibility:
- persist and retrieve the latest reply-end selection for the current conversation/session
4. Behavior policy hook
Responsibility:
- inspect
lastChoice - suppress proactive continuation when
stopis active
Plugin-oriented design goal
Even though V1 is Telegram-only, implementation should be split so the feature can be reused by other agents.
Required separation
A. Channel-specific layer
Telegram-only code:
- inline keyboard rendering
- callback query parsing
- Telegram message edit/update behavior
B. Agent-neutral control core
Reusable logic:
- reply-end choice state model
- state persistence rules
- Continue/Stop behavior policy
- helpers for reading and updating
lastChoice
C. Agent integration adapter
Per-agent integration points:
- how a given agent/runtime appends controls to replies
- how a given agent/runtime consults the stored choice before later turns
This means V1 should not hard-code every behavior directly into Telegram handlers. Telegram should be the transport/integration layer, while the choice model and policy logic should stay reusable.
Multi-agent reuse target
The design should make it possible for future agents to reuse the same core with minimal custom work:
- Agent A: Telegram assistant using OpenClaw
- Agent B: another Telegram bot runtime
- Agent C: future Slack/Discord version, if ever needed later
The shared core should answer:
- what choice was made?
- when was it made?
- is the conversation currently in
continueorstopmode? - should the next assistant turn suppress proactive continuation?
Recommended code layout
Suggested V1 layout:
reply-end-controls/
├── README.md
├── telegram-v1-design.md
├── core/
│ ├── state-model.md
│ ├── policy.md
│ └── callback-contract.md
├── telegram/
│ ├── reply-decorator.md
│ ├── callback-handler.md
│ └── message-update.md
└── adapters/
└── openclaw.md
V1 does not need all of these files implemented yet, but the structure should guide the implementation so transport-specific code does not swallow the reusable core.
Acceptance criteria for V1
V1 is complete when all of the following are true:
- A normal Telegram assistant reply shows both buttons.
- Clicking
繼續is received and stored. - Clicking
就這樣吧,不需要額外處理is received and stored. - After click, the original message is updated to show the choice state.
- A new typed user message still works without pressing any button.
- A later turn can read the stored choice and alter continuation behavior.
Non-goals for V1
- multi-channel abstraction
- governance integration
- analytics dashboard
- complex branching controls beyond
continueandstop