Files
reply-end-controls/telegram-v1-design.md

216 lines
5.4 KiB
Markdown

# 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:
```json
{
"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:continue`
- `rec:stop`
If message-scoped state is needed later, extend to:
- `rec:continue:<messageId>`
- `rec:stop:<messageId>`
## Technical flow
### Outbound reply flow
1. Assistant reply text is produced.
2. Telegram reply payload is decorated with inline keyboard.
3. Message is sent to Telegram.
### Callback flow
1. User clicks button.
2. Telegram sends callback query.
3. Callback handler parses `continue` or `stop`.
4. State is persisted.
5. Original message buttons are updated to reflect the chosen option.
### Next-turn behavior
1. A later turn begins.
2. Runtime checks `replyEndControls.lastChoice`.
3. If `stop`, do not proactively extend or continue the previous thread unless the user explicitly asks.
4. 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 `stop` is 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 `continue` or `stop` mode?
- should the next assistant turn suppress proactive continuation?
## Recommended code layout
Suggested V1 layout:
```text
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:
1. A normal Telegram assistant reply shows both buttons.
2. Clicking `繼續` is received and stored.
3. Clicking `就這樣吧,不需要額外處理` is received and stored.
4. After click, the original message is updated to show the choice state.
5. A new typed user message still works without pressing any button.
6. 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 `continue` and `stop`