# agent 通用能力接入文档 ## 1. 文档目的 本文用于说明 `backend/agent` 目录下“通用能力”的职责边界、放置位置和接入约束,避免后续继续出现“同一类能力复制三份、四份”的情况。 这里的“通用能力”特指: 1. 会被两个及以上能力域复用,或者已经明确会继续扩散的基础能力。 2. 与具体业务语义弱耦合,抽出来后不会把某个 skill 的 prompt、状态字段、业务规则污染到其它模块。 3. 抽出后能显著减少样板代码、降低迁移成本,或者统一链路行为。 本文不负责描述某个具体 skill 的业务流程。业务流程、状态机、prompt 细节,仍应放在对应能力域自己的文件中。 ## 2. 当前目录分层 ```text backend/agent/ entrance.go chat/ graph/ llm/ model/ node/ prompt/ router/ shared/ stream/ ``` ### 2.1 `entrance.go` 职责: 1. 作为 `agent` 模块对上层 service 的统一入口。 2. 负责装配路由器与各能力 handler。 3. 不负责具体 graph 逻辑、不负责直接调模型、不负责工具执行。 ### 2.2 `router/` 职责: 1. 负责一级分流,把请求映射到具体能力链路。 2. 维护统一的请求/响应结构和 action 定义。 3. 不承载具体 skill 的业务判断细节。 适合放入这里的能力: 1. 路由请求结构。 2. action 解析与分发。 3. 对上层稳定暴露的最小门面。 ### 2.3 `graph/` 职责: 1. 只负责组图、连线和节点编排。 2. 文件里应尽量只出现节点挂载、分支和边定义。 3. 不直接写复杂业务逻辑、不直接调 DAO、不直接拼 prompt。 ### 2.4 `node/` 职责: 1. 承接能力域的核心业务节点实现。 2. 按“节点逻辑文件 + 工具文件”的双文件格局组织复杂能力域。 3. 在确实存在多节点复用时,可下沉少量带业务语义的 node 内部公共 helper。 当前约定: 1. `schedule_plan.go` / `schedule_plan_tool.go` 为一组。 2. `schedule_refine.go` / `schedule_refine_tool.go` 为一组。 3. `quicknote.go` / `quicknote_tool.go`、`taskquery.go` / `taskquery_tool.go` 同理。 补充说明: 1. `node/tool_common.go` 是 node 层内部通用工具聚合点。 2. 这里只放“被两个及以上节点复用、但仍带一点节点上下文语义”的 helper。 3. 如果某个能力已经弱化到与业务无关,应继续下沉到 `shared/`,而不是长期堆在 `tool_common.go`。 ### 2.5 `llm/` 职责: 1. 统一封装模型调用、JSON 解析、推理参数和模型侧协议。 2. 让上层节点尽量只关心“要什么结果”,不重复实现 SDK 样板代码。 3. 不承载具体业务状态流转。 ### 2.6 `model/` 职责: 1. 统一放置 agent 内部状态结构、输入输出 DTO、默认预算等模型无关定义。 2. 不在这里写业务执行逻辑。 ### 2.7 `prompt/` 职责: 1. 维护系统提示词、结构化输出模板、路由提示词等文本资产。 2. 不在 prompt 文件中写节点控制流和工具编排。 ### 2.8 `stream/` 职责: 1. 统一承接 SSE chunk 包装、阶段推送、OpenAI/Ark 流式适配。 2. 保证上层 service 不需要重复拼装流协议。 ### 2.9 `shared/` 职责: 1. 放置跨能力域复用的纯工具能力,例如时间、重试、深拷贝等。 2. 要求业务语义尽量弱、依赖尽量少。 3. 一旦某类逻辑已经被第二处复用,必须优先评估是否放到这里。 ## 3. 什么该抽成通用能力 满足以下任一条件时,必须优先评估抽公共层: 1. 同类逻辑已经出现第二份实现。 2. 不同 skill 的实现只有参数不同,控制流基本一致。 3. 上层 service 已经开始出现重复胶水代码。 4. 继续复制会增加迁移、测试或回归排查成本。 常见应优先考虑抽取的方向: 1. 模型调用门面。 2. JSON 容错解析。 3. SSE 阶段推送与 chunk 包装。 4. 深拷贝与快照转换。 5. 缓存快照读写辅助逻辑。 ## 4. 什么不该抽成通用能力 以下内容默认不应抽到公共层: 1. 某个 skill 独有的 prompt 片段。 2. 只服务单一业务的状态字段映射。 3. 带强业务语义的 ReAct 决策规则。 4. 只在一个节点里短期使用、且没有第二处复用证据的 helper。 判断原则: 1. 若抽出来后名字仍然需要带明显业务词,通常说明它还不够通用。 2. 若抽出来会让其它模块被迫理解某个 skill 的内部规则,说明抽取层级过早。 ## 5. 新增能力时的落点规则 1. 纯工具、弱业务语义、跨域复用:优先放 `shared/`。 2. 只在路由阶段复用:放 `router/`。 3. 只与模型协议相关:放 `llm/`。 4. 只与流式输出相关:放 `stream/`。 5. 只在 node 层内被多个节点复用,且带少量业务上下文:放 `node/tool_common.go` 或同层 helper。 6. 仍然明显属于某个能力域:留在对应 `node/`、`prompt/`、`model/` 文件中,不要硬抽。 ## 6. 变更要求 后续若在 `backend/agent` 中新增、下沉、替换任何通用能力,必须同步完成以下动作: 1. 更新本文档,说明新能力放在哪一层、为什么放这里。 2. 说明是否替代了旧实现,旧实现是否已经删除。 3. 检查是否还残留第三份及以上重复实现。 4. 若本轮只是暂时无法抽公共层,必须在代码注释或文档里写明原因。 ## 7. 当前结构结论 截至当前版本,`backend/agent` 已是唯一正式实现目录,`backend/service/agentsvc` 也已与历史旧路径完全解耦。 后续重构优先级建议: 1. 继续收口 node 层内部重复的查询/校验/移动辅助逻辑。 2. 持续把 service 层里可复用的旁路读写逻辑下沉到更稳定的公共层。 3. 保持 graph 只做编排、node 只做业务、shared 只做弱语义公共能力,避免重新堆回大杂烩结构。