iconsulting/docs/architecture/10-implementation-plan.md

922 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 10 - 实施计划详解 (Implementation Plan)
## 1. 总体时间线
```
Week 1 Week 2 Week 2-3 Week 3 Week 4 Week 5
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Phase 1 │ │ Phase 2 │ │ Phase 3 │ │ Phase 4 │ │ Phase 5+6│ │ Phase 7 │
│ │ │ │ │ │ │ │ │ │ │ │
│ 架构文档 │──→│ 基础设施 │──→│ 专家Agent│──→│ Coordinator│──→│ 集成+前端│──→│ 测试+优化│
│ + 类型 │ │ │ │ │ │ │ │ │ │ │
│ 定义 │ │ Queue │ │ 6个Agent │ │ 核心Loop │ │ Module │ │ 场景测试 │
│ │ │ Context │ │ 6份Prompt│ │ 主Prompt │ │ Gateway │ │ 性能优化 │
│ │ │ Base │ │ │ │ │ │ Frontend │ │ 旧代码清理│
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
```
## 2. Phase 1: 架构文档 + 类型定义 (Week 1)
### 2.1 架构文档12份
| 序号 | 文件 | 内容 | 状态 |
|------|------|------|------|
| 00 | `00-overview.md` | 总览 + 架构图 | ✅ 已完成 |
| 01 | `01-coordinator-agent.md` | Coordinator 设计 | ✅ 已完成 |
| 02 | `02-specialist-agents.md` | 6 个专家 Agent 设计 | 待完成 |
| 03 | `03-agent-communication.md` | Agent 间通信协议 | 待完成 |
| 04 | `04-streaming-protocol.md` | 流式传输协议 | 待完成 |
| 05 | `05-frontend-integration.md` | 前端集成方案 | 待完成 |
| 06 | `06-token-cost-management.md` | Token 与成本管理 | 待完成 |
| 07 | `07-testing-strategy.md` | 测试策略 | 待完成 |
| 08 | `08-context-injection.md` | 动态上下文注入 | ✅ 已完成 |
| 09 | `09-tool-execution.md` | 工具并发执行 | ✅ 已完成 |
| 10 | `10-implementation-plan.md` | 实施计划(本文档) | ✅ 已完成 |
| 11 | `11-prompt-templates.md` | 所有 Prompt 模板 | ✅ 已完成 |
### 2.2 类型定义文件
需要创建以下类型定义文件:
```
packages/services/conversation-service/src/infrastructure/agents/
├── types/
│ ├── agent.types.ts # Agent 相关类型
│ ├── stream.types.ts # 流式事件类型
│ └── context.types.ts # 上下文注入类型
```
**agent.types.ts**
```typescript
// 核心 Agent 类型定义
/** Agent 名称枚举 */
export enum AgentName {
COORDINATOR = 'coordinator',
POLICY_EXPERT = 'policy_expert',
ASSESSMENT_EXPERT = 'assessment_expert',
STRATEGIST = 'strategist',
OBJECTION_HANDLER = 'objection_handler',
CASE_ANALYST = 'case_analyst',
MEMORY_MANAGER = 'memory_manager',
}
/** Agent 使用的模型 */
export enum AgentModel {
SONNET = 'claude-sonnet-4-20250514',
HAIKU = 'claude-haiku-4-20250514',
}
/** Agent 配置 */
export interface AgentConfig {
name: AgentName;
model: AgentModel;
maxTokens: number;
maxTurns: number; // Agent mini-loop 最大轮次
timeoutMs: number; // 超时时间
tools: string[]; // 可用工具名列表
systemPromptFile: string; // Prompt 文件路径
}
/** Agent 执行上下文 */
export interface AgentExecutionContext {
userId: string;
conversationId: string;
coordinatorTurn: number; // Coordinator 当前轮次
parentToolUseId: string; // 触发此 Agent 的 tool_use ID
}
/** Agent Loop 参数 */
export interface AgentLoopParams {
messages: Anthropic.MessageParam[];
systemPrompt: string[] | Anthropic.TextBlockParam[];
tools: Anthropic.Tool[];
maxTurns: number;
maxBudgetUsd: number;
conversationId: string;
userId: string;
abortSignal?: AbortSignal;
}
/** 咨询状态(从 consulting_state XML tag 提取) */
export interface ConsultingStateReport {
currentStage: string;
collectedFields: string[];
nextAction: string;
confidenceLevel: 'low' | 'medium' | 'high';
recommendedPrograms?: string[];
}
```
**stream.types.ts**
```typescript
// 流式事件类型
/** 所有可能的 Stream 事件 */
export type StreamEvent =
| TextStreamEvent
| AgentStartEvent
| AgentProgressEvent
| AgentCompleteEvent
| ToolStartEvent
| ToolCompleteEvent
| ToolErrorEvent
| StateUpdateEvent
| UsageEvent
| ErrorEvent
| EndEvent;
export interface TextStreamEvent {
type: 'text';
content: string;
}
export interface AgentStartEvent {
type: 'agent_start';
agentName: string;
toolUseId: string;
}
export interface AgentProgressEvent {
type: 'agent_progress';
agentName: string;
turn: number;
maxTurns: number;
}
export interface AgentCompleteEvent {
type: 'agent_complete';
agentName: string;
durationMs: number;
tokensUsed?: { input: number; output: number };
}
export interface StateUpdateEvent {
type: 'state_update';
state: ConsultingStateReport;
}
export interface UsageEvent {
type: 'usage';
usage: { inputTokens: number; outputTokens: number };
totalCostUsd: number;
}
export interface ErrorEvent {
type: 'error';
code: string;
message: string;
}
export interface EndEvent {
type: 'end';
totalTokens: { input: number; output: number };
totalCostUsd: number;
turnsUsed: number;
agentsCalled: string[];
}
```
**context.types.ts**
- 详见 [08-context-injection.md](./08-context-injection.md) 第 3 节
**交付标准**
- 所有类型文件通过 `tsc --noEmit` 类型检查
- 每个 interface 有 JSDoc 注释
- 导出为 barrel file (`types/index.ts`)
## 3. Phase 2: 基础设施 (Week 2)
### 3.1 文件结构
```
packages/services/conversation-service/src/infrastructure/agents/
├── types/ # Phase 1 产物
│ ├── agent.types.ts
│ ├── stream.types.ts
│ ├── context.types.ts
│ └── index.ts
├── core/ # Phase 2 产物
│ ├── tool-execution-queue.ts # 工具并发执行队列
│ ├── context-injector.service.ts # 上下文注入器
│ ├── base-specialist.service.ts # 专家 Agent 基类
│ ├── agent-executor.ts # Agent 执行器工厂
│ └── token-tracker.ts # Token 追踪器
```
### 3.2 tool-execution-queue.ts
- 完整实现详见 [09-tool-execution.md](./09-tool-execution.md) 第 4 节
- **关键依赖**: `tool-execution.types.ts`
- **单测覆盖**:
- 纯并发批次(所有 safe 工具)
- 纯串行批次(所有 unsafe 工具)
- 混合批次safe + unsafe 交替)
- 单个工具超时
- 批次中一个工具失败
- 空请求
- 结果排序正确性
```typescript
// 单测示例
describe('ToolExecutionQueue', () => {
it('should execute concurrent-safe tools in parallel', async () => {
const queue = new ToolExecutionQueue();
const executionOrder: string[] = [];
queue.registerTool('tool_a', {
isConcurrencySafe: true,
executor: async () => {
executionOrder.push('a_start');
await sleep(100);
executionOrder.push('a_end');
return { content: 'a', success: true };
},
// ...
});
queue.registerTool('tool_b', {
isConcurrencySafe: true,
executor: async () => {
executionOrder.push('b_start');
await sleep(50);
executionOrder.push('b_end');
return { content: 'b', success: true };
},
// ...
});
const results = await queue.executeAll([
{ toolUseId: '1', toolName: 'tool_a', input: {}, originalIndex: 0 },
{ toolUseId: '2', toolName: 'tool_b', input: {}, originalIndex: 1 },
]);
// 两个工具应该几乎同时开始
expect(executionOrder[0]).toBe('a_start');
expect(executionOrder[1]).toBe('b_start');
// b 先完成50ms vs 100ms
expect(executionOrder[2]).toBe('b_end');
expect(executionOrder[3]).toBe('a_end');
// 结果按 originalIndex 排序
expect(results[0].toolName).toBe('tool_a');
expect(results[1].toolName).toBe('tool_b');
});
});
```
### 3.3 context-injector.service.ts
- 完整实现详见 [08-context-injection.md](./08-context-injection.md) 第 5 节
- **关键依赖**: `KnowledgeClientService`, `context.types.ts`
- **单测覆盖**:
- 所有 8 种上下文的独立构建
- 缓存命中/未命中
- Token 预算裁剪
- P0 上下文不被裁剪
- 缓存失效
- auto-compaction 触发条件
### 3.4 base-specialist.service.ts
- 完整实现详见 [09-tool-execution.md](./09-tool-execution.md) 第 6 节
- **关键依赖**: `@anthropic-ai/sdk`
- **单测覆盖**:
- Mini-loop 正常完成1轮无工具调用
- Mini-loop 有工具调用2轮
- 达到 maxTurns 强制终止
- API 错误处理
- Token 追踪回调
### 3.5 交付标准
- 所有基础设施组件可以独立运行单测
- 不依赖具体的 Specialist Agent 实现
- 使用 mock 的 Claude API 进行测试
## 4. Phase 3: 专家 Agent (Week 2-3)
### 4.1 文件结构
```
packages/services/conversation-service/src/infrastructure/agents/
├── specialists/
│ ├── policy-expert.service.ts # 政策专家
│ ├── assessment-expert.service.ts # 评估专家
│ ├── strategist.service.ts # 策略顾问
│ ├── objection-handler.service.ts # 异议处理
│ ├── case-analyst.service.ts # 案例分析
│ └── memory-manager.service.ts # 记忆管理
├── prompts/
│ ├── coordinator-system-prompt.ts # Phase 4
│ ├── policy-expert-prompt.ts
│ ├── assessment-expert-prompt.ts
│ ├── strategist-prompt.ts
│ ├── objection-handler-prompt.ts
│ ├── case-analyst-prompt.ts
│ └── memory-manager-prompt.ts
```
### 4.2 各 Agent 实现计划
| Agent | 继承 | Model | 工具 | 预估代码量 | 优先级 |
|-------|------|-------|------|-----------|--------|
| `PolicyExpertService` | `BaseSpecialistService` | Sonnet | `search_knowledge` | ~120 行 | P0 |
| `AssessmentExpertService` | `BaseSpecialistService` | Sonnet | `search_knowledge`, `get_user_context` | ~200 行 | P0 |
| `MemoryManagerService` | `BaseSpecialistService` | Haiku | `save_user_memory`, `get_user_context` | ~150 行 | P0 |
| `StrategistService` | `BaseSpecialistService` | Sonnet | `get_user_context` | ~100 行 | P1 |
| `ObjectionHandlerService` | `BaseSpecialistService` | Sonnet | `search_knowledge`, `get_user_context` | ~120 行 | P1 |
| `CaseAnalystService` | `BaseSpecialistService` | Haiku | `search_knowledge`, `get_user_context` | ~100 行 | P2 |
### 4.3 开发顺序
建议按以下顺序开发(优先级 + 依赖关系):
```
1. MemoryManagerService → 最简单,验证 BaseSpecialist + 工具执行
2. PolicyExpertService → 最常用,验证 knowledge-service 集成
3. AssessmentExpertService → 核心业务,需要 knowledge + 用户上下文
4. StrategistService → 辅助 Coordinator 决策
5. ObjectionHandlerService → 异议处理,依赖 knowledge
6. CaseAnalystService → 最后实现,依赖度最低
```
### 4.4 每个 Agent 的独立测试策略
```typescript
// 以 PolicyExpertService 为例的独立测试
describe('PolicyExpertService', () => {
let service: PolicyExpertService;
let mockAnthropicClient: jest.Mocked<Anthropic>;
let mockKnowledgeClient: jest.Mocked<KnowledgeClientService>;
beforeEach(() => {
mockAnthropicClient = createMockAnthropicClient();
mockKnowledgeClient = createMockKnowledgeClient();
service = new PolicyExpertService(mockAnthropicClient, mockKnowledgeClient);
});
it('should answer policy questions without tool calls', async () => {
// Mock: Claude 直接回答,不调用工具
mockAnthropicClient.messages.create.mockResolvedValue({
content: [{ type: 'text', text: '高才通B类要求...' }],
usage: { input_tokens: 500, output_tokens: 200 },
stop_reason: 'end_turn',
});
const result = await service.execute({
input: { query: '高才通B类条件是什么' },
maxTurns: 3,
});
expect(result.output).toContain('高才通');
expect(result.turnsUsed).toBe(1);
});
it('should use search_knowledge tool when needed', async () => {
// Mock: Claude 调用 search_knowledge再用结果生成回答
mockAnthropicClient.messages.create
.mockResolvedValueOnce({
content: [
{ type: 'tool_use', id: 't1', name: 'search_knowledge', input: { query: 'TTPS B类 条件' } },
],
usage: { input_tokens: 500, output_tokens: 100 },
stop_reason: 'tool_use',
})
.mockResolvedValueOnce({
content: [{ type: 'text', text: '根据查询结果高才通B类...' }],
usage: { input_tokens: 800, output_tokens: 300 },
stop_reason: 'end_turn',
});
mockKnowledgeClient.retrieveKnowledge.mockResolvedValue({
content: '高才通B类要求全球百强大学学士学位...',
sources: [{ articleId: '1', title: '高才通指南', similarity: 0.92 }],
});
const result = await service.execute({
input: { query: '高才通B类条件' },
maxTurns: 3,
onToolCall: jest.fn(),
});
expect(result.output).toContain('根据查询结果');
expect(result.turnsUsed).toBe(2);
expect(mockKnowledgeClient.retrieveKnowledge).toHaveBeenCalled();
});
});
```
### 4.5 交付标准
- 每个 Agent 有独立的单元测试mock Claude API + mock 外部服务)
- 每个 Agent 的 Prompt 是独立文件,可以独立调整
- 所有 Agent 通过 `BaseSpecialistService.execute()` 统一调用
## 5. Phase 4: Coordinator (Week 3)
### 5.1 文件结构
```
packages/services/conversation-service/src/infrastructure/agents/
├── coordinator/
│ ├── coordinator-agent.service.ts # 主服务
│ ├── agent-loop.ts # 核心递归循环
│ └── state-extractor.ts # 从回复中提取 consulting_state
├── prompts/
│ └── coordinator-system-prompt.ts # 500+ 行 Prompt
```
### 5.2 coordinator-system-prompt.ts
这是整个系统最重要的文件,详见 [11-prompt-templates.md](./11-prompt-templates.md)。
关键结构:
```typescript
export function buildCoordinatorSystemPrompt(config: {
expertContact: { wechat: string; phone: string; workingHours: string };
paidServices: { assessmentPrice: number; description: string };
currentDate: string;
}): string {
return `
# 身份定义
...(约 30 行)
# 你的专家团队
...(约 80 行)
# 六大移民类别
...(约 200 行)
# 对话策略
...(约 100 行)
# 回复规范
...(约 40 行)
# 状态报告格式
...(约 30 行)
# 业务规则
...(约 20 行)
`;
}
```
### 5.3 agent-loop.ts
核心递归循环,详见 [01-coordinator-agent.md](./01-coordinator-agent.md) 第 4 节。
关键特性:
- `async function* agentLoop()`: AsyncGenerator 模式
- 递归调用自身tool_results → 再次调用 Claude
- 集成 ContextInjector
- 集成 ToolExecutionQueue
- 集成 state extractor
- abort 信号支持
### 5.4 coordinator-agent.service.ts
NestJS 服务,封装 agent-loop对外暴露与旧 `ClaudeAgentServiceV2` 相同的接口:
```typescript
@Injectable()
export class CoordinatorAgentService {
constructor(
private contextInjector: ContextInjectorService,
private toolExecutionQueue: ToolExecutionQueue,
// ... 各 Specialist Agent
) {}
async *sendMessage(params: {
conversationContext: ConversationContext;
userMessage: string;
attachments?: FileAttachment[];
userId: string;
conversationId: string;
deviceInfo?: DeviceInfo;
}): AsyncGenerator<StreamEvent> {
// 委托给 agentLoop
yield* agentLoop({
messages: this.buildMessages(params),
systemPrompt: this.buildSystemPrompt(),
tools: this.toolExecutionQueue.getClaudeTools(),
maxTurns: 15,
maxBudgetUsd: 0.50,
conversationId: params.conversationId,
userId: params.userId,
});
}
}
```
### 5.5 交付标准
- Coordinator 可以独立运行集成测试(使用真实 Claude API
- agent-loop 有完整的单元测试mock API
- System Prompt 经过人工审查
- 通过 5 个核心对话场景的 E2E 测试
## 6. Phase 5: 集成 (Week 4 前半)
### 6.1 NestJS Module 集成
**新增 agents.module.ts**
```typescript
// packages/services/conversation-service/src/infrastructure/agents/agents.module.ts
@Module({
imports: [KnowledgeModule], // 依赖 KnowledgeClientService
providers: [
// Core
ToolExecutionQueue,
ContextInjectorService,
// Specialists
PolicyExpertService,
AssessmentExpertService,
StrategistService,
ObjectionHandlerService,
CaseAnalystService,
MemoryManagerService,
// Coordinator
CoordinatorAgentService,
],
exports: [CoordinatorAgentService],
})
export class AgentsModule {}
```
**修改 claude.module.ts**
```typescript
// 在 claude.module.ts 中导入 AgentsModule
@Module({
imports: [AgentsModule], // 新增
providers: [
ClaudeAgentServiceV2, // 保留旧服务(过渡期)
// ...
],
exports: [
ClaudeAgentServiceV2, // 保留旧导出
CoordinatorAgentService, // 新增导出
],
})
export class ClaudeModule {}
```
**修改 conversation.service.ts**
```typescript
// 切换注入(使用 feature flag
@Injectable()
export class ConversationService {
constructor(
@Inject(CONVERSATION_REPOSITORY)
private readonly conversationRepo: IConversationRepository,
@Inject(MESSAGE_REPOSITORY)
private readonly messageRepo: IMessageRepository,
// 旧服务(过渡期保留)
private readonly claudeAgentService: ClaudeAgentServiceV2,
// 新服务
private readonly coordinatorAgentService: CoordinatorAgentService,
private readonly configService: ConfigService,
) {}
private get useNewArchitecture(): boolean {
return this.configService.get<boolean>('USE_MULTI_AGENT', false);
}
async *sendMessage(params: SendMessageParams): AsyncGenerator<StreamChunk> {
if (this.useNewArchitecture) {
yield* this.sendMessageV3(params); // 新架构
} else {
yield* this.sendMessageV2(params); // 旧架构
}
}
}
```
**更新 conversation.gateway.ts**
```typescript
// 新增 Agent 相关的 WebSocket 事件
// stream_chunk 保持不变
// 新增:
// agent_start { agentName, conversationId }
// agent_progress { agentName, turn, maxTurns, conversationId }
// agent_complete { agentName, durationMs, conversationId }
```
### 6.2 Feature Flag 策略
```
环境变量: USE_MULTI_AGENT=true/false
开发环境: true (直接使用新架构)
测试环境: true (测试新架构)
生产环境: false (等全部测试通过后切换)
```
### 6.3 共享类型更新
```typescript
// packages/shared/types/src/conversation.ts
// 新增 StreamEvent 类型供前端使用
export interface AgentStatusEvent {
type: 'agent_start' | 'agent_progress' | 'agent_complete';
agentName: string;
conversationId: string;
// agent_progress only
turn?: number;
maxTurns?: number;
// agent_complete only
durationMs?: number;
}
```
### 6.4 交付标准
- Feature flag 可以在不重启服务的情况下切换
- 旧架构在 `USE_MULTI_AGENT=false` 时完全不受影响
- WebSocket 事件向后兼容(新事件是追加的,不修改已有事件)
## 7. Phase 6: 前端 (Week 4 后半)
### 7.1 前端文件修改
```
packages/clients/web-client/src/
├── stores/
│ └── chatStore.ts # 新增 agentStatus 状态
├── components/
│ ├── chat/
│ │ ├── ChatWindow.tsx # 处理新的 WebSocket 事件
│ │ ├── MessageBubble.tsx # 可能需要微调
│ │ └── AgentStatus.tsx # 新增Agent 工作状态组件
│ └── shared/
│ └── AgentBadge.tsx # 新增Agent 名称+状态徽章
```
### 7.2 chatStore 更新
```typescript
// chatStore.ts (Zustand)
interface AgentStatus {
name: string;
displayName: string; // 中文显示名
status: 'idle' | 'working' | 'completed';
startedAt?: number;
completedAt?: number;
durationMs?: number;
}
interface ChatState {
// 已有状态...
messages: Message[];
isStreaming: boolean;
// 新增Agent 状态
activeAgents: AgentStatus[];
agentHistory: AgentStatus[]; // 本次对话中所有 Agent 调用记录
}
// Agent 名称映射
const AGENT_DISPLAY_NAMES: Record<string, string> = {
policy_expert: '政策专家',
assessment_expert: '评估专家',
strategist: '策略顾问',
objection_handler: '异议处理',
case_analyst: '案例分析',
memory_manager: '记忆管理',
};
```
### 7.3 AgentStatus 组件
```tsx
// AgentStatus.tsx
// 显示在聊天窗口中,消息气泡和输入框之间
function AgentStatus({ agents }: { agents: AgentStatus[] }) {
const workingAgents = agents.filter(a => a.status === 'working');
if (workingAgents.length === 0) return null;
return (
<div className="agent-status-bar">
{workingAgents.map(agent => (
<div key={agent.name} className="agent-badge working">
<span className="agent-icon">🔄</span>
<span className="agent-name">{agent.displayName}</span>
<span className="agent-time">
{formatElapsedTime(Date.now() - (agent.startedAt || 0))}
</span>
</div>
))}
<span className="agent-hint">正在分析中...</span>
</div>
);
}
```
### 7.4 ChatWindow 事件处理
```typescript
// ChatWindow.tsx - WebSocket 事件处理更新
socket.on('agent_start', (data: { agentName: string; conversationId: string }) => {
chatStore.addActiveAgent({
name: data.agentName,
displayName: AGENT_DISPLAY_NAMES[data.agentName] || data.agentName,
status: 'working',
startedAt: Date.now(),
});
});
socket.on('agent_complete', (data: { agentName: string; durationMs: number }) => {
chatStore.completeAgent(data.agentName, data.durationMs);
});
socket.on('stream_end', () => {
chatStore.clearActiveAgents(); // 清除所有工作中的 Agent 状态
});
```
### 7.5 交付标准
- Agent 状态在 UI 中实时显示
- Agent 完成后自动消失(带淡出动画)
- 在弱网环境下不会出现 Agent 状态 "卡住" 的问题(超时自动清除)
- 旧架构模式下不显示 Agent 状态
## 8. Phase 7: 测试 + 优化 + 清理 (Week 5)
### 8.1 测试场景矩阵
| 场景编号 | 场景描述 | 涉及 Agent | 预期行为 |
|----------|---------|-----------|---------|
| S01 | 新用户首次咨询 | Coordinator + Memory | 破冰 → 收集信息 → 保存记忆 |
| S02 | 询问高才通条件 | Coordinator + Policy | 检索知识库 → 准确回答 |
| S03 | 信息收集后评估 | Coordinator + Assessment + Memory | 评估资格 → 推荐方案 |
| S04 | 用户表示犹豫 | Coordinator + Objection + Strategist | 识别异议 → 策略回应 |
| S05 | 用户要求付费评估 | Coordinator + (Payment tool) | 生成支付链接 |
| S06 | 老用户回访 | Coordinator + Memory | 加载历史记忆 → 个性化问候 |
| S07 | 并发工具调用 | Coordinator + Policy + Case | 并行执行两个 Agent |
| S08 | 超长对话 (30+ 轮) | All | Auto-compaction 触发 |
| S09 | API 错误恢复 | Coordinator | 降级到 Haiku / 友好错误 |
| S10 | 用户中途取消 | Coordinator | AbortSignal 生效 |
### 8.2 性能优化清单
| 优化项 | 目标 | 方法 |
|--------|------|------|
| 首次回复延迟 | < 3s | Prompt Caching + 预热 |
| 并发 Agent 延迟 | < 5s (3 Agent 并行) | ToolExecutionQueue 并行 |
| Context Injection 延迟 | < 200ms | 缓存 + 并行获取 |
| Auto-compaction 延迟 | < 2s | Haiku 摘要 |
| Token 成本 (每对话) | < $0.30 | Haiku for 辅助 Agent + Caching |
| 内存使用 | < 100MB per 1000 并发对话 | 对话结束清理缓存 |
### 8.3 旧代码清理计划
**阶段 A: 标记废弃 (Week 5)**
```typescript
// 不删除代码,只标记 @deprecated
/** @deprecated Use CoordinatorAgentService instead. Will be removed in v4. */
export class ClaudeAgentServiceV2 { ... }
/** @deprecated Replaced by Coordinator Prompt. */
export class StrategyEngineService { ... }
/** @deprecated Intent classification now handled by LLM. */
export const intentClassifier = { ... };
/** @deprecated Response quality now handled by Prompt. */
export const responseGate = { ... };
```
**阶段 B: 删除代码 (Week 6+, after 1 week in production)**
- 删除 `strategy-engine.service.ts`
- 删除 `intent-classifier.ts`
- 删除 `response-gate.ts`
- 删除 `default-strategy.ts`
- 删除 `claude-agent-v2.service.ts`
- 移除 feature flag
### 8.4 Rollback 计划
```
如果新架构在生产中出现严重问题:
1. 即时回滚 (< 1 分钟):
设置环境变量 USE_MULTI_AGENT=false
→ 自动切回 ClaudeAgentServiceV2
→ 不需要重新部署
2. 部署回滚 (< 5 分钟):
git revert 到 Phase 5 之前的 commit
→ 重新部署 conversation-service
3. 数据恢复:
新架构不修改数据库 schema
ConsultingState 格式向后兼容
→ 无需数据迁移
```
## 9. 组件依赖图
```
┌─────────────────┐
│ agents.module │
└────────┬────────┘
│ exports
┌────────────▼────────────┐
│ CoordinatorAgentService │
└────────────┬────────────┘
│ depends on
┌──────────────────┼──────────────────┐
│ │ │
┌────────▼───────┐ ┌────────▼────────┐ ┌───────▼────────┐
│ ContextInjector │ │ ToolExecution │ │ agentLoop() │
│ Service │ │ Queue │ │ (function) │
└────────┬───────┘ └────────┬────────┘ └───────┬────────┘
│ │ │
┌────────▼───────┐ ┌────────▼────────┐ │
│ Knowledge │ │ Agent Executors │ │
│ ClientService │ │ (factory) │ │
└────────────────┘ └────────┬────────┘ │
│ │
┌───────▼───────────────────┘
┌─────────▼─────────┐
│ BaseSpecialist │
│ Service (abstract) │
└─────────┬─────────┘
│ extends
┌───────┬───────┬───┴───┬───────┬───────┐
│ │ │ │ │ │
Policy Assess Strat Object Case Memory
Expert Expert gist Handler Analyst Manager
```
## 10. 风险与缓解
| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|---------|
| Coordinator Prompt 效果不佳 | | | Phase 4 投入大量时间测试 Prompt准备多个版本 A/B 测试 |
| Token 成本超预期 | | | 监控每次对话成本设置 maxBudgetUsd 硬上限 |
| 并发 Agent 导致 Rate Limit | | | 实现指数退避重试降级到 Haiku |
| Context Window 不够用 | | | Auto-compaction + 严格的 token 预算 |
| 前端 Agent 状态同步问题 | | | WebSocket 事件超时自动清理 |
| 旧代码删除导致回归 | | | Feature flag 过渡期完善的回滚计划 |
## 11. 交付 Checklist
### Phase 1 Checklist
- [ ] 12 份架构文档全部完成
- [ ] `agent.types.ts` 通过类型检查
- [ ] `stream.types.ts` 通过类型检查
- [ ] `context.types.ts` 通过类型检查
- [ ] 所有类型有 JSDoc 注释
### Phase 2 Checklist
- [ ] `ToolExecutionQueue` 通过所有单元测试
- [ ] `ContextInjectorService` 通过所有单元测试
- [ ] `BaseSpecialistService` 通过所有单元测试
- [ ] 所有组件可以独立测试不依赖 Claude API
### Phase 3 Checklist
- [ ] 6 Specialist Agent 全部实现
- [ ] 6 Prompt 文件全部编写
- [ ] 每个 Agent 有独立的单元测试
- [ ] 每个 Agent 使用真实 API 的集成测试可选按需运行
### Phase 4 Checklist
- [ ] Coordinator System Prompt 完成500+
- [ ] agent-loop 通过所有单元测试
- [ ] CoordinatorAgentService 通过集成测试
- [ ] 5 个核心场景 E2E 测试通过
### Phase 5 Checklist
- [ ] `agents.module.ts` 编写完成
- [ ] Feature flag 切换工作正常
- [ ] 旧架构在 flag=false 时不受影响
- [ ] WebSocket 事件向后兼容
### Phase 6 Checklist
- [ ] chatStore 更新完成
- [ ] AgentStatus 组件实现
- [ ] ChatWindow 处理新事件
- [ ] 前端无 regression
### Phase 7 Checklist
- [ ] 10 个测试场景全部通过
- [ ] 性能指标达标
- [ ] 旧代码标记 @deprecated
- [ ] 回滚计划验证通过
- [ ] 文档更新完成