# Agent 规范 本文件是 FTB 系统中所有 AI Agent 的**唯一权威定义**。任何对 agent 的能力、职责、权限、协作方式的修改,必须先在本文件落地,再同步到 architecture / decisions / workflow / roadmap / glossary。 ## 何时更新本文件 1. **新增 agent**:新建一个独立 agent 2. **agent 职责变化**:输入/输出/调用条件变了 3. **agent 权限变化**:可读哪些数据、可写哪些数据变了 4. **多 agent 协作方式变化**:编排顺序、依赖关系、出错回退策略变了 不影响以上四类的 prompt 微调、模型版本切换、性能优化不需要更新本文件。 ## 全局原则 1. **AI 不直接动数据,先生草案,用户确认** - 所有写入实体(DevTask / TestCase)必须带 `aiDraft: true` 标记 - 用户编辑保存后,标记自动清除(在 `useDevTaskStore.updateTask` / `useTestCaseStore.updateTestCase` 里实现) 2. **每条产物强制带引用** - DevTask / TestCase 必须有 `references: Reference[]`,至少 1 条 - 引用类型:`requirement` / `prototype_note` / `external` - 不带引用的草案不允许写入 3. **AI 输出必须有"对账报告"** - 拆解任务前,先输出三段对账: - ✅ 完美对应(需求 ↔ 原型注释 ↔ 任务) - ⚠️ 仅需求未见原型 / 仅原型未见需求 - ❓ 注释含糊无法转化 - 对账报告先呈现给用户,用户审核后才执行写入 4. **历史版本不强制存储** - 系统不要求历史原型 URL 作为基准 - 拆偏问题靠"对账报告"暴露给用户,由人工补救 - 这条决定见 decisions.md #17 ## Agent 列表 ### Agent 1:Prototype Decompose Agent(原型拆解) **目的**:把"产品方案原型 + 关联需求"拆解成开发任务草案 + 测试用例草案。 **输入**: - 当前版本「产品方案」类型 + status=completed 的 VersionPlan,取其 `resultUrl` 作为**原型链接**(约定:产品方案的成果即原型) - 当前版本关联需求列表(已被加进 Version 的 Requirement[]) - 版本成员清单(带角色:前端/后端/UI/测试) **调用入口**:版本详情页 → 产品方案 Tab → 计划状态 = completed 后,按钮「AI 拆解任务和用例」 **触发条件**: - 当前版本至少有 1 条 type=product 的 VersionPlan 处于 `completed` 且 resultUrl 非空(提交了原型) - 当前版本至少关联 1 条需求 **输出**: - 对账报告(结构化文本,含"完美对应/单边/含糊"三段) - DevTask 草案数组(每条带 `aiDraft: true` + `references[]`) - TestCase 草案数组(每条带 `aiDraft: true` + `references[]`) **写入**: - 用户确认后,调用 `useDevTaskStore.createTask` 和 `useTestCaseStore.createTestCase` - 写入字段中 `aiDraft: true`、`aiDraftAt: ISO时间戳` **权限**: - 读:Version, Requirement, VersionPlan, Member - 写:DevTask(仅 aiDraft 草案)、TestCase(仅 aiDraft 草案) - 不得修改:Requirement、Version、VersionPlan、Member、Bug **失败回退**: - 原型 URL 不可达 → 报告"原型无法访问",不写入任何数据 - 没有已完成的产品方案计划 → 报告"请先完成产品方案并提交原型成果",不写入 - 关联需求为空 → 报告"无关联需求,无法对照",不写入 - 对账报告全是 ❓ → 报告"原型注释含糊度过高,建议人工拆解",不写入 **MVP 阶段限制**(V3.1): - 只生成 DevTask 和 TestCase 草案 - 不自动分配 assignee(assignee 留给用户从草案编辑时手填) - 不做"上一版基准 diff" ### Agent 2:Risk Watch Agent(风险预警)— 待规划 仅占位,正式规划见 roadmap.md V3.2。 ### Agent 3:Schedule Suggest Agent(排期建议)— 待规划 仅占位,正式规划见 roadmap.md V3.2。 ## 多 Agent 协作(V3.2 规划) 当前 V3.1 只有 Prototype Decompose Agent 单独运行。 未来 Risk Watch / Schedule Suggest 引入后,编排策略另行设计。 ## 实现位置 V3.1 起,所有 Agent **走 NestJS 后端**(不走 Next.js API Route),原因: - 与现有 `product` / `requirement` 模块架构一致 - 共享 Prisma 实例便于后续 AiLog 持久化 - 多 Agent 引入时统一在 `AiGateway` 管理 prompt / 降级 / 重试 代码位置: ``` apps/server/src/modules/ ├── ai/ │ ├── ai.module.ts │ ├── ai.controller.ts # POST /api/v1/ai/decompose │ ├── ai.service.ts # 抓原型 + 调 LLM + 解析 │ ├── ai-gateway.service.ts # Anthropic 客户端单例(懒加载,key 改了重建) │ ├── prompts/decompose.ts # System Prompt + Tool Schema │ └── dto/decompose.dto.ts # 入参校验 └── config/ ├── config.module.ts ├── ai-config.controller.ts # GET/PATCH /api/v1/config/ai, POST /test ├── ai-config.service.ts # 读写 data/ai-config.json └── dto/update-ai-config.dto.ts ``` 共享类型:`packages/shared/src/agent.ts`(前后端通用) ## 配置管理 **多提供商支持(V3.1.5 起)**:系统支持配置任意数量的 AI 提供商,每个独立的 baseURL / apiKey / model,运行时切换激活。 **支持的 API 格式**: - `anthropic` — Anthropic 官方 + 兼容 Anthropic Messages API 格式的中转站(如 ikuncode 的 anthropic 端点) - `openai` — OpenAI 官方 + 兼容 OpenAI Chat Completions 格式的中转站 **API Key 优先级**:当前激活提供商的 apiKey → 环境变量 `ANTHROPIC_API_KEY`(兜底,仅 anthropic 格式可用) **前端配置入口**:`/admin/ai-config`,仅超管(`role.permissions` 含 `'*'`)可见 **字段(每个 Provider)**: - `id`:用户自定义唯一 ID(如 `ikuncode`) - `name`:显示名 - `format`:`anthropic` / `openai` - `baseURL`:完整 API endpoint - `apiKey`:完整 Key 仅在服务端持有;前端只能拿到 mask 视图 - `model`:该提供商上使用的模型 ID - `remark`:可选备注 **全局字段**: - `activeProviderId`:当前激活哪个 provider - `updatedAt` / `updatedBy`:审计 **测试连接**:`POST /api/v1/config/ai/test` 带 `{ id }`,用 16 token 极简调用验证目标 provider 可用性 **激活**:`POST /api/v1/config/ai/activate` 带 `{ id }`,切换激活 provider;AiGateway 缓存自动失效,下次调用重新构建客户端 **安全约束**: - 配置文件路径在 .gitignore 里(`apps/server/data/`),不进入版本控制 - 前端 GET 接口永远不返回完整 Key - 修改 Key 只能从前端 PATCH 上传新值,不支持读出旧值 - 编辑提供商时若不传 apiKey,则保留原值 **数据迁移**:旧版(V3.1)的 `{ anthropicApiKey, model }` 单 key 结构,自动迁移为多 providers 结构(id 为 `anthropic-official`,自动激活)。 ## 数据契约 ### Reference 类型 ```ts interface Reference { type: 'requirement' | 'prototype_note' | 'external'; id: string; // REQ-008 / QY0007 / 自由文本 label: string; // 展示用 url?: string; // 可选跳转链接 } ``` ### AI 草案标记 ```ts // DevTask 和 TestCase 共有 aiDraft?: boolean; aiDraftAt?: string; // ISO 时间戳 references?: Reference[]; ``` ### Agent 输入预期 ```ts interface DecomposeInput { version: VersionWithContext; // 上下文(不含 prototypeUrl,原型从产品方案成果取) prototypeUrl: string; // 从产品方案 completed 计划的 resultUrl 派生 requirements: Requirement[]; // 当前版本所属项目下已采纳、可用于本次拆解的需求 members: VersionMember[]; // 该版本参与人员(带角色) } ``` 要求:`requirements` 不能从产品级全量需求池直接取,必须经过项目维度和已采纳状态过滤。 ### Agent 输出预期 ```ts interface DecomposeOutput { report: { matched: Array<{ reqId: string; noteIds: string[]; taskCount: number }>; reqOnly: string[]; // 需求 ID 列表 noteOnly: string[]; // 原型注释 ID 列表 ambiguous: Array<{ noteId: string; reason: string }>; }; devTaskDrafts: Array & { categoryCode: string; aiDraft: true; aiDraftAt: string; references: Reference[] }>; testCaseDrafts: Array & { categoryCode: string; aiDraft: true; aiDraftAt: string; references: Reference[] }>; } ``` 要求:AI 不输出数据库 `categoryId`,只输出稳定 `categoryCode`。前端确认写入时按 `TaskCategory.code` 映射成 `categoryId`;映射失败时使用对应分组的默认类型兜底。 ## 视觉规范 AI 草案在 DevTask / TestCase 列表中的视觉区分: - 整行加 `border-l-2 border-l-purple-400 bg-purple-50/30` - 标题旁紫色徽章「AI 草案」(`bg-purple-100 text-purple-600`) - 用户在详情抽屉里编辑保存任意字段后,徽章和左边线自动消失