dashboard-nanobot/design/topic-mcp.md

272 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Topic 消息流方案(`topic_mcp`
## 1. 目标与边界
### 1.1 目标
- 将“对话消息”与“任务反馈消息”分离。
- 新增 RSS 风格 Topic 面板,支持按 Topic 订阅和无干扰查看。
- 由模型决定“是否写入 Topic、写入哪个 Topic”。
### 1.2 约束
- 尽量不修改 nanobot 引擎源码(`engines/nanobot-*`)。
- 若必须扩展能力,优先通过 Dashboard 内嵌 MCP Server 实现。
- MCP Server 固定命名:`topic_mcp`。
## 2. 术语统一(避免混淆)
- `transport_channel`:机器人对外通信渠道(`dashboard/telegram/feishu/qq/...`)。
- `topic`Dashboard 内的消息流分组(例如 `inbox`、`build`、`alerts`)。
- `topic_item`:某个 topic 下的一条消息。
## 3. 总体架构
```mermaid
flowchart LR
U["User"] --> UI["Dashboard UI"]
UI --> API["Dashboard Backend (FastAPI)"]
API --> DB["SQLite topic_* tables"]
API --> MCP["topic_mcp (streamableHttp)"]
BOT["nanobot"] -->|"MCP call"| MCP
MCP --> DB
BOT -->|"normal chat via dashboard transport_channel"| API
API --> UI
```
说明:
- 聊天消息仍走现有 dashboard 渠道。
- Topic 写入走 `topic_mcp` 工具调用,不侵入 nanobot 核心 loop/channel。
- Topic 路由与投递对所有 `transport_channel` 生效(`dashboard/feishu/telegram/qq/...`),即无论用户从哪个渠道发起请求,只要模型调用 `topic_*` 工具,都会统一写入 Topic 面板。
## 4. `topic_mcp` 配置策略(默认写入、不可删除)
### 4.1 写入位置
写入 bot 的 `.nanobot/config.json`
```json
{
"tools": {
"mcpServers": {
"topic_mcp": {
"type": "streamableHttp",
"url": "http://host.docker.internal:8000/api/mcp/topic",
"headers": {
"x-topic-mcp-token": "<bot-scoped-token>"
},
"toolTimeout": 30
}
}
}
}
```
### 4.2 不可删除规则
在 Dashboard 后端实现硬约束:
1. Bot 创建后自动注入 `topic_mcp`
2. `PUT /api/bots/{bot_id}/mcp-config` 全量更新时,若缺失 `topic_mcp`,后端自动补回。
3.`topic_mcp` 的关键字段做白名单校验(`type/url/headers/toolTimeout`)。
4. 返回给前端时标记 `locked=true`,前端禁用删除按钮(但以后端校验为准)。
## 5. `topic_mcp` 工具定义
建议工具集V1
1. `topic_list_topics`
- 作用:返回当前 bot 可投递的 topic 清单与路由说明。
- 用途:让模型先了解可投递目标,避免“靠名字猜”。
2. `topic_get_schema`
- 作用:返回允许的 `view` 结构定义(声明式渲染,不允许脚本)。
- 用途:让模型生成可渲染卡片,而非任意 HTML/JS。
3. `topic_route`
- 作用:输入候选内容,返回 `should_publish`、`topic_key`、`confidence`、`reason`。
- 用途:把“该不该发、发到哪”交给 Dashboard 规则层,降低模型随意性。
4. `topic_publish`
- 作用:写入一条 topic 消息。
- 关键字段:`topic_key/title/content/level/tags/view/dedupe_key`.
说明:
- 不建议 V1 暴露 `topic_create/topic_delete` 给模型。
- topic 由用户在 Dashboard 维护,模型仅消费已发布规则并投递。
- `sendProgress/sendToolHints` 产生的进度流和工具提示流不应投递到 Topic默认硬过滤
## 6. 数据模型Backend
### 6.1 `topic_bot_settings`
- `id` (PK)
- `bot_id` (unique, index)
- `topic_enabled`Topic 总开关,默认 `true`
- `created_at/updated_at`
### 6.2 `topic_topic`
- `id` (PK)
- `bot_id` (index)
- `topic_key` (unique with `bot_id`)
- `name`
- `description`
- `is_active`
- `is_default_fallback`
- `routing_json`(包含 include/exclude/examples/priority
- `view_schema_json`(允许的渲染模板)
- `created_at/updated_at`
### 6.3 `topic_item`
- `id` (PK)
- `bot_id` (index)
- `topic_key` (index)
- `title`
- `content`
- `level` (`info/warn/error/success`)
- `tags_json`
- `view_json`
- `source` (`mcp/manual/system`)
- `dedupe_key` (index)
- `is_read`
- `created_at`
约束:
- 同一 `bot_id + dedupe_key` 可设置幂等去重窗口(如 10 分钟)。
- 未命中 topic 时回退到默认 topic推荐 `inbox`)。
## 7. 后端 APIDashboard
面向 UI 的 REST示例
- `GET /api/bots/{bot_id}/topics`
- `POST /api/bots/{bot_id}/topics`
- `PUT /api/bots/{bot_id}/topics/{topic_key}`
- `DELETE /api/bots/{bot_id}/topics/{topic_key}`(禁止删除 fallback
- `GET /api/bots/{bot_id}/topic-settings`
- `PUT /api/bots/{bot_id}/topic-settings`(配置 `topic_enabled` 开关)
- `GET /api/bots/{bot_id}/topic-items?topic_key=...&cursor=...`
- `POST /api/bots/{bot_id}/topic-items/{id}/read`
面向 bot 的 MCP
- `POST /api/mcp/topic`streamableHttp
## 8. 路由策略(模型如何判断)
最终策略是“模型 + 规则引擎”:
1. 模型提取候选信息(摘要、类型、重要度)。
2. 调用 `topic_route` 获取决策建议。
3. `should_publish=true` 时调用 `topic_publish`
4. `should_publish=false` 不写 Topic仅保留聊天输出。
5.`topic_enabled=false` 时,`topic_route` 固定返回 `should_publish=false`
6. 当消息被判定为 progress/tool-hint对应 `sendProgress/sendToolHints` 流)时,固定 `should_publish=false`
topic 的路由配置建议包含:
- `purpose`topic 用途
- `include_when`:应收条件
- `exclude_when`:排除条件
- `examples`:正反例
- `priority`:冲突优先级
- `system_filters`:系统硬过滤(如 progress/tool-hint
金融信息 topic 路由示例(`topic_key=finance_market`
```json
{
"purpose": "沉淀与金融市场相关的关键结论和告警,便于用户集中查看。",
"include_when": [
"内容涉及股票/指数/外汇/利率/宏观数据/财报",
"包含明确数值、时间点、事件影响判断",
"属于'可执行建议'或'风险提示'"
],
"exclude_when": [
"纯寒暄或无结论聊天",
"与金融无关的任务进度",
"重复内容且dedupe_key命中窗口"
],
"examples": {
"positive": [
"美联储议息后10Y美债收益率上行20bp成长股承压",
"AAPL财报超预期但指引下调盘后转跌建议关注开盘波动"
],
"negative": [
"我已经开始处理你的请求",
"文件上传成功"
]
},
"priority": 80,
"fallback_topic_key": "inbox"
}
```
## 9. 前端 Topic Panel
UI 结构建议:
- 左列topic 列表(未读计数、筛选)
- 中列topic item 流(时间倒序、分页)
- 右列item 详情与结构化视图渲染
- 顶部:`Topic Enabled` 开关(开/关)
开关行为:
- `ON`:正常执行 `topic_route/topic_publish`
- `OFF`Topic 面板只读历史,不接收新投递;`topic_route` 返回 `should_publish=false`
- `topic_mcp` 配置仍保留且不可删除,避免反复改写 `config.json`
渲染要求:
- `view` 仅支持声明式类型:`markdown/card/table/checklist/metric/timeline`
- 禁止执行脚本与任意 HTML 注入
- 超长内容折叠 + 展开
## 10. 安全与治理
- `topic_mcp` 使用 bot 级 token 鉴权。
- 限流:每 bot 每分钟最大 publish 次数。
- 去重:`dedupe_key` + 时间窗口。
- 噪声过滤:`sendProgress/sendToolHints` 的进度与工具提示消息不进入 Topic。
- 降级:无 topic/路由失败时投递 `inbox` 或直接跳过(按策略)。
- 审计:记录每次 `topic_route/topic_publish` 调用。
## 11. 分阶段落地
### Phase 1最小可用
- 新增 `topic_bot_settings` / `topic_topic` / `topic_item`
- 新增 Topic Panel 基础查询展示
- 实现 `topic_mcp` + `topic_publish`
- 注入并锁定 `config.json.tools.mcpServers.topic_mcp`
### Phase 2稳定化
- 增加 `topic_list_topics/topic_get_schema/topic_route`
- 加去重、限流、fallback、审计日志
- 增加 topic 管理 UI规则编辑
### Phase 3体验增强
- item 模板优化与卡片渲染
- 未读/置顶/归档
- 统计与告警topic 热点、失败率)
## 12. 与现有代码对接点
- MCP 配置接口:`/api/bots/{bot_id}/mcp-config`
文件:[main.py](/Users/jiliu/WorkSpace/dashboard-nanobot/backend/main.py)
- 前端主面板:
[BotDashboardModule.tsx](/Users/jiliu/WorkSpace/dashboard-nanobot/frontend/src/modules/dashboard/BotDashboardModule.tsx)
- 实时同步:
[useBotsSync.ts](/Users/jiliu/WorkSpace/dashboard-nanobot/frontend/src/hooks/useBotsSync.ts)
原则:
- 不改 nanobot 核心引擎行为;
- 通过 Dashboard 承担 Topic 规则、投递和展示。