Files
ewoooc/docs/adr/ADR-019-telegram-bot-agentic-conversation-layer.md
OoO db02ecf2cf
All checks were successful
CD Pipeline / deploy (push) Successful in 2m55s
feat(telegram): ADR-019 Phase 1 - PPT data freshness gate + store_insight fix
ADR-019 Phase 1 (止血):PPT 生成前 probe 資料新鮮度。月初/缺資料期間用戶按
ppt:monthly/daily 不再產出空白報告,改主動 inline keyboard 詢問:
  - 改看最新有資料的月份/日期(一鍵)
  - 自訂月份/日期(接 await:date_ppt_*)
  - 取消

新增 PPTDataInsufficientError exception + _ppt_check_data_freshness() helper。
_generate_ppt_cmd 簽章加 _reply_to=None;_ppt_background 靜默吞此例外。

順手修同檔 :1976/:1993 兩處 store_insight() positional args 錯位 bug —
原本 (date, report_type, ai_text) 對應 signature (insight_type, content, period)
完全錯位,導致 period varchar(50) 被 2000 字 AI 內容截斷、INSERT 失敗、
ai_insights 表寫入永久失敗。改成 kwargs 呼叫。

ADR-019 (Telegram Bot Agentic Conversation Layer) 同步落地,Status: Accepted。
六 Phase 路線圖見 ADR 文件,本 commit 完成 Phase 1。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 12:52:45 +08:00

109 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-019: Telegram Bot Agentic Conversation Layer
- **Status**: Accepted
- **Date**: 2026-05-02
- **Deciders**: 統帥
- **Related**: ADR-001三 Agent 學習分工、ADR-012Agent Action Ladder、ADR-015Telegram Menu Restoration、ADR-018四 Agent Control Plane
## Context
ADR-018 已定義 Hermes / NemoTron / OpenClaw / ElephantAlpha 四 Agent control plane 的責任邊界。OpenClaw 是 L3 Strategist負責高品質策略、報告、長期洞察。
但實作上Telegram Bot 的互動層**完全繞過 OpenClaw 的決策能力**
1. **菜單按鈕走快車道**`cmd:X` callback ([routes/openclaw_bot_routes.py:4412](../../routes/openclaw_bot_routes.py#L4412)) 直接呼叫寫死 handler`_generate_ppt_cmd:2189`),不經 agent。
2. **NL chat 是 last-resort fallback**`openclaw_answer:4176` 已具備 Gemini Function Calling + NIM tool use 能力,但只在用戶輸入文字「沒匹配任何 keyword/state」時才被呼叫[telegram_bot_service.py:933](../../services/telegram_bot_service.py#L933))。
3. **Rigid default + 靜默空白**`_generate_ppt_cmd` 月報分支 [line 2293](../../routes/openclaw_bot_routes.py#L2293) 用 `now.year, now.month` 當預設,若 ETL 未進當月資料PPT 生成「本月業績為零」的虛文,無提示無詢問。
4. **無對話 state** — 每條訊息獨立,無 multi-turn confirmation、無 carry-over slot。
5. **EventRouter 覆蓋 1.8%** — 21 個 telegram 發送點各自為政(記憶 `feedback_agent_action_ladder.md``reference_telegram_endpoints_map.md`)。
**痛點觸發**2026-05-02 真實事件):用戶在月初 5/2 點 ppt:monthly → 系統預設查 5 月 → DB 最新資料只到 4/25 → AI 老實寫「業績為零」→ PPT 內容大量空白 → 用戶反映「老是異常你都無感嗎」。
## Decision
採用「**Agent-First Conversation Layer**」原則Telegram Bot 互動層的所有用戶輸入cmd / menu / NL都經過 OpenClaw agent 決策層菜單按鈕降級為「agent suggestion shortcuts」而非繞過 agent 的快車道。
### 五條互動原則
| # | 原則 | 含意 |
|---|------|------|
| 1 | **單一決策入口** | 所有 cmd:X / menu:X / NL message 統一進 `openclaw_decide(intent, args, ctx)`agent 自決下一步動作 |
| 2 | **資料缺口優先告知,不靜默** | Agent 在執行任何資料查詢前,先 probe `latest_date()` / `query_available_*()`;缺資料時主動 inline ask不出空白報告 |
| 3 | **NL 對話一等公民** | 用戶可用「我要看上個月月報」「最近一週的銷售」等 NL 觸發與按鈕等價agent 用 tool calling 解析 |
| 4 | **Multi-turn state** | 加 `services/openclaw_session.py` 管 chat_id 對話狀態,支援 carry-over slot如「剛問月份 → 用戶答 4 → 接續執行」)|
| 5 | **EventRouter 統一出口** | 所有 telegram 發送經 EventRouteragent 的 ask / answer / report 也走同管道,便於去重/降級/重送 |
### 邊界(不做什麼)
- 不取代 ADR-018 的 control plane 責任分工(仍是四 agent
- 不繞過 ADR-012 的 L0/L1/L2/L3 信任邊界(高風險 action 仍走 HITL
- 不重寫 telegram_templates.py31 個模板繼續用)
- 不改 webhook/polling 雙路徑架構ADR-008 已定)
- 不改 dedup guardcommit 1a886d9 已部署)
### 範圍
-`routes/openclaw_bot_routes.py` cmd dispatch 改造
-`services/telegram_bot_service.py` handle_message NL → agent 路徑
- ✅ 新增 `services/openclaw_session.py` 對話 state
- ✅ 新增 `services/openclaw_tools.py` agent tool registry
- ✅ EventRouter 21 個發送點遷移refactor-specialist 範圍)
- ❌ Hermes embedding worker 不動
- ❌ NemoTron / ElephantAlpha 內部邏輯不動
## Alternatives Considered
| 方案 | 不採用原因 |
|------|----------|
| A. 只補 freshness gateband-aid | 同類 bug 散在 daily/weekly/strategy/competitor/promo 多處,補不完,治標不治本 |
| B. 引入外部 agent framework (LangGraph/AutoGen) | 黑盒、難審計、跨 agent 通訊已有 EventRouter 能擴展,不增加依賴 |
| C. 直接 deprecate cmd:X 路徑只留 NL | 用戶習慣按鈕互動,移除會破壞 UX菜單可以保留為 agent suggestion |
| D. 把 OpenClaw 換成 ElephantAlpha 做對話入口 | ADR-018 已分工ElephantAlpha 是 orchestrator 不是對話 agentOpenClaw 才是 |
## Consequences
正面:
- PPT 空白等「rigid default」類 bug 一次性根除agent 主動 detect 缺口)
- NL 對話和按鈕互動統一,用戶體驗一致
- Multi-turn state 讓複雜場景(如「上個月 vs 過去 3 個月」對比)變可能
- EventRouter 覆蓋率 1.8% → 80%,系統可觀測性大幅提升
風險:
- Phase 3 影響 21 個 cmd 行為,需灰度 + feature flag + e2e regression
- Agent 多一層決策,每個 cmd 增加 200-500ms latencyNIM/Gemini call
- 對話 state 引入新故障面session race / memory leak
- 全部完成需 4-6 週工程,期間需保持向下相容
降級策略:
- Agent 失敗 → 回退原 cmd:X 寫死 handlerfeature flag off
- Tool call timeout → 用 cached response or template fallback
- Session lookup fail → 視為新對話,不阻斷主流程
## Implementation Plan
分 6 Phase 漸進交付,每 Phase 可獨立上線/回滾:
| Phase | 目標 | 工時 | 可獨立 ship |
|-------|------|------|-----------|
| 0 | 本 ADR + 計畫對齊 | 1h | ✅ |
| 1 | PPT 3 個 handler 補 freshness gate止血| 2h | ✅ |
| 2 | OpenClaw tool registryquery_*, ppt 等變 tool| 1d | ✅ |
| 3 | cmd:X dispatch 接入 agent.decide()feature flag 灰度)| 2d | ✅ |
| 4 | Multi-turn stateservices/openclaw_session.py| 1d | ✅ |
| 5 | EventRouter 21 發送點遷移refactor-specialist| 2-3d | ✅ |
| 6 | Proactive 09:00 資料新鮮度 probe + agent 主動通知 | 1d | ✅ |
每 Phase 後驗收:
- Phase 1: PPT 空白事件 = 0
- Phase 3: 21 cmd regression test pass + agent 接管率 100%
- Phase 5: EventRouter coverage 1.8% → 80%
## References
- ADR-001 三 Agent 學習分工
- ADR-012 Agent Action Ladder
- ADR-015 Telegram Menu Restoration
- ADR-018 四 Agent Control Plane
- 記憶:`feedback_agent_action_ladder.md``reference_telegram_endpoints_map.md``feedback_iterative_rollout.md`
- 觸發事件2026-05-02 用戶 PPT 月報空白回報