Multi-Agent Collaboration System
多智能体协作系统 —— 主智能体负责需求分析、任务分派与调度,子智能体负责按技能执行任务。
技术栈: TypeScript + Bun 运行时 + Express HTTP 框架 + Zod Schema 校验
目录
- 系统架构
- 主智能体 (MainAgent)
- 子智能体 (SubAgent)
- 任务调度 (TaskQueue)
- 意图路由 (IntentRouter)
- 统一规划器 (UnifiedPlanner)
- 工具体系
- 记忆与上下文系统
- 技能注册表 (SkillRegistry)
- LLM 客户端
- 通信协议与数据流
- 可观测性
- 保底机制 (Fallback)
- 扩展能力
- API 接口
- 会话管理
- 配置
- 测试
- 快速开始
- 架构优化记录
系统架构
整体架构图
用户请求
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ API 层 (Express + SSE) │
│ POST /tasks/stream → event: start/step/reasoning/complete/error│
└──────────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ MainAgent (规划与调度中枢) │
│ │
│ ① 图片分析 (VisionLLMClient) │
│ ② 上下文加载 (UserProfile + Memory + SessionContext) │
│ ③ 意图路由 (IntentRouter) ──→ small_talk / confirm / unclear │
│ ④ 任务规划 (UnifiedPlanner) ──→ 单任务直接 / 多任务 LLM 规划 │
│ ⑤ 任务调度 (TaskQueue) ──→ DAG 依赖 + 并发控制 │
│ ⑥ 结果汇总 + 持久化 │
└──────────────────────────┬──────────────────────────────────────┘
│ submitPlanTasks()
▼
┌─────────────────────────────────────────────────────────────────┐
│ TaskQueue (调度引擎) │
│ │
│ • DAG 依赖管理 (DFS 循环检测) │
│ • 并发控制 (MAX_CONCURRENT_SUBAGENTS = 5) │
│ • 任务状态机: pending → running → completed / failed │
│ • 超时处理 (AbortController, 默认 400s) │
│ • 失败传播 (强依赖级联 + 弱依赖跳过) 🆕 │
│ • 事件驱动 (EventEmitter, 替代轮询) 🆕 │
│ • 任务持久化 (防抖 + 原子写入) 🆕 │
│ • 自动清理 (每 5 分钟清理已完成/失败 > 1h 的任务) │
└──────────────────────────┬──────────────────────────────────────┘
│ executeTask(task)
▼
┌─────────────────────────────────────────────────────────────────┐
│ SubAgent (纯执行层) │
│ │
│ ① 加载技能定义 (SkillRegistry.loadFullSkill) │
│ ② 构建 System Prompt (技能说明 + 参数 + 保底规则) │
│ ③ 注册可用工具列表(按 allowedTools 过滤)🆕 │
│ ④ LLM 工具调用循环(并行安全工具并发执行)🆕 │
│ ⑤ 返回最终文本响应 │
└─────────────────────────────────────────────────────────────────┘
项目结构
src/
├── index.ts # 应用入口,bootstrap 初始化流程
├── agents/
│ ├── main-agent.ts # 主智能体(规划层)
│ └── sub-agent.ts # 子智能体(执行层)
├── api/
│ └── index.ts # Express HTTP API 层(SSE 流式 + /metrics)
├── config/
│ └── fallback.ts # 保底机制配置加载器
├── context/
│ ├── dynamic-context.ts # 动态上下文构建器
│ └── claude-md-loader.ts # CLAUDE.md 加载器
├── hooks/ # 🆕 P2-2: Hooks 生命周期系统
│ ├── types.ts # HookEvent 枚举 + HookContext 接口
│ └── hook-manager.ts # Hook 管理器(注册/触发/隔离)
├── llm/
│ ├── index.ts # LLM 客户端(多 provider + 并行工具执行)
│ ├── error-recovery.ts # 🆕 P0-4: 错误恢复管理器
│ └── vision-client.ts # 视觉模型客户端(GLM-4V)
├── memory/
│ ├── memory-service.ts # 统一记忆服务
│ ├── conversation-memory.ts # 对话历史持久化
│ ├── session-context.ts # 短期会话上下文(内存)
│ ├── auto-compact.ts # 四层上下文压缩 + 🆕 P1-4: 压缩后上下文重注入
│ ├── token-counter.ts # 🆕 P1-3: Token 精确计算(tiktoken + 估算回退)
│ └── types.ts # 记忆类型定义
├── mcp/ # 🆕 P3-3: MCP 协议集成
│ └── mcp-client.ts # MCP 客户端(stdio + SSE 传输)
├── observability/ # 🆕 P2-1: 可观测性
│ ├── logger.ts # 结构化 JSON 日志(级别控制 + 子 Logger)
│ └── metrics.ts # 指标采集(counter/histogram/gauge + Prometheus)
├── orchestrator/ # 🆕 P3-5: 分层编排器
│ └── index.ts # Orchestrator(任务编排 + 智能重规划)
├── planners/
│ └── unified-planner.ts # 统一规划器(合并分析+匹配+规划)
├── prompts/
│ ├── main-agent.ts # 主智能体/匹配器/规划器/重规划器 Prompt
│ ├── sub-agent.ts # 子智能体 Prompt
│ ├── prompt-builder.ts # 🆕 P1-5: Prompt 缓存构建器(静态/动态段落分离)
│ └── index.ts # Prompt 导出
├── routers/
│ └── intent-router.ts # 意图路由器(快速路径 + LLM 判断)
├── security/ # 🆕 P0-2/P3-1: 安全模块
│ ├── path-guard.ts # 路径安全检查 + 危险命令拦截
│ └── sandbox.ts # 沙箱隔离(bubblewrap)
├── skill-registry/
│ └── index.ts # 技能注册表(渐进式披露 + 🆕 P2-3: 热重载)
├── task-queue/
│ ├── index.ts # 任务队列(DAG + 并发 + 🆕 P1-1: 事件驱动 + P3-4: 弱依赖)
│ └── storage.ts # 🆕 P0-3: 任务持久化存储(防抖 + 原子写入)
├── tools/
│ ├── interfaces.ts # 工具接口定义
│ ├── base-tool.ts # 工具抽象基类
│ ├── tool-registry.ts # 工具注册表(+ 🆕 P1-2: isConcurrencySafe)
│ ├── file-read-tool.ts # 文件读取工具(+ 🆕 P0-2: 路径安全检查)
│ ├── bash-tool.ts # Shell 命令工具(+ 🆕 P0-2: 命令安全检查)
│ ├── glob-tool.ts # 文件模式匹配工具
│ ├── grep-tool.ts # 文件内容搜索工具
│ ├── write-tool.ts # 文件写入工具(+ 🆕 P0-2: 路径安全检查)
│ ├── edit-tool.ts # 文件编辑工具(+ 🆕 P0-2: 路径安全检查)
│ ├── context-tool.ts # 上下文管理工具
│ └── vision-analyze-tool.ts # 视觉分析工具
├── types/
│ ├── index.ts # 核心类型(+ 🆕 P0-4: LLMErrorType 扩展 + P3-4: weakDependencies)
│ └── requirement-types.ts # 需求拆解类型定义
└── user-profile/
└── index.ts # 用户画像服务
核心设计原则
| 原则 | 说明 |
|---|---|
| 规划-执行分离 | MainAgent 只规划不执行,SubAgent 只执行不规划 |
| 渐进式披露 | SkillRegistry 启动时只加载元数据,执行时才加载完整内容 |
| 保守默认策略 | BaseTool 的 isConcurrencySafe / isReadOnly 默认 false |
| 事件驱动 | LLMEventEmitter 实时推送推理过程;TaskQueue 事件驱动替代轮询 |
| 熔断器 | AutoCompactService 连续失败 3 次停止压缩 |
| DAG 调度 | TaskQueue 基于依赖关系的任务调度 + 循环检测 + 弱依赖支持 |
| 策略模式 | IntentRouter 快速路径(正则) vs LLM 路径 |
| 依赖注入 | LLMClient、SkillRegistry、TaskQueue 通过构造函数注入 |
| 安全纵深防御 | PathGuard 路径检查 + allowedTools 权限过滤 + 沙箱隔离 |
主智能体 (MainAgent)
主智能体是整个系统的 规划与调度中枢,不执行具体任务。
核心职责
- 需求接收与预处理 — 接收用户输入,处理图片附件(调用 VisionLLMClient 分析)
- 上下文加载与注入 — 加载用户画像、对话历史、动态上下文
- 意图路由 — 通过 IntentRouter 分类用户意图
- 任务规划 — 单任务直接创建计划,多任务调用 UnifiedPlanner
- 任务调度与监控 — 提交任务到 TaskQueue,轮询等待完成
- 失败重规划 — 最多 3 次重规划(replan),仅对 RETRYABLE 错误重试
- 结果汇总与持久化 — 合并子任务结果,保存交互记录
processRequirement 主流程
用户请求
│
├─ [步骤1] 图片分析(如有附件)→ VisionLLMClient.analyzeImage()
│
├─ [步骤2] 上下文加载
│ ├─ 加载用户画像 (UserProfileService)
│ ├─ 加载对话历史 (MemoryService)
│ ├─ 微压缩 (microCompact) → 清除 >5min 的工具结果
│ ├─ 自动压缩 (checkAndCompact) → tokens > 167K 时 LLM 摘要
│ ├─ 加载 SessionContext(当前会话状态)
│ └─ 构建动态上下文 (DynamicContextBuilder)
│
├─ [步骤3] 意图路由 (IntentRouter.classify)
│ ├─ small_talk → 直接返回闲聊回复
│ ├─ confirm_system → 返回确认问题
│ ├─ unclear → 返回转人工消息
│ └─ skill_task → 继续处理
│
├─ [步骤4] 任务规划
│ ├─ 单任务 → 直接构建 TaskPlan
│ └─ 多任务 → UnifiedPlanner.plan()(一次 LLM 调用)
│
├─ [步骤5] 任务执行 (monitorAndReplan)
│ ├─ submitPlanTasks() → 提交到 TaskQueue
│ ├─ waitForCompletion() → 轮询等待(指数退避 100ms→1s)
│ └─ 失败时 replan() → 最多 3 次
│
└─ [步骤6] 结果汇总
├─ 合并所有子任务响应
├─ 更新用户画像
├─ 保存交互记录
└─ 返回最终结果
关键设计决策
- 规划与执行分离: MainAgent 绝不直接调用工具,所有具体操作通过 SubAgent 执行
- 指数退避轮询:
waitForCompletion使用 100ms 起步、最大 1s 的指数退避轮询机制 - 重规划机制:
monitorAndReplan实现了最多 3 次的自动重规划循环,仅对 RETRYABLE 错误重试 - 复合需求处理: 支持一个用户请求中包含多个技能任务(如"帮我查报销和请假")
- 转人工与技能任务并行: 检测到转人工请求时,仍会执行已匹配的技能任务,结果中合并转人工提示
子智能体 (SubAgent)
子智能体是 纯执行层,负责加载技能、构建 Prompt、通过 LLM function calling 驱动工具调用。
核心职责
- 从 SkillRegistry 加载技能的完整定义(SKILL.md body)
- 构建子智能体 System Prompt(注入技能说明 + 已获取参数 + 保底规则)
- 注册可用工具列表,通过 LLM function calling 驱动工具调用
- 执行工具调用循环(最多 5 轮工具调用迭代)
- 返回最终文本响应
执行流程
SubAgent.execute(task)
│
├─ 加载技能 (skillRegistry.loadFullSkill)
│
├─ 构建 System Prompt
│ ├─ SUB_AGENT_BASE_PROMPT(基础指令)
│ ├─ 技能说明 body(从 SKILL.md 加载)
│ ├─ 技能根目录路径
│ ├─ 已获取参数(从 task.params 传入)
│ └─ 保底规则(从 config/fallback.md 加载)
│
├─ 注册工具列表(10 个工具)
│ ├─ context-get / context-set / context-get-all
│ ├─ conversation-get
│ ├─ bash / read / write / edit / glob / grep
│ └─ vision-analyze
│
└─ LLM 工具调用循环 (generateWithTools, maxIterations=5)
├─ LLM 返回 content → 直接返回
└─ LLM 返回 tool_calls → 执行工具 → 将结果回传 LLM → 继续循环
参数获取优先级
子智能体 Prompt 中定义了严格的参数获取优先级,避免重复询问用户:
1. 检查「已获取参数」(task.params) → 主智能体已提取的参数
2. 调用 context-get → 会话上下文中缓存的参数
3. 调用 conversation-get → 从对话历史中提取
4. 最后才询问用户
任务调度 (TaskQueue)
TaskQueue 是系统的 调度引擎,实现 DAG 依赖管理与并发控制。
核心特性
| 特性 | 说明 |
|---|---|
| DAG 依赖管理 | 支持任务间的依赖关系,使用 DFS 检测循环依赖 |
| 并发控制 | 最大 5 个并发子智能体(MAX_CONCURRENT_SUBAGENTS = 5) |
| 任务状态机 | pending → running → completed / failed |
| 超时处理 | 每个任务有独立超时(默认 400s),使用 AbortController 中止 |
| 失败传播 | 父任务失败时,级联标记所有依赖任务为失败 |
| 自动清理 | 每 5 分钟清理已完成/失败超过 1 小时的任务 |
| 结果大小限制 | 单个任务结果最大 1MB,超出则截断 |
调度流程
addTask(task)
│
├─ 校验:队列未满(max 100)、无循环依赖
│
├─ 记录依赖关系(dependencies / dependents 双向关联)
│
└─ processQueue()
│
├─ findReadyTasks() — 找出所有依赖已完成的 pending 任务
│ └─ 跳过无 skillName 的任务(仅跟踪任务)
│
├─ 按创建时间排序(FIFO)
│
└─ 对每个就绪任务(不超过并发上限)
└─ executeTask(task)
├─ 设置 AbortController 超时
├─ 调用 executor(即 SubAgent.execute)
├─ 成功 → completeTask → notifyDependents
└─ 失败 → failTask → failDependents(级联失败)
与 MainAgent 的交互模式
采用 推-拉结合 模式:
- 推: MainAgent 将任务推入 TaskQueue(
submitPlanTasks) - 拉: MainAgent 轮询 TaskQueue 中任务状态(
waitForCompletion,指数退避 100ms→1s)
意图路由 (IntentRouter)
IntentRouter 负责对用户输入进行意图分类,采用 快速路径 + LLM 综合判断 的双层策略。
多层信号收集
在分类前收集多个辅助信号,辅助 LLM 做出更准确的判断:
| 优先级 | 信号 | 置信度范围 | 说明 |
|---|---|---|---|
| 0 | 用户输入的系统名 | 0.90-1.00 | 直接匹配 systemName |
| 1 | Session Context 当前技能 | 0.70-0.90 | 当前会话激活的技能(随轮次衰减) |
| 2 | 关键词命中 | 0.70-0.88 | 从技能 metadata.keywords 匹配 |
| 3 | 历史技能 | 0.60-0.75 | 上一个会话使用的技能 |
| 4 | 用户画像 | 0.50-0.65 | 统计信息,参考价值低 |
快速路径 vs LLM 路径
classify(userInput)
│
├─ 收集所有信号 (collectSignals)
│
├─ 决策引擎 (decide)
│ ├─ 快速闲聊匹配 → 正则匹配 7 种闲聊模式 → 直接返回(无 LLM 调用)
│ └─ 超出范围匹配 → 正则匹配 30+ 种超出范围模式 → 直接返回
│
└─ LLM 综合判断 (llmMatchSkillWithSignals)
├─ 构建 Prompt(包含对话历史 + 辅助信号 + 技能列表 + 保底规则)
├─ 调用 LLM(generateStructured,Zod Schema 校验)
└─ 返回 IntentResult(intent + tasks + confidence)
意图类型: skill_task | small_talk | confirm_system | out_of_scope | unclear
闲聊快速应答: 预定义 7 种闲聊模式正则匹配(问候、同理心、身份、感谢、告别、帮助、能力查询),匹配后直接返回模板化回复,无需 LLM 调用,大幅降低延迟。
统一规划器 (UnifiedPlanner)
UnifiedPlanner 是性能优化的产物,将原来的 3-4 次 LLM 调用合并为 1 次:
优化前: IntentRouter.classify() + analyzeRequirement() + discoverSkills() + createPlan()
优化后: IntentRouter.classify() + UnifiedPlanner.plan() (仅 2 次 LLM 调用)
输出 Schema (Zod 校验):
const UnifiedPlanSchema = z.object({
analysis: z.object({ summary, entities, intent }).optional(),
skillSelection: z.any(), // 支持数组或对象两种格式
plan: z.object({
needsClarification: z.boolean().optional(),
clarificationPrompt: z.string().optional(),
tasks: z.array(z.any()),
}),
});
规划器会验证选中的技能是否存在,处理多种字段名格式(skillName/skill、requirement/description),确保健壮性。
工具体系
工具接口设计
所有工具实现 Tool 接口,继承自 BaseTool 抽象类:
interface Tool {
name: string;
description: string;
parameters?: ToolParameters;
required?: string[];
execute(input: unknown, context: ToolContext): Promise<ToolResult>;
isConcurrencySafe(input: unknown): boolean; // 默认 false(保守策略)
isReadOnly(): boolean; // 默认 false(保守策略)
}
关键设计: BaseTool 采用 保守默认策略 — isConcurrencySafe() 和 isReadOnly() 默认都返回 false,子类必须显式声明为安全才允许并发。
已注册工具一览
| 工具名 | 类型 | 并发安全 | 只读 | 用途 |
|---|---|---|---|---|
context-get |
上下文 | 获取会话参数 | ||
context-get-all |
上下文 | 获取所有会话参数 | ||
context-set |
上下文 | 保存会话参数 | ||
conversation-get |
上下文 | 获取对话历史 | ||
bash |
文件/命令 | 执行 Shell 命令 | ||
read |
文件 | 读取文件 | ||
write |
文件 | 写入文件 | ||
edit |
文件 | 编辑文件 | ||
glob |
文件 | 文件模式匹配 | ||
grep |
文件 | 文件内容搜索 | ||
vision-analyze |
视觉 | 图片分析 |
记忆与上下文系统
三层记忆架构
| 层级 | 组件 | 存储 | 生命周期 | 用途 |
|---|---|---|---|---|
| L1 | SessionContextService | 内存 (Map) | 会话级(30分钟过期) | 当前对话窗口状态、临时变量 |
| L2 | ConversationMemoryService | 文件系统 (JSON) | 持久化(滑动窗口) | 对话历史记录 |
| L3 | UserProfileService | 文件系统 (JSON) | 永久 | 用户画像(部门、常用系统、标签) |
四层上下文压缩
AutoCompactService 实现了递进式压缩策略,根据上下文压力自动选择最轻量的方案:
| 层级 | 触发条件 | 操作 | 成本 |
|---|---|---|---|
| MICRO | 工具结果 > 5 分钟 | 替换为占位符 | 零 |
| AUTO | tokens > 167K | LLM 摘要压缩 | 高 |
| SESSION | 会话结束 | 会话级压缩 | 中 |
| REACTIVE | 上下文压力 | 响应式压缩 | 可变 |
熔断器: 连续失败 3 次后停止压缩,防止级联故障。
Token 估算: 字符数 / 4,准确率约 85%。
动态上下文构建
DynamicContextBuilder 将用户画像和对话历史格式化为 Markdown 注入到 Prompt 中:
## 用户上下文
### 用户画像
- **用户ID**: user123
- **部门**: 研发部
- **常用系统**: EES, GEAM
- **对话次数**: 15
### 对话历史
[最近对话摘要...]
技能注册表 (SkillRegistry)
渐进式披露设计
- 扫描阶段: 只解析 YAML frontmatter(metadata),不加载 body
- 执行阶段: 按需加载完整 SKILL.md 内容(
loadFullSkill)
这避免了启动时加载大量技能文档的内存开销。
技能文件结构
skills/
├── {skill-name}/
│ ├── SKILL.md # 技能定义(YAML frontmatter + Markdown body)
│ ├── references/ # 知识库文档
│ │ ├── permission.md
│ │ └── login.md
│ └── scripts/ # 执行脚本(可选)
技能元数据
interface SkillMetadata {
name: string; // 技能名称
description: string; // 技能描述
metadata?: {
systemName: string; // 系统名(精确匹配用)
keywords: string[]; // 关键词(模糊匹配用)
trigger: string; // 触发场景
exclude: string; // 排除条件
};
allowedTools?: string[]; // 允许使用的工具
requiredFields?: string[]; // 需要从用户对话中提取的参数
hidden?: boolean; // 是否隐藏
}
LLM 客户端
多 Provider 支持
| Provider | 默认模型 | 特性 |
|---|---|---|
| OpenRouter | qwen/qwen3.6-plus-preview:free | 推理 + 流式 |
| NVIDIA | minimax-m2.5 | 流式 |
| Zhipu (智谱) | glm-4.7-flash | 推理 + 流式 |
| SiliconFlow | MiniMax-M2.5 | 流式 |
核心方法
| 方法 | 用途 | 使用者 |
|---|---|---|
generateText() |
纯文本生成 | AutoCompactService |
generateStructured() |
结构化输出(Zod Schema 校验) | IntentRouter, UnifiedPlanner, MainAgent.replan |
generateWithTools() |
工具调用循环(最多 5 轮) | SubAgent |
可靠性机制
- 指数退避重试: 最多 3 次,基础延迟 2s/4s/8s + 随机抖动
- 超时控制: 默认 120s,通过 AbortController 实现
- 错误分类: RATE_LIMIT / TIMEOUT / INVALID_KEY / API_ERROR / NETWORK_ERROR
- 推理内容捕获: 通过
llmEvents实时发射reasoning_content供前端展示
通信协议与数据流
MainAgent ↔ SubAgent 通信
通信是 间接的,通过 TaskQueue 解耦。MainAgent 和 SubAgent 在同一进程内运行,通过 TaskQueue 的内存数据结构(Map)共享任务状态。
MainAgent TaskQueue SubAgent
│ │ │
├─ submitPlanTasks(tasks) ────────>│ │
│ ├─ executeTask(task) ────────────>│
│ │ ├─ loadSkill()
│ │ ├─ buildPrompt()
│ │ ├─ LLM + Tools
│ │<───────── result ───────────────┤
│<───── poll (getTask status) ────│ │
SubAgent ↔ 工具通信
SubAgent 通过 LLM function calling 机制与工具交互:
SubAgent → LLM API (带 tools 定义)
LLM API → 返回 tool_calls
SubAgent → ToolRegistry.execute(toolName, arguments, context)
ToolRegistry → 具体工具.execute(input, context)
结果 → 回传 LLM → 继续循环(最多 5 轮)
前端 ↔ API 通信 (SSE)
主要使用 SSE (Server-Sent Events) 流式接口:
POST /tasks/stream
├─ event: start → 开始处理
├─ event: step → 处理步骤(捕获 MainAgent/SubAgent/IntentRouter 日志)
├─ event: reasoning → LLM 思考过程(通过 llmEvents 事件系统)
├─ event: complete → 最终结果
└─ event: error → 错误信息
LLM 事件系统
LLMEventEmitter 是一个全局事件发射器,用于追踪 LLM 的推理过程:
class LLMEventEmitter {
setAgent(agent: 'MainAgent' | 'SubAgent'): void; // 切换当前 Agent 标识
emit(event: 'reasoning' | 'response', data: string): void;
on(event, callback): void;
off(event, callback): void;
}
SubAgent 在执行前设置 llmEvents.setAgent('SubAgent'),执行后恢复,使得 API 层可以区分推理事件来自哪个 Agent。
保底机制 (Fallback)
保底规则通过 Markdown 配置文件管理,注入到 IntentRouter 和 SubAgent 的 System Prompt 中。
触发条件:
- 显式转人工: 用户说"转人工/转工程师"时直接触发
- 被动转人工: 知识库检索 2 次无结果 / 追问超过 2 次
- 反问约束: 最多追问 2 次,禁止跨域提问,禁止猜测
- 技能匹配规则: 精确匹配优先,用户否定后终止猜测
- 复合场景: 当前有技能任务时,"转人工XXX"需返回 2 个任务(转人工 + 新技能)
可通过环境变量 FALLBACK_CONFIG 切换不同业务的保底规则:
FALLBACK_CONFIG=fallback.md # 运维业务(默认)
FALLBACK_CONFIG=ecommerce.md # 电商业务
API 接口
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /health | 健康检查 |
| GET | /skills | 列出所有技能 |
| GET | /metrics | |
| POST | /tasks/stream | SSE 流式任务提交 |
| POST | /tasks/execute | |
| GET | /tasks/:id | 任务状态 |
| GET | /tasks/:id/result | 任务结果 |
| DELETE | /tasks/:id | 取消任务 |
请求格式
{
"userId": "user-xxx",
"sessionId": "session-xxx",
"requirement": "用户需求描述"
}
响应格式
技能任务:
{
"results": [
{
"taskId": "plan-xxx-task-1",
"skillName": "geam-qa",
"requirement": "申请GEAM权限",
"response": "您好!请问您要登录系统操作什么?...",
"status": "completed"
}
],
"type": "skill_task"
}
转人工:
{
"message": "您好,我帮您转到人工这边...",
"type": "unclear"
}
确认系统:
{
"message": "您提到的'BCC系统',请问具体是哪个系统?",
"type": "confirm_system"
}
会话管理
每个浏览器窗口独立:
userId:user-{时间戳}-{随机6位}sessionId:session-{时间戳}
| 层级 | 组件 | 存储 | 生命周期 |
|---|---|---|---|
| L1 | SessionContextService | 内存 (Map) | 会话级(30分钟过期) |
| L2 | ConversationMemoryService | 文件系统 (JSON) | 持久化(滑动窗口) |
| L3 | UserProfileService | 文件系统 (JSON) | 永久 |
配置
环境变量
| 环境变量 | 说明 | 默认值 |
|---|---|---|
| ZHIPU_API_KEY | 智谱 API Key | - |
| NVIDIA_API_KEY | NVIDIA API Key | - |
| OPENROUTER_API_KEY | OpenRouter API Key | - |
| LLM_PROVIDER | LLM 提供商 | zhipu |
| LLM_MODEL | 模型名称 | glm-4.5-air |
| FALLBACK_CONFIG | 保底机制配置文件 | fallback.md |
系统常量
| 配置项 | 默认值 | 说明 |
|---|---|---|
| MAX_CONCURRENT_SUBAGENTS | 5 | 最大并发子智能体数 |
| MAX_QUEUE_SIZE | 100 | 任务队列最大容量 |
| MAX_REPLAN_ATTEMPTS | 3 | 最大重规划次数 |
| TASK_TIMEOUT_MS | 400,000 (400s) | 单任务超时 |
| TOTAL_TIMEOUT_MS | 600,000 (600s) | 总工作流超时 |
| LLM_TIMEOUT_MS | 120,000 (120s) | LLM API 超时 |
| SCRIPT_TIMEOUT_MS | 180,000 (180s) | 脚本执行超时 |
| LLM_TEMPERATURE | 0.7 | 生成温度 |
| SKILL_DIRECTORY | ./skills/ | 技能目录 |
可观测性
结构化日志
使用 Logger 替代 console.log,输出 JSON 格式日志,支持日志级别和上下文注入:
import { createLogger } from './observability/logger';
const log = createLogger({ module: 'SubAgent', taskId: 'xxx' });
log.info('任务开始执行');
log.error('任务执行失败', { code: 500, skill: 'geam-qa' });
日志级别通过 LOG_LEVEL 环境变量配置(默认 info)。
指标采集
MetricsCollector 提供 counter、histogram、gauge 三种指标类型,通过 GET /metrics 端点输出 Prometheus 格式:
import { metrics } from './observability/metrics';
metrics.incrementCounter('tasks_total');
metrics.recordHistogram('task_latency_ms', 150);
Hooks 生命周期
HookManager 在关键节点触发事件,支持自定义回调:
import { hookManager } from './hooks/hook-manager';
import { HookEvent } from './hooks/types';
hookManager.on(HookEvent.BEFORE_TASK_EXECUTE, async (ctx) => {
console.log(`任务 ${ctx.taskId} 即将执行`);
});
hookManager.on(HookEvent.AFTER_TOOL_CALL, async (ctx) => {
// 审计日志
});
可用事件: BEFORE_INTENT_CLASSIFY | AFTER_INTENT_CLASSIFY | BEFORE_TASK_EXECUTE | AFTER_TASK_EXECUTE | BEFORE_TOOL_CALL | AFTER_TOOL_CALL | ON_ERROR | ON_FALLBACK
扩展能力
Plan Mode
通过 planMode 选项启用规划预览,用户确认后再执行:
const result = await mainAgent.processRequirement(requirement, undefined, userId, sessionId, {
planMode: true // 返回计划详情,不执行
});
// 确认后通过 POST /tasks/execute 提交执行
沙箱隔离
Sandbox 基于 bubblewrap 提供文件系统和网络隔离,自动回退:
import { Sandbox } from './security/sandbox';
const result = Sandbox.execute('cat /etc/passwd', '/workspace', {
allowedDirs: ['/workspace'],
network: false, // 禁止网络访问
});
// bwrap 不可用时自动回退到直接执行并发出警告
MCP 协议集成
MCPClient 支持通过 MCP 协议接入外部工具(JIRA、GitLab 等):
import { MCPClient } from './mcp/mcp-client';
const mcp = new MCPClient();
await mcp.connectServer({
name: 'jira',
transport: 'stdio',
command: 'npx',
args: ['@anthropic/mcp-server-jira'],
});
const result = await mcp.callTool('jira', 'search_issues', { jql: 'project=API' });
分层编排器
Orchestrator 将调度、监控、重规划逻辑从 MainAgent 中分离:
import { Orchestrator } from './orchestrator';
const orchestrator = new Orchestrator(taskQueue, llm, skillRegistry, planner);
const result = await orchestrator.orchestrate(plan);
// 包含事件驱动等待、超时保护、智能重规划
测试
使用 vitest 运行测试:
# 运行全部测试
npx vitest run
# 运行优化项测试(66 个用例)
npx vitest run __tests__/optimizations.test.ts
# TypeScript 编译检查
npx tsc --noEmit
测试覆盖: 66 个测试用例,覆盖 P0-P3 全部 18 项优化的核心逻辑。
快速开始
# 安装
bun install
# 配置环境变量
cp .env.example .env
# 编辑 .env 添加 API Key
# 启动
bun run src/index.ts
# 测试页面
open http://localhost:3000/test.html
架构优化记录
基于 Claude Code 源码深度解读 的对比分析,已完成 18 项架构优化。
P0 — 紧急(安全加固与可靠性)
| 编号 | 优化项 | 新增文件 | 修改文件 |
|---|---|---|---|
| P0-1 | allowedTools 权限过滤 | — | sub-agent.ts |
| P0-2 | 敏感文件/命令保护 | security/path-guard.ts | bash-tool.ts, file-read-tool.ts, write-tool.ts, edit-tool.ts |
| P0-3 | 任务状态持久化 | task-queue/storage.ts | task-queue/index.ts |
| P0-4 | 错误恢复增强 | llm/error-recovery.ts | types/index.ts (LLMErrorType 扩展) |
P1 — 重要(性能优化)
| 编号 | 优化项 | 新增文件 | 修改文件 |
|---|---|---|---|
| P1-1 | 事件驱动替代轮询 | — | task-queue/index.ts, main-agent.ts |
| P1-2 | 并行工具执行 | — | llm/index.ts, tool-registry.ts |
| P1-3 | Token 精确计算 | memory/token-counter.ts | memory/auto-compact.ts |
| P1-4 | 压缩后上下文重注入 | — | memory/auto-compact.ts |
| P1-5 | Prompt Cache 优化 | prompts/prompt-builder.ts | — |
P2 — 改进(可观测性与扩展性)
| 编号 | 优化项 | 新增文件 | 修改文件 |
|---|---|---|---|
| P2-1 | 结构化日志与指标 | observability/logger.ts, observability/metrics.ts | api/index.ts |
| P2-2 | Hooks 生命周期系统 | hooks/types.ts, hooks/hook-manager.ts | — |
| P2-3 | 技能热重载 | — | skill-registry/index.ts, index.ts |
| P2-4 | Plan Mode | — | main-agent.ts, api/index.ts |
P3 — 长期(架构演进)
| 编号 | 优化项 | 新增文件 | 修改文件 |
|---|---|---|---|
| P3-1 | 沙箱隔离 | security/sandbox.ts | — |
| P3-2 | 多进程架构 | — | (框架已搭建) |
| P3-3 | MCP 协议集成 | mcp/mcp-client.ts | — |
| P3-4 | 弱依赖级联失败 | — | task-queue/index.ts, types/index.ts |
| P3-5 | 分层编排器 | orchestrator/index.ts | — |
变更统计: 新增 12 个文件,修改 14 个文件,66 个测试用例全部通过,TypeScript 编译零错误。