# 微信 AI 助手 Go 后端与多智能体开发方案 > 本文基于 `docs/api-design.md` 的目标契约制定,供技术评审和实施拆分使用。 > > 当前 API 文档是目标契约,不代表接口已经实现;当前 `agent/` 目录是单次运行的 RPA demo,不应直接作为生产后端继续堆功能。 ## 1. 评审结论 推荐采用“模块化单体 Go sidecar + 本地原生自动化宿主 + 受控多智能体运行时”的架构: - Go sidecar 只监听 `127.0.0.1:8766`,承载 HTTP、WebSocket、SQLite、文件中心、模型网关、多智能体调度、知识库、蒸馏、员工和审计日志。 - Tauri/Rust 继续独占窗口选择、截图、坐标、标注、鼠标键盘和 Windows 原生生命周期。 - 多智能体首期运行在同一个 Go 进程内,不拆微服务,不引入 Redis、Kafka、Temporal 或 Kubernetes。 - SQLite 是唯一业务事实源;文件使用应用数据目录下的内容寻址存储;Windows Credential Manager 保存模型密钥。 - 智能体采用 Supervisor + 有限 DAG/状态机,不允许子 Agent 自由递归、自主扩权或直接执行桌面动作。 - LLM/VLM 是模型能力提供者;业务 Agent 才负责目标、状态、权限和流程。代码层应将两者分开,避免把一次模型调用误当成完整 Agent。 此方案适合当前“单机 Windows、单操作者、本地 sidecar”的产品边界。将来如果要多账号、多设备或云端协作,应另行设计,不在首期预埋分布式复杂度。 ## 2. 当前代码判断 当前 `agent/` 的实际状态: - `main.go` 是命令行单次运行入口,不是常驻 HTTP/WS 服务。 - `config.go` 直接读取 `config.toml`,并且默认路径仍包含 macOS `~/Library/Application Support`。 - `llm.go`/`planner.go` 直接调用单一兼容 OpenAI 的模型,缺少 provider 抽象、限流、重试分类、结构化输出校验和调用审计。 - `task.go` 只有 `click/type_text/press_enter/scroll/wait` 等简单动作白名单,任务和历史保存为 JSON 文件。 - `chat_sync.go` 直接读取标注文件和截图,再调用多模态模型提取聊天。这与当前 API 文档“标注调试数据不进入 Go 后端”的边界不能直接兼容。 - Go 模块当前只有 TOML 依赖,没有 HTTP、SQLite、WebSocket、迁移、后台任务或测试基础设施。 - 当前代码强制 `DryRun=true`,真实 Windows 自动化链路尚不能视为完成。 因此建议新建正式服务结构,逐步迁移可复用代码;不要直接把所有接口继续写进现有 `package main`。 ## 3. 编码前必须修正的契约缺口 `api-design.md` 可以覆盖当前页面,但要实现多智能体仍有以下缺口。建议先在 API 文档中确认,再冻结 OpenAPI。 ### 3.1 本地标注边界与引擎接口存在冲突 API 同时规定: - 标注调试状态、截图、区域和窗口信息不得进入 Go; - `/bootstrap` 和 `/engine/state` 又包含 `annotationComplete`; - `/engine/startup-checks` 包含 annotation check; - Go WebSocket 事件表包含 `engine.annotation.changed`。 推荐修正: 1. `annotationComplete` 由 Tauri 前端通过本地 IPC 合并展示,不由 Go 持久化。 2. `engine.annotation.changed` 改为 Tauri event,不进入 Go WebSocket。 3. Rust 在启动生产引擎前完成本地检查,仅向 Go 提交一次性 `nativeReadinessToken` 或布尔能力证明;Go 不接收标注内容。 4. Go 的启动检查只负责模型、配置、知识库、任务队列等业务检查;窗口和标注检查由 Rust 返回。 ### 3.2 单模型设置不足以支持 LLM/VLM 现有 `/settings` 只有一个 `model`。多模型至少需要: - `modelProfiles[]`:`id`、`kind=llm|vlm|embedding`、provider、endpoint、modelName、超时、并发、能力标签; - 每个 Agent 引用 `modelProfileId`,而不是读取全局唯一模型; - 密钥按 provider/profile 保存,但响应只返回 `keyConfigured`。 首期也可以只有一个 LLM profile 和一个 VLM profile,但数据结构不能把二者写死成同一个模型。 ### 3.3 Agent 对象缺少运行类型和工具策略 现有 `AgentSummary.type=builtin|custom` 只是来源类型。建议补充: - `agentKind`:`conversation | llm_worker | vlm_worker | wechat_action | chat_reader | employee_distill | knowledge_summary | knowledge_entity`; - `capabilities[]`:可被 Supervisor 路由的能力; - `modelProfileId`; - `toolPolicy`:允许工具、最大步骤、超时、是否必须人工确认; - `inputSchemaVersion`、`outputSchemaVersion`; - `runtimeVersion`:用于重放和问题定位。 `builtin|custom` 保留为 `sourceType` 更清晰。 ### 3.4 VLM 测试入口不足 当前 `agent_test_attachment` 不接受图片和视频。如果产品需要在智能体测试窗口验证 VLM,应补充图片格式;视频首期建议只接受明确抽取后的若干用户选择帧,避免隐式视频理解。 知识库图片/视频仍必须遵守现有规则:只使用人工描述,不允许 Knowledge Agent 或 VLM 自动生成描述。 ### 3.5 缺少 Agent Run 可观测接口 建议增加只读诊断接口: - `GET /agent-runs/{runId}`:运行状态、开始/结束时间、最终结果和错误; - `GET /agent-runs/{runId}/steps`:Agent 步骤、工具名、耗时、token、结果摘要; - `POST /agent-runs/{runId}/cancel`:取消仍在运行的测试或后台任务。 不得返回完整系统提示词、API Key、未脱敏聊天原文或模型内部推理文本。 ## 4. 总体架构 ```mermaid flowchart LR UI[React UI] -->|HTTP/WS 8766| API[Go API Server] UI -->|Tauri invoke/event| Native[Tauri/Rust Native Host] API --> APP[Application Services] APP --> AR[Multi-Agent Runtime] APP --> JOB[Durable Job Runner] APP --> DB[(SQLite + FTS5)] APP --> FS[Content-addressed File Store] APP --> EVT[Transactional Outbox + WS Hub] AR --> MG[Model Gateway] AR --> TOOL[Tool Registry] MG --> LLM[LLM Providers] MG --> VLM[VLM Providers] Native -->|Sanitized native bridge| BRIDGE[Local Agent Bridge] BRIDGE --> AR AR -->|Semantic action plan| BRIDGE Native --> WX[WeChat Window] ``` ### 4.1 进程职责 #### React/Tauri 前端 - 页面交互、loading/error、表单 dirty 状态和本地主题; - 通过 HTTP/WS 访问 Go 业务服务; - 通过 Tauri IPC 使用标注、窗口选择和本地生命周期能力; - 不把 mock/localStorage 当作业务事实源。 #### Tauri/Rust Native Host - 启停并监督 Go sidecar; - 生成 session token,并通过继承管道或受限文件句柄安全传递; - 独占标注文件、截图、窗口句柄、DPI、区域坐标和鼠标键盘执行; - 把生产运行期观察结果转换为不含坐标、截图路径和窗口句柄的语义对象; - 校验 Go 返回的动作计划,在必要时请求人工确认,再执行动作; - 保持标注调试链路完全不进入 Go。 #### Go Business/Agent Sidecar - 提供 `api/v1` HTTP 和 WebSocket; - 管理设置、文件、知识库、Agent、蒸馏、员工、日志和导出; - 运行模型网关和多智能体调度; - 保存结构化运行记录和业务状态; - 不直接调用 Windows 鼠标键盘 API,不读取标注文件。 ### 4.2 Native Agent Bridge 生产自动化不建议复用公开 HTTP。使用 Tauri 启动 Go 时建立的匿名管道或当前用户受限的 Windows named pipe,传输长度前缀 JSON 消息。 Rust 到 Go 的最小语义消息: ```json { "type": "conversation.observed", "observationId": "obs_01...", "conversationFingerprint": "sha256:...", "messages": [ { "messageFingerprint": "sha256:...", "role": "other", "content": "请问可以退款吗?", "occurredAt": null } ], "observedAt": "2026-07-21T09:35:01Z" } ``` Go 到 Rust 的语义动作计划: ```json { "type": "wechat.action.plan", "planId": "plan_01...", "conversationFingerprint": "sha256:...", "expectedObservationId": "obs_01...", "actions": [ { "type": "focus_input" }, { "type": "replace_text", "text": "可以,请提供订单号。" }, { "type": "request_send", "confirmationRequired": true } ], "expiresAt": "2026-07-21T09:35:11Z" } ``` 关键约束: - Go 只使用语义目标,不下发屏幕坐标;Rust 根据当前本地标注解析目标。 - 动作计划必须绑定 conversation fingerprint 和 observation ID,防止窗口切换后误发。 - 计划短时过期;执行前重新检查窗口、会话和输入框状态。 - `request_send` 与“是否自动发送”分离;最终策略由 Rust 和托管设置共同裁决。 - Bridge 不传输标注截图、标注坐标、窗口句柄或标注文件路径。 ## 5. Go 工程结构 推荐目录: ```text agent/ cmd/wechat-ai-sidecar/main.go internal/ bootstrap/ # 依赖装配、启动和优雅关闭 api/ httpapi/ # route、handler、middleware、DTO realtime/ # ticket、WS hub、订阅和续传 app/ # command/query application services domain/ engine/ files/ knowledge/ agents/ distill/ employees/ settings/ logs/ agentruntime/ supervisor/ registry/ runner/ tools/ policies/ trace/ agents/ conversation/ llmworker/ vlmworker/ wechataction/ chatreader/ employeedistill/ knowledgesummary/ knowledgeentity/ model/ gateway/ openaicompat/ volcengine/ nativebridge/ jobs/ persistence/ sqlite/ migrations/ filestore/ secrets/ parsing/ txt/ pdf/ docx/ pptx/ observability/ migrations/ testdata/ ``` 规则: - `domain` 不依赖 HTTP、SQLite 或具体模型 SDK。 - handler 只负责协议解析、鉴权和 DTO 映射,业务事务放在 `app`。 - repository 接口定义在使用方模块,SQLite 实现在 `persistence/sqlite`。 - Agent 只能通过 Tool Registry 使用受控能力,不能直接访问数据库或任意文件路径。 - 模型 provider 只实现模型调用,不承载业务 prompt。 ## 6. 建议技术选型 | 能力 | 建议 | 原因 | |---|---|---| | HTTP | Go `net/http` + `chi` | 中间件和路由清晰,不引入重框架 | | WebSocket | `coder/websocket` | API 简洁,支持 context 取消 | | SQLite | `database/sql` + `modernc.org/sqlite` | Windows 构建避免 CGO;实施前必须实测 FTS5 | | 迁移 | 内嵌 SQL migrations + migration table | 单机服务简单、可审计,避免运行时外部文件依赖 | | 日志 | `log/slog` JSON handler | 标准库、结构化、方便敏感字段过滤 | | ID | ULID | 可排序、适合 cursor 和本地日志 | | 配置 | 业务配置存 SQLite;启动参数仅包含端口和路径 | 避免 TOML/DB 两个事实源 | | Secret | `SecretStore` 接口 + Windows Credential Manager | API Key 不进 SQLite、日志和普通配置文件 | | 模型协议 | 自建窄接口 + OpenAI-compatible adapter | 避免业务层被特定 SDK 数据结构绑定 | | 后台任务 | SQLite durable jobs + 固定 worker pool | 单机足够,可恢复,无需外部队列 | | 文件 | 应用目录内容寻址存储 + SQLite metadata | 去重、原子完成、便于引用计数和清理 | 不建议首期引入通用 Agent 框架。多智能体的状态、权限、重放和审计是本项目核心,使用显式 Go 接口和状态机更可控。 ## 7. HTTP 接口实现方式 ### 7.1 通用请求链 每个请求依次经过: 1. loopback 来源检查; 2. Bearer session token 鉴权; 3. request ID 生成或透传; 4. body 大小和 Content-Type 限制; 5. JSON 严格解码,拒绝未知字段; 6. handler DTO 校验; 7. application command/query; 8. SQLite 事务和 revision 校验; 9. outbox 事件写入; 10. 标准成功或错误包络。 错误必须使用稳定 code,内部错误原因只写脱敏日志,不直接返回堆栈。 ### 7.2 幂等性 `idempotency_keys` 保存: - key、route、requestBodyHash; - responseStatus、responseBody; - resourceId、createdAt、expiresAt。 处理流程: - 在事务内锁定/插入 key; - 相同 key、相同 body 返回首次结果; - 相同 key、不同 body 返回 `409 IDEMPOTENCY_CONFLICT`; - 24 小时后后台清理。 长任务创建必须先落 job 和幂等记录,再返回 `202`,避免响应丢失后重复创建任务。 ### 7.3 Revision 所有可变聚合根包含整数 `revision`。更新 SQL 必须使用: ```sql UPDATE agents SET enabled = ?, revision = revision + 1, updated_at = ? WHERE id = ? AND revision = ?; ``` `RowsAffected=0` 后重新查询:不存在返回 404,存在则返回 `REVISION_CONFLICT`。 ### 7.4 Cursor cursor 使用 base64url 编码的服务端签名结构,例如: ```json { "sortValue": "2026-07-21T09:35:01Z", "id": "agent_01...", "sort": "updatedAt:desc" } ``` 客户端不得解析;查询使用稳定二元排序 `(updated_at, id)`,避免翻页重复或遗漏。 ## 8. SQLite 与文件存储 ### 8.1 核心表 建议按聚合建立: - 基础:`schema_migrations`、`settings`、`idempotency_keys`、`realtime_tickets`、`events_outbox`、`logs`; - 文件:`files`、`file_uploads`、`file_upload_parts`、`file_references`; - 知识库:`knowledge_bases`、`knowledge_drafts`、`knowledge_draft_files`、`knowledge_versions`、`knowledge_version_files`、`knowledge_chunks`、`knowledge_fts`; - Agent:`agents`、`agent_drafts`、`agent_releases`、`agent_knowledge_bindings`、`agent_test_sessions`、`agent_messages`、`agent_test_records`; - 运行时:`agent_runs`、`agent_steps`、`agent_tool_calls`、`agent_usage`; - 蒸馏:`distill_drafts`、`distill_draft_files`、`distill_jobs`、`distill_stages`、`distill_evaluations`; - 员工:`employees`、`employee_versions`、`employee_agent_bindings`、`employee_knowledge_bindings`、`employee_calls`; - 对话:`conversations`、`conversation_messages`、`conversation_memories`。 ### 8.2 SQLite 配置 启动时设置并校验: - `journal_mode=WAL`; - `foreign_keys=ON`; - 合理的 `busy_timeout`; - 单写连接或应用层串行写入; - 读连接池数量受控; - 每次迁移前创建可恢复备份。 不依赖 SQLite 自动清理文件引用。发布、删除和草稿清理都在显式事务内维护引用关系。 ### 8.3 文件中心 存储布局建议: ```text app-data/ files/sha256/ab/cd/ files/converted/.txt uploads//.part exports/. ``` 流程: 1. 上传写入临时文件,同时流式计算 SHA-256,不把完整文件读入内存; 2. 同时校验扩展名、MIME 和 magic bytes; 3. fsync 后原子 rename 到内容寻址路径; 4. 事务更新 FileAsset; 5. 文档投递 parser job;媒体直接进入 `parseStatus=not_required`; 6. 分片完成时逐片复核哈希和总长度,再合并并校验整体哈希; 7. Range 下载严格处理 `206/416`、Content-Range 和最大并发; 8. 清理任务删除过期 upload、无引用测试附件和孤立导出文件。 ### 8.4 文档解析 首期可行实现: - TXT:BOM 检测、UTF-8 校验、换行归一化; - PDF:使用支持文本层提取的库或隔离命令,只读取文本对象; - DOCX:按 ZIP/XML 规范读取段落和表格,不执行宏; - PPTX:按 ZIP/XML 读取文本框、表格和备注; - 旧 `.ppt`:Go 原生解析生态不足,建议通过受限的 LibreOffice headless 转换到 PPTX/TXT;若产品不接受外部依赖,应从首期支持列表移除 `.ppt`。 所有解析器必须有超时、文件大小限制、压缩炸弹限制和临时目录隔离。解析失败只影响该文件 job,不能拖垮 API 进程。 ## 9. WebSocket 与后台任务 ### 9.1 WebSocket - `POST /realtime-tickets` 在 SQLite 中创建 30 秒单次票据; - upgrade 时事务性消费票据,防止重放; - 每个连接维护允许频道集合,不允许订阅任意资源 ID; - 业务事务同时写聚合数据和 `events_outbox`; - publisher 从 outbox 发到内存 WS hub,并标记 dispatched; - 最近 10 分钟事件保留,用 `lastEventId` 续传; - 续传窗口外返回 `resumeAccepted=false`,客户端重新 GET。 模型 token delta 是高频临时事件,可直接流式发送并定期落消息快照;完成、失败和取消事件必须持久化。 ### 9.2 Durable Job Runner `jobs` 至少保存: - id、type、state、payloadRef; - attempt、maxAttempts、availableAt; - leaseOwner、leaseUntil; - progress、stage、cancelRequested; - lastErrorCode、createdAt、updatedAt。 worker 通过短租约 claim job。进程崩溃后租约过期可恢复。重试只针对网络暂时失败、模型 429/5xx 和可恢复文件错误;校验错误、权限错误和结构化输出长期不合法不可无限重试。 建议并发池: - 文件解析:2; - LLM:按 provider/profile 限制; - VLM:1,避免本机内存和上游限流; - 蒸馏:1 个 job,但 job 内可小批量并发; - 导出:1。 ## 10. 多智能体运行时 ### 10.1 核心原则 - Supervisor 唯一负责路由和结束条件;子 Agent 不得自由调用任意子 Agent。 - 每次运行都有 `runId`、输入 schema、权限快照、token/time/step budget 和取消 context。 - 所有 Agent 输出必须通过 JSON Schema 或显式 Go struct 校验。 - 工具调用必须经过 Tool Registry 和 Policy Engine;模型输出不能直接执行 SQL、HTTP、文件或桌面动作。 - 每一步都持久化状态和可审计摘要,但不保存模型隐藏推理链。 - 同一业务事件通过 dedupe key 保证不会重复执行。 - 自动发送属于高风险副作用,生成回复和执行发送必须是两个独立步骤。 ### 10.2 Go 接口示意 ```go type Agent interface { Descriptor() Descriptor Run(ctx context.Context, req RunRequest) (RunResult, error) } type Descriptor struct { Kind string Capabilities []string InputVersion string OutputVersion string } type RunRequest struct { RunID string ParentStepID string Input json.RawMessage Permissions PermissionSet Budget Budget Trace TraceContext } type Tool interface { Name() string Validate(input json.RawMessage, permissions PermissionSet) error Execute(ctx context.Context, input json.RawMessage) (json.RawMessage, error) } ``` 模型调用应为单独接口: ```go type ModelGateway interface { Generate(ctx context.Context, req GenerateRequest) (GenerateResponse, error) Stream(ctx context.Context, req GenerateRequest, sink DeltaSink) (GenerateResponse, error) } ``` ### 10.3 运行状态 `queued -> running -> waiting_confirmation | completed | failed | cancelled` 步骤状态: `pending -> running -> completed | skipped | failed | cancelled` Supervisor 在每一步检查: - run 是否取消; - deadline; - 剩余 token、模型调用数和工具调用数; - agent/tool 是否在权限快照内; - 输入是否仍绑定最新 conversation observation; - 是否需要人工确认。 ## 11. Agent 设计 ### 11.1 Conversation Supervisor Agent 职责:处理一条新聊天观察或测试消息,选择必要的子 Agent,生成最终候选回复。 典型 DAG: ```text ChatRecordReader -> Intent/LLM Worker -> Knowledge Entity Agent -> Employee Policy Agent -> Response LLM Worker -> Safety/Boundary Validator -> WeChat Action Orchestration Agent ``` 约束: - 无需 VLM 时不调用 VLM; - 无需知识时不强制检索; - 子 Agent 失败按类型降级,不能悄悄编造结果; - 关键知识必须带 `knowledgeId/version/chunkId` 引用; - 没有足够事实时输出澄清问题或转人工,不强行回答。 ### 11.2 LLM Model Agent 定位:受控文本模型 worker,不持有业务状态。 能力: - 意图分类; - 结构化信息抽取; - 回复生成; - 文本摘要; - 蒸馏阶段的策略归纳和反例生成。 实现: - 根据 `modelProfileId` 路由 provider; - 请求包含固定 system policy、Agent prompt、最小上下文和 JSON schema; - 支持 streaming 和 non-streaming; - provider 429/5xx 使用抖动退避,超时和取消立即终止; - 记录 model、latency、token usage、finish reason 和错误类别; - 对结构化输出只允许有限次 repair,仍失败则返回明确错误。 禁止: - 直接执行桌面动作; - 任意读取数据库和文件; - 自己扩展工具权限; - 将模型生成内容当作已验证事实。 ### 11.3 VLM Model Agent 定位:处理明确授权的图片输入和测试附件,输出结构化视觉结果。 适用: - 用户在对话或 Agent 测试中明确提交的图片; - 产品未来允许的显式视频帧分析; - 非标注调试的视觉能力实验。 不适用: - 知识库图片/视频自动描述; - 标注截图、窗口截图、区域坐标解析; - 未经授权的视频全量理解。 知识库 `purpose=knowledge_source` 且 `kind=image|video` 时,VLM Tool 必须拒绝调用;检索只使用标题、标签和人工 `description`。 输出示例应是结构化事实候选,并带 `confidence` 和 `uncertainFields`,由上层业务 Agent 决定是否可用,不能直接形成动作。 ### 11.4 WeChat Action Orchestration Agent 职责:把已批准的业务决策转换为短期语义动作计划,不直接控制鼠标键盘。 输入: - conversation fingerprint; - latest observation ID; - candidate reply; - 托管策略、quiet hours、联系人 allow/block 规则; - `confirmBeforeSend`; - 当前错误计数。 输出仅允许: - `focus_input`; - `replace_text`; - `request_send`; - `wait_and_reobserve`; - `abort`。 安全规则: - 默认不使用坐标动作; - 发送前必须再次比对会话 fingerprint; - 回复为空、内容超长、联系人 block、quiet hours、窗口变化或 observation 过期时中止; - `confirmBeforeSend=true` 时只填充输入框并等待确认; - 连续错误达到阈值后暂停自动发送并发出 `engine.state.changed`; - 每个 plan 只能执行一次,重复回执幂等。 ### 11.5 Chat Record Reader Agent 职责:管理聊天读取流程、消息归一化、跨页去重和增量游标;不直接读取标注文件。 分层: 1. Rust Native Collector 从当前微信窗口获得本地观察; 2. Rust 输出规范化 `conversation.observed`; 3. Go Chat Reader 校验 schema、conversation fingerprint 和顺序; 4. 根据 message fingerprint、相邻消息上下文和时间窗口去重; 5. 写入 `conversation_messages`; 6. 发布 `conversation.updated` 供 Supervisor 使用。 消息 ID 不能只由 `sender+content` 决定,否则重复发送相同文本会被误去重。建议组合:会话 fingerprint、方向、规范化内容、页面邻接 fingerprint、可见时间和首次观察序号。 如果评审要求 Go 内 VLM 直接读取微信截图,就必须先修改第 14 节的本地隐私边界;按当前契约不可实施。 ### 11.6 Employee Distillation Agent 职责:把已上传且解析完成的文本材料转成可版本化的员工能力包。 持久化状态机与 API stage 对齐: 1. `source_validation`:文件状态、数量、最小有效对话数; 2. `data_cleaning`:编码、空记录、重复、角色归一化; 3. `scene_clustering`:按业务场景聚类; 4. `strategy_extraction`:提取目标、触发条件、话术策略; 5. `boundary_induction`:提取禁止行为、优惠/承诺边界和转人工条件; 6. `counterexample_generation`:生成越界和歧义样本; 7. `evaluation`:固定评测集 + 新反例评测; 8. `completed`:生成不可变 EmployeeVersion 草稿。 蒸馏产物不能只有一段 prompt,应包含: ```json { "persona": {}, "scenePolicies": [], "decisionRules": [], "responsePatterns": [], "prohibitedBehaviors": [], "escalationRules": [], "positiveExamples": [], "counterExamples": [], "sourceRefs": [], "evaluation": {} } ``` 发布前要求: - 所有 sourceRef 可追溯; - overallScore 达到阈值; - overreachRate 满足阈值; - 评估使用的 job revision 等于当前 revision; - 发布事务同时生成 Employee、EmployeeVersion 和 bindings。 ### 11.7 Knowledge Summary Agent 职责:只对文本知识生成辅助摘要、标题建议、主题和章节概览,降低检索上下文长度。 边界: - 输入只来自解析后的 TXT 或操作者填写的媒体 description; - 不对知识图片或视频调用 VLM; - 摘要是派生数据,不能替换原文; - 每条摘要保存 source chunk refs、模型版本和生成时间; - 知识版本变化后旧摘要失效并异步重建; - 摘要失败不能阻止原始文档发布,但 UI 应显示派生状态。 ### 11.8 Knowledge Entity Agent(知识体 Agent) 本文将“知识体 Agent”定义为版本化知识组织与检索 Agent,不是第二个自由对话 Agent。 职责: - 将 KnowledgeVersion 组装成稳定的 Knowledge Entity; - 管理文本 chunk、人工媒体描述、标签、摘要和来源引用; - 根据 Agent/Employee 的知识授权过滤候选; - 使用 FTS5 BM25 召回并执行确定性重排; - 返回带证据的 KnowledgeContext; - 检查知识启停状态和绑定版本,禁止命中已停用知识; - 记录 retrieval trace,用于详情页 hit metrics。 建议返回: ```json { "query": "退款期限", "items": [ { "knowledgeId": "kb_refund", "version": "v1.8", "chunkId": "chunk_01...", "sourceFileId": "file_01...", "score": 0.87, "text": "……", "sourceKind": "document_text" } ] } ``` `sourceKind` 可为 `document_text | manual_media_description`,不能出现 `generated_media_description`。 ### 11.9 Employee Runtime Agent 员工不是简单的 Agent ID 集合。运行时应加载不可变 EmployeeVersion: - 根据场景选择已授权能力 Agent; - 注入画像、边界和 escalation rules; - 限制知识库为 employee bindings 与 agent bindings 的交集; - 汇总子 Agent 结果,生成候选回复; - 记录采用、人工修改、拒绝和异常,形成 calls/metrics; - 不在线自我修改 prompt,重新学习必须通过 redistill 和新版本发布。 ## 12. 关键业务流程 ### 12.1 Agent 测试流式回复 1. HTTP 创建 test session,固定 agent release 或 draft revision 快照; 2. 前端上传附件并等待解析 ready; 3. WS 发送 message command,服务端以 `clientMessageId` 幂等受理; 4. 事务写 user message、assistant placeholder 和 run; 5. 发送 accepted; 6. Supervisor 执行知识检索、模型调用和校验; 7. delta 按 sequence 推送; 8. 完整消息、usage 和 test result 原子落库; 9. 发送 completed/failed; 10. draft 修改后旧测试立即失效。 取消只取消当前 generation context,不删除已有 user message。 ### 12.2 知识发布 1. 创建/更新 draft; 2. 文件上传完成; 3. 文档解析为 TXT,媒体等待人工 description; 4. preview 汇总阻塞错误; 5. publish 事务固定 file IDs、内容哈希和 baseVersion; 6. 生成 KnowledgeVersion; 7. 文本切块并更新 FTS5; 8. 写 knowledge.changed outbox; 9. 异步运行 Knowledge Summary Agent; 10. 已绑定 Agent 若使用“跟随当前版本”,下次调用读取新版本;若绑定固定版本则不变。 ### 12.3 微信自动回复 1. Rust 确认当前窗口和本地标注有效; 2. Native Collector 产生新的语义 observation; 3. Chat Reader 去重并持久化; 4. Conversation Supervisor 读取最近消息、长期摘要和联系人策略; 5. Knowledge Entity Agent 检索授权知识; 6. Employee Runtime Agent 应用场景策略; 7. LLM 生成候选回复; 8. Policy Validator 检查敏感内容、越权、quiet hours 和发送权限; 9. WeChat Action Agent 生成短期计划; 10. Rust 重新检查会话,确认或自动执行; 11. Rust 返回逐动作结果; 12. Go 写 agent run、employee call 和结构化日志。 任一步不确定都应中止发送,而不是“尽力点击”。 ### 12.4 员工蒸馏 1. 创建 draft、绑定解析完成文件; 2. start 在事务内创建 job 和 stage rows; 3. worker 分批清洗和聚类,并在 checkpoint 后更新 progress; 4. 每阶段写结构化中间产物,不把全部上下文塞入单次 prompt; 5. 评估失败可重跑 evaluation,但不重复前面已完成阶段; 6. cancel 设置 `cancelRequested`,worker 在批次边界安全停止; 7. publish 固定 job revision 和评估结果,创建 EmployeeVersion。 ## 13. 模型网关 ### 13.1 Provider 抽象 统一能力: - `Generate`; - `Stream`; - `SupportsVision`; - `SupportsJSONSchema`; - `CountOrEstimateTokens`; - `HealthCheck`。 每个 profile 配置: - provider、endpoint、modelName; - context window 和 max output; - request timeout; - max concurrency; - 每分钟请求/token 限制; - 支持的输入类型和结构化输出方式。 ### 13.2 重试 可重试:连接重置、429、部分 5xx;不可重试:401、无效模型、输入超长、内容策略拒绝、schema 长期不合法。 生成回复不能无条件重试,因为第一次请求可能已在上游完成。使用 provider request ID 和本地 run step 幂等语义,最多有限次重试,并在日志中标明 attempt。 ### 13.3 Prompt 管理 - 固定安全 prompt 编译进版本化资源; - 用户 custom prompt 是独立字段; - Agent release 保存 prompt hash 和 runtime version; - prompt 组合顺序固定:系统安全规则 -> Agent 角色 -> Employee policy -> KnowledgeContext -> ConversationContext -> 当前输入; - 对外日志只保存 prompt hash、字符数和模板版本,不保存完整系统 prompt。 ## 14. 安全与权限 ### 14.1 权限模型 工具权限使用明确 code: - `knowledge.query`; - `conversation.read_current`; - `conversation.read_history`; - `attachment.read`; - `model.llm.invoke`; - `model.vlm.invoke`; - `message.compose`; - `message.request_send`; - `employee.policy.read`。 Agent release 固定权限快照。Supervisor 只能取交集,不能给子 Agent 增权。 ### 14.2 文件安全 - 用户文件名只作展示,不参与存储路径; - 拒绝路径穿越、NTFS alternate data stream 和非法设备名; - Office ZIP 限制展开文件数、总大小和压缩比; - 预览响应设置安全 Content-Type、Content-Disposition 和 `X-Content-Type-Options: nosniff`; - 不执行 Office 宏、嵌入对象或上传文件内脚本; - 视频只支持 Range 读取,不自动启动转码或识别。 ### 14.3 日志脱敏 记录:requestId、resourceId、agentKind、stage、latency、token、errorCode。 禁止:API Key、完整 prompt、完整聊天原文、附件正文、截图路径、绝对本机路径、窗口 title/handle。 模型上游错误体先通过 allowlist 提取 code/message,不能原样写日志。 ## 15. 可观测性与故障恢复 - 每个 HTTP 请求、WS command、job 和 agent run 共享 trace/request ID; - `/bootstrap` 返回 serverVersion 和 schema version; - 提供只监听 loopback 的 `/health/live` 和 `/health/ready`; - ready 检查 SQLite、迁移状态、文件目录和 job runner,不强制检查外部模型; - 每次模型调用记录 usage 和耗时; - outbox backlog、job queue depth、WS connection count 和连续错误数写结构化指标; - Go sidecar 崩溃后,running job 由 lease 恢复;running agent generation 标记 interrupted,由客户端重试,不自动重复发送消息; - Rust 发现 Go 不可用时暂停托管和所有发送动作。 ## 16. 测试策略 ### 16.1 单元测试 重点覆盖: - revision 冲突; - idempotency key 同体/异体; - cursor 稳定分页; - 文件类型三重校验; - Range 请求; - chat message 去重; - Agent 权限交集和 budget; - 微信动作计划过期、会话变更和重复执行; - 知识媒体禁止 VLM、只索引人工描述; - distill 状态机的取消和恢复。 ### 16.2 Repository 集成测试 每个测试使用独立临时 SQLite: - migrations 从空库可完成; - foreign key 和 cascade/restrict 符合预期; - 聚合更新与 outbox 在同一事务; - FTS5 查询、停用过滤和版本绑定; - job claim/lease/recovery; - 并发 revision 更新只有一个成功。 ### 16.3 API 契约测试 从 OpenAPI 生成或维护 request/response fixtures,覆盖: - 所有 `api-design.md` 页面入口; - 错误 code; - 未知字段和 body size; - ticket 单次消费; - WS 事件顺序和断线续传; - 文件上传、分片、完成、取消和清理。 ### 16.4 Agent 评测 Agent 不能只测“调用成功”。为每个 Agent 建固定 golden scenarios: - 意图和结构化抽取准确性; - 知识引用是否真实存在; - 无知识时是否拒绝编造; - 员工边界和转人工规则; - 自动发送是否在危险条件下阻断; - VLM 不确定输出是否正确标注; - 蒸馏重跑的一致性和 overreach rate。 模型评测记录 provider/model/prompt/runtime version,避免模型升级后结果不可解释。 ### 16.5 Windows 端到端测试 在真实 Tauri + Windows + 微信测试账号环境验证: - sidecar 启停和 token 传递; - 标注数据未进入 Go 日志、DB 和 Bridge; - observation/action fingerprint 防误会话; - confirmBeforeSend; - quiet hours、block list 和异常暂停; - 进程崩溃后不重复发送; - DPI、窗口移动和窗口切换时动作中止。 ## 17. 分阶段开发路线 ### 阶段 0:契约冻结 交付: - 修正 annotationComplete/WS 事件边界; - 增加 model profiles、agentKind/capabilities/toolPolicy; - 明确 VLM 可接受输入; - 补 Agent Run 诊断接口; - 生成并评审 OpenAPI 3.1; - 固定 Native Bridge 消息 schema。 验收:前端、Rust 和 Go 对每个字段的所有权无冲突。 ### 阶段 1:服务基础层 交付: - 新目录结构和依赖装配; - loopback HTTP、session token、request ID、错误包络; - SQLite migrations、revision、idempotency; - settings、SecretStore、bootstrap; - WS ticket、hub、outbox、续传; - health、结构化日志和优雅关闭。 验收:基础契约测试通过,重启后状态和事件可恢复。 ### 阶段 2:文件中心与知识库 交付: - 小文件、分片上传、Range 下载; - TXT/PDF/DOCX/PPTX 解析; - 媒体人工 description; - knowledge draft/version/publish/status/delete; - FTS5、引用关系和清理任务; - Knowledge Summary/Entity Agent。 验收:文档、图片、视频知识按契约工作;任何路径都不会自动生成媒体描述。 ### 阶段 3:模型网关与 Agent Runtime 交付: - LLM/VLM model profiles; - provider adapter、streaming、限流、取消和 usage; - Agent Registry、Supervisor、Tool Registry、Policy Engine; - run/step/tool trace; - budget、schema validation 和权限交集。 验收:用 fake model 可完全重放流程;真实 provider 的错误分类和取消正确。 ### 阶段 4:Agent 管理与测试会话 交付: - agent draft、release、knowledge binding、status/delete; - test session/messages; - WS accepted/delta/completed/failed; - 发布前 revision-matched test gate; - Conversation、LLM、VLM Agent。 验收:关闭并重新打开测试窗口可恢复消息;重复 command 不重复生成。 ### 阶段 5:蒸馏与员工 交付: - distill draft/job/stages/checkpoint/cancel; - Employee Distillation Agent; - evaluation、report export、publish; - EmployeeVersion、bindings、calls、redistill、clone; - Employee Runtime Agent。 验收:长任务重启可恢复,取消有效,发布产物可追溯到来源和评估版本。 ### 阶段 6:微信生产运行链路 交付: - Native Bridge; - Chat Record Reader Agent; - WeChat Action Orchestration Agent; - engine state、startup/stop/pause; - semantic observation、action receipt 和异常暂停; - Tauri/Rust 人工确认和最终动作执行。 验收:窗口切换、会话变化、过期计划、重复回执和 sidecar 崩溃均不会误发消息。 ### 阶段 7:替换 demo 与发布加固 交付: - 前端移除 mock/localStorage 业务状态; - 删除已迁移的旧 `package main` demo 路径,不保留双实现; - Windows sidecar 打包、迁移备份和回滚; - 性能、资源和安全测试; - 完整端到端发布检查。 验收:`api-design.md` 页面映射中的所有按钮和状态都来自真实接口或明确的 Tauri IPC。 ## 18. 主要风险与决策 | 风险 | 影响 | 建议决策 | |---|---|---| | API 的 annotation 状态所有权冲突 | Go/Tauri 双事实源 | 阶段 0 先修契约,不带冲突开工 | | 旧 `.ppt` 解析 | Go 生态弱、攻击面大 | 依赖受限 LibreOffice,或首期移除 `.ppt` | | 微信截图不能进入 Go,但旧 demo 依赖截图 VLM | chat_sync 无法直接迁移 | Native Collector 输出语义消息;若要 Go 看截图,必须显式改隐私契约 | | 多 Agent 自由协作 | 循环、成本失控、难审计 | Supervisor + DAG + budget,不做自由自治群聊 | | 自动发送误会话 | 高风险用户事故 | fingerprint + observation binding + expiry + Rust 二次校验 | | SQLite 并发写 | busy/锁竞争 | 单写队列、短事务、WAL、worker 并发受控 | | 大视频上传 | 磁盘占满、恢复困难 | quota、分片 TTL、预留空间检查、无自动处理 | | 模型输出不稳定 | 流程失败或越权 | schema、有限 repair、policy validator、确定性工具层 | | 蒸馏任务成本和上下文过大 | 超时、结果不可重复 | 分阶段 checkpoint、小批次、产物版本化 | | API Key 泄露 | 严重安全问题 | Windows Credential Manager、日志 allowlist、禁止 argv/env/DB 明文 | ## 19. 评审时建议确认的决策 1. 是否接受 Tauri/Rust 是唯一桌面动作执行者,Go 只输出语义动作计划? 2. 是否接受 Go 不读取任何标注/窗口截图,Chat Reader 只接收 Native Collector 的结构化消息? 3. VLM 首期是否只用于用户授权的图片附件,而不用于知识库媒体和标注截图? 4. `.ppt` 是依赖 LibreOffice,还是从首期格式中移除? 5. 是否接受模块化单体和 SQLite durable jobs,而不是首期引入微服务和外部队列? 6. 自动发送首期是否强制 `confirmBeforeSend=true`,稳定后再开放联系人级别白名单? 7. “知识体 Agent”是否按本文定义为版本化知识组织/检索 Agent,而不是可以自行修改知识的自治 Agent? 8. 模型 profile 是否需要首期支持多个 provider,还是先实现一个 provider、但保留多 profile 数据模型? 9. 员工蒸馏最低发布阈值、overreach 上限和人工复核规则由谁配置? 10. Agent run trace 在 UI 中展示到什么粒度,哪些字段只供本地诊断? ## 20. 最小可行落地范围 如果希望先验证架构而不是一次完成全部功能,最小闭环应包含: 1. HTTP/SQLite/WS 基础层; 2. settings + 模型密钥; 3. 文件上传和 TXT/PDF/DOCX/PPTX 文本解析; 4. 知识库发布 + FTS5 + Knowledge Entity Agent; 5. 单 LLM profile + Agent Runtime; 6. Agent draft/test/publish; 7. Native Bridge 的一条 observation -> candidate reply -> confirm -> send 闭环; 8. 全链路 run/step 日志和误发送防护。 VLM、员工蒸馏、复杂视频、自动发送可在该闭环稳定后加入。这个切分没有改变最终架构,也不会产生需要保留的临时双实现。