# 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": "" }, "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. 后端 API(Dashboard) 面向 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 规则、投递和展示。