--- title: "feat: AgentKit Phase 9 — Integrated Next-Stage Plan" status: active created: 2026-06-12 plan-type: feat depth: deep origin: "整合 017/018/019/021 活跃计划剩余工作 + 本次会话发现的新问题" --- # feat: AgentKit Phase 9 — Integrated Next-Stage Plan ## Summary 整合全部活跃计划的剩余工作,形成统一的下一阶段实施计划。核心目标:完成对话响应速度优化(sub-1s 首 Token)、补齐安全加固和劣势项改进的遗漏项、实现拍卖机制和智能并行工具执行。 **来源计划完成度:** | 计划 | 完成度 | 剩余项 | |------|--------|--------| | 020 Pipeline 对抗闭环 | ~100% | 验证测试覆盖度 | | 017 Multi-Agent Marketplace | ~90% | U9 拍卖机制 | | 018 P2 安全加固 | ~90% | U6 配置热重载防御性修复 | | 019 劣势项改进 | ~70% | U4 集成测试、U5 ReWOO 回退链配置化 | | 021 响应速度优化 | ~60% | U2 合并路由 LLM 调用、U6 Chat 管线优化 | **本次会话新增修复(已完成):** - 确认卡片死锁修复(`pending_confirmations or {}` → `if is not None`) - Shell 白名单扩展(30 → 90+ 命令,管道智能检测) - SkillInstallTool 新增(Agent 可正确安装技能) - 前端技能列表自动刷新 ## Problem Frame 当前 AgentKit 存在三个核心问题: 1. **对话响应仍不够快**:启发式分类器已消除路由层 LLM 调用,但当启发式不确定时仍走独立 IntentRouter LLM 调用;Chat 管线中每次消息新建 ReActEngine、串行 Session I/O 等仍有优化空间 2. **安全加固和测试覆盖有缺口**:配置热重载的线程安全问题、ReWOO 回退链不可配置、集成测试覆盖不足 3. **拍卖机制未实现**:Multi-Agent Marketplace 的核心经济模型缺失 ## Scope Boundaries ### In Scope - 021-U2: 合并路由 LLM 调用(complexity + intent 单次 LLM) - 021-U6: Chat 管线优化(ReActEngine 复用、Session 操作并行化) - 智能并行工具执行(LLM 标注可并行性,自动判断) - 018-U6: 配置热重载防御性修复 - 019-U4: 集成测试补充 - 019-U5: ReWOO 回退链配置化 - 017-U9: 拍卖机制实现 - 流式首 Token 前端渲染优化 ### Out of Scope - 分布式消息总线(Redis 实现,后续按需) - jieba 分词集成(可选依赖,后续按需) - UI 可视化 trace(Jaeger/Zipkin 前端,运维配置) - Headroom 检索优化(013,独立计划) - 分层记忆系统(016,独立计划) ### Deferred to Follow-Up Work - LLM Provider 级别 Prompt 缓存(需 LLM API 支持) - 上下文压缩策略异步化(当前截断方案足够) - 轻量模型自动降级(需 A/B 测试验证质量) --- ## Requirements | ID | Requirement | Priority | Origin | |----|-------------|----------|--------| | R1 | 启发式分类器不确定时,complexity + intent 合并为单次 LLM 调用 | P0 | 021-U2 | | R2 | Chat 管线中 ReActEngine 实例复用,避免每次消息重建 | P0 | 021-U6 | | R3 | 多 tool_calls 时由 LLM 标注可并行性,自动并行执行独立工具 | P1 | 新需求 | | R4 | 配置热重载线程安全,非 asyncio 线程调用不触发竞态 | P1 | 018-U6 | | R5 | ReWOO 回退链可从 YAML 配置,不硬编码 | P1 | 019-U5 | | R6 | 关键路径集成测试覆盖:路由链、ReWOO 回退、对抗闭环 | P1 | 019-U4 | | R7 | 拍卖机制:Agent 竞标任务,基于能力+成本+历史质量评分 | P2 | 017-U9 | | R8 | 前端流式首 Token 即渲染,不等 final_answer | P2 | 021-P1 | | R9 | 所有改动有配置开关,可秒级回退 | P0 | 全局 | --- ## Key Technical Decisions ### KTD1: 合并路由 LLM 调用 — 单次 LLM 同时输出 complexity + intent 当 `HeuristicClassifier` 返回 `complexity=0.5`(不确定区间)时,不再分别调用 `quick_classify()` 和 `IntentRouter._classify_with_llm()`,而是发起一次 LLM 调用,prompt 要求同时输出: ```json {"complexity": 0.7, "intent": "code_generation", "skill_hint": "react_agent"} ``` 这比两次独立 LLM 调用节省 1-3s。LLM 的 structured output 能力确保格式可靠。 **Fallback**:若 LLM 返回格式异常,按 `complexity=0.5` 走默认 Agent。 ### KTD2: 智能并行工具执行 — LLM 在 tool_calls 中标注 `parallelizable` 在 `ReActEngine` 的 system prompt 中指示 LLM:当返回多个 tool_calls 时,在每个 tool_call 的 `_metadata` 中标注 `"parallelizable": true/false`。ReActEngine 收集所有 `parallelizable=true` 的工具,用 `asyncio.gather` 并行执行;`parallelizable=false` 或未标注的串行执行。 **为什么不用纯规则判断**:工具间的依赖关系是语义级的(如"先搜索再分析"),规则无法可靠判断。让 LLM 标注是最准确的方案。 **安全网**:`parallel_tools` 配置仍保留,设为 `"auto"` 时启用智能判断,设为 `true` 时全部并行,设为 `false` 时全部串行。 ### KTD3: ReActEngine 复用 — Agent 级别持有实例 在 `AgentPool.create_agent()` 中创建 `ReActEngine` 实例并绑定到 Agent 对象。`_handle_chat_message` 从 Agent 获取已有实例而非每次新建。每次调用 `execute_stream()` 前重置内部状态(对话历史、step count)。 **为什么不用全局单例**:不同 Agent 可能有不同的 `max_steps`、`parallel_tools` 配置,需要实例隔离。 ### KTD4: 拍卖机制 — Vickrey 拍卖 + 能力匹配 采用 Vickrey(次价)拍卖模型:Agent 提交密封标价(bid = cost_estimate),出价最低者赢得任务,但支付第二低价。结合能力匹配过滤不合格竞标者。 **为什么选 Vickrey**:激励相容——Agent 的最优策略是如实报告成本,不需要策略性报价。比英式拍卖更简单,比固定分配更高效。 ### KTD5: 配置热重载线程安全 — asyncio.run_coroutine_threadsafe `_on_config_change` 从 `watchfiles` 线程调用时,通过 `asyncio.run_coroutine_threadsafe()` 将重载操作调度到事件循环,避免在非 asyncio 线程中直接操作 asyncio 对象。 --- ## High-Level Technical Design ### 路由合并流程 ```mermaid flowchart TD A[用户消息] --> B{HeuristicClassifier} B -->|complexity < 0.3| C[Layer 0: 默认 Agent] B -->|0.3 <= complexity <= 0.7| D[合并 LLM 调用: complexity + intent] B -->|complexity > 0.7| E[Layer 2: 能力匹配] D -->|有 skill_hint| F[路由到指定 Skill] D -->|无 skill_hint| C D -->|LLM 格式异常| C E -->|匹配成功| G[路由到最佳 Agent] E -->|无匹配| F ``` ### 智能并行工具执行 ```mermaid flowchart TD A[LLM 返回 tool_calls] --> B{parallel_tools 配置} B -->|false| C[全部串行执行] B -->|true| D[全部并行执行] B -->|auto| E[检查每个 tool_call 的 parallelizable 标注] E --> F[parallelizable=true 的工具 asyncio.gather 并行] E --> G[parallelizable=false 或未标注的串行执行] F --> H[合并结果,按 tool_call_id 排序] G --> H ``` ### 拍卖机制 ```mermaid sequenceDiagram participant Client participant Auctioneer participant Agent1 participant Agent2 Client->>Auctioneer: 提交任务 Auctioneer->>Agent1: 广播任务需求 Auctioneer->>Agent2: 广播任务需求 Agent1->>Auctioneer: 提交标价 (bid=0.3) Agent2->>Auctioneer: 提交标价 (bid=0.5) Auctioneer->>Auctioneer: Vickrey 拍卖: 赢家=Agent1, 支付=0.5 Auctioneer->>Agent1: 分配任务 (payment=0.5) Agent1->>Auctioneer: 返回结果 Auctioneer->>Client: 返回结果 ``` --- ## Implementation Units ### U1. 合并路由 LLM 调用 **Goal:** 当 HeuristicClassifier 不确定时,将 complexity 评估和 intent 分类合并为单次 LLM 调用,消除路由层的第二次 LLM 调用。 **Requirements:** R1, R9 **Dependencies:** None **Files:** - `src/agentkit/chat/skill_routing.py` — 新增 `MergedRouter` 类 - `src/agentkit/chat/skill_routing.py` — 修改 `CostAwareRouter._route_layer1()` 使用合并调用 - `tests/unit/test_cost_aware_router.py` — 新增测试 - `configs/agentkit.yaml` — 新增 `router.merged_llm_classify: true` 配置 **Approach:** 1. 在 `CostAwareRouter` 中新增 `_classify_merged()` 方法,构建单次 LLM prompt 要求同时输出 complexity + intent + skill_hint 2. 修改 `_route_layer1()`:当 `HeuristicClassifier` 返回不确定区间(0.3-0.7)时,调用 `_classify_merged()` 而非分别调用 `quick_classify()` 和 `IntentRouter._classify_with_llm()` 3. LLM 返回格式:`{"complexity": float, "intent": str, "skill_hint": str|null}`,使用 JSON mode 确保格式可靠 4. Fallback:LLM 格式异常时按 `complexity=0.5` 走默认 Agent 5. 配置开关:`router.merged_llm_classify: true`(默认),设为 false 时回退到独立调用 **Patterns to follow:** `HeuristicClassifier` 的配置开关模式(`classifier` 参数),`IntentRouter._classify_with_llm()` 的 LLM 调用模式 **Test scenarios:** - 合并调用返回有效 JSON,正确路由到指定 skill - 合并调用返回格式异常,fallback 到默认 Agent - 合并调用返回 complexity < 0.3,走 Layer 0 - 合并调用返回 complexity > 0.7,走 Layer 2 - 配置 `merged_llm_classify: false` 时回退到独立调用 - 合并调用超时,fallback 到默认 Agent **Verification:** 启用 `merged_llm_classify` 后,不确定区间的路由只产生 1 次 LLM 调用(而非 2 次) --- ### U2. Chat 管线优化 **Goal:** ReActEngine 实例复用 + Session 操作并行化,减少每次消息的初始化和 I/O 开销。 **Requirements:** R2, R9 **Dependencies:** None **Files:** - `src/agentkit/core/agent_pool.py` — Agent 创建时绑定 ReActEngine 实例 - `src/agentkit/server/routes/chat.py` — 从 Agent 获取已有 ReActEngine - `src/agentkit/core/react.py` — 新增 `reset()` 方法重置内部状态 - `tests/unit/test_chat_routes.py` — 新增测试 - `tests/unit/test_react_engine.py` — 新增 `test_reset` 测试 **Approach:** 1. 在 `ReActEngine` 中新增 `reset()` 方法,清空内部对话历史、step count、cancellation token 2. 在 `AgentPool.create_agent()` 中创建 `ReActEngine` 实例并绑定到 `agent._react_engine` 3. 修改 `_handle_chat_message()`:从 `agent._react_engine` 获取实例,调用 `reset()` 后执行 4. 若 Agent 无 `_react_engine`(向后兼容),仍新建实例 5. Session 操作:`append_message` 的 user message 和 assistant message 可并行写入(两者无依赖) **Patterns to follow:** `AgentPool.create_agent()` 的 Agent 初始化模式 **Test scenarios:** - ReActEngine.reset() 清空内部状态后可正常执行 - 连续两次 execute_stream() 调用互不干扰 - Agent 无 _react_engine 时向后兼容新建实例 - Session 并行写入后 get_messages() 返回完整消息列表 **Verification:** 连续发送 10 条消息,ReActEngine 实例 ID 保持不变 --- ### U3. 智能并行工具执行 **Goal:** LLM 在 tool_calls 中标注可并行性,ReActEngine 自动判断并行/串行执行。 **Requirements:** R3, R9 **Dependencies:** None **Files:** - `src/agentkit/core/react.py` — 修改 `_execute_loop()` 中的工具执行逻辑 - `src/agentkit/core/react.py` — 修改 system prompt 指示 LLM 标注 parallelizable - `tests/unit/test_react_engine.py` — 新增并行测试 - `configs/agentkit.yaml` — `parallel_tools` 支持 `"auto"` 值 **Approach:** 1. 修改 `parallel_tools` 参数类型为 `bool | str`,支持 `True`/`False`/`"auto"` 2. 在 ReActEngine 的 system prompt 中添加指引:当返回多个 tool_calls 时,在每个 tool_call 的 arguments 中包含 `_parallelizable: true/false` 3. `_execute_loop()` 中: - `parallel_tools=True` → 全部 `asyncio.gather` - `parallel_tools=False` → 全部串行 - `parallel_tools="auto"` → 收集 `parallelizable=true` 的工具并行执行,其余串行 4. 执行顺序:先执行所有串行工具(按顺序),再并行执行所有可并行工具 5. 结果按 `tool_call_id` 顺序追加到对话历史 **Patterns to follow:** 现有 `asyncio.gather` 并行执行模式(`parallel_tools=True` 分支) **Test scenarios:** - `parallel_tools="auto"` + LLM 标注 2 个 parallelizable=true → 并行执行 - `parallel_tools="auto"` + LLM 标注 1 个 true 1 个 false → 串行先执行,再并行 - `parallel_tools="auto"` + LLM 未标注 parallelizable → 全部串行(安全默认) - `parallel_tools=True` → 忽略标注,全部并行 - `parallel_tools=False` → 忽略标注,全部串行 - 并行执行结果按 tool_call_id 顺序追加 **Verification:** 发送需要多工具的消息,观察日志中的执行顺序和耗时 --- ### U4. 配置热重载防御性修复 **Goal:** 修复配置热重载的线程安全问题,确保非 asyncio 线程调用不触发竞态。 **Requirements:** R4, R9 **Dependencies:** None **Files:** - `src/agentkit/server/app.py` — 修改 `_on_config_change()` 使用 `asyncio.run_coroutine_threadsafe()` - `src/agentkit/server/app.py` — 添加 shell proc.kill() 错误处理 - `tests/unit/test_app_lifecycle.py` — 新增测试 **Approach:** 1. `_on_config_change()` 从 watchfiles 线程调用时,通过 `asyncio.run_coroutine_threadsafe(_async_reload_config(app, config), loop)` 调度到事件循环 2. 新增 `_async_reload_config()` 异步方法,包含原重载逻辑 3. 添加 `_config_reload_lock` 的线程安全版本(`threading.Lock` + `asyncio.Lock` 双锁) 4. shell proc.kill() 添加 try/except ProcessLookupError **Patterns to follow:** `asyncio.run_coroutine_threadsafe()` 模式 **Test scenarios:** - 从非 asyncio 线程触发配置变更,重载正常完成 - 并发配置变更,只有一个生效(锁保护) - proc.kill() 时进程已退出,不抛异常 - 配置变更后 LLM Gateway 正确重建 **Verification:** 修改 agentkit.yaml 后观察日志,确认重载在事件循环中执行 --- ### U5. ReWOO 回退链配置化 **Goal:** ReWOO 的 fallback 策略可从 YAML 配置,不硬编码。 **Requirements:** R5, R9 **Dependencies:** None **Files:** - `src/agentkit/core/rewoo.py` — `FALLBACK_STRATEGIES` 改为从配置读取 - `configs/skills/rewoo_agent.yaml` — 新增 `fallback_strategies` 字段 - `tests/unit/test_rewoo_engine.py` — 新增测试 **Approach:** 1. `ReWOOEngine.__init__()` 接受 `fallback_strategies: list[str]` 参数,默认 `["simplified_rewoo", "react", "direct"]` 2. Skill YAML 中新增 `fallback_strategies` 字段,覆盖默认值 3. `_plan_phase()` 失败时按配置的策略顺序尝试 fallback 4. 支持的策略名:`simplified_rewoo`、`react`、`direct`、`plan_exec` **Patterns to follow:** `SkillConfig` 的字段扩展模式 **Test scenarios:** - 默认 fallback 链:simplified_rewoo → react → direct - 自定义 fallback 链:plan_exec → react → direct - 空 fallback 链:直接抛异常 - 无效策略名:跳过并警告 **Verification:** 修改 rewoo_agent.yaml 的 fallback_strategies,重启后观察日志 --- ### U6. 集成测试补充 **Goal:** 补充关键路径的集成测试,保障其他模块改动的回归安全。 **Requirements:** R6 **Dependencies:** U1, U2, U3 **Files:** - `tests/integration/test_router_engine_chain.py` — 路由→引擎全链路测试 - `tests/integration/test_rewoo_fallback.py` — ReWOO 回退链测试 - `tests/integration/test_parallel_tools.py` — 并行工具执行测试 - `tests/integration/test_merged_router.py` — 合并路由测试 **Approach:** 1. 路由链测试:用户消息 → HeuristicClassifier → 合并 LLM 调用 → Skill 匹配 → ReActEngine 执行 → 结果 2. ReWOO 回退测试:Planning 失败 → simplified_rewoo → react → direct 3. 并行工具测试:LLM 返回多个 tool_calls + parallelizable 标注 → 验证执行顺序 4. 合并路由测试:不确定区间消息 → 单次 LLM 调用 → 正确路由 **Patterns to follow:** 现有 `tests/integration/test_react_loop.py` 模式 **Test scenarios:** - 路由链:问候语 → Layer 0 直达;代码问题 → 合并 LLM → react_agent - ReWOO 回退:mock LLM Planning 失败 → 验证 fallback 执行 - 并行工具:2 个 parallelizable=true 工具 → 验证并行执行(耗时 < 串行) - 合并路由:不确定消息 → 验证只产生 1 次 LLM 调用 **Verification:** `pytest tests/integration/ -v` 全部通过 --- ### U7. 拍卖机制实现 **Goal:** 实现 Vickrey 拍卖模型,Agent 竞标任务,基于能力+成本+历史质量评分。 **Requirements:** R7 **Dependencies:** None **Files:** - `src/agentkit/marketplace/auction.py` — 新增 `Auctioneer`、`Bid`、`AuctionResult` 类 - `src/agentkit/marketplace/wealth.py` — 新增 `WealthTracker` 类 - `src/agentkit/chat/skill_routing.py` — `CostAwareRouter._route_layer2()` 集成拍卖 - `configs/agentkit.yaml` — 新增 `router.auction_enabled: true` 配置 - `tests/unit/test_auction.py` — 新增测试 **Approach:** 1. `Bid` 数据类:agent_id、cost_estimate、capability_score、quality_history 2. `Auctioneer` 类: - `announce_task(task_desc, required_capabilities)` → 广播给合格 Agent - `submit_bid(bid)` → 收集标价 - `resolve_auction()` → Vickrey 拍卖:最低价者赢,支付第二低价 - 能力过滤:先按 `required_capabilities` 过滤不合格竞标者 3. `WealthTracker` 类:跟踪每个 Agent 的累计收入/支出,用于后续经济分析 4. 集成到 `CostAwareRouter._route_layer2()`:当 `auction_enabled=True` 且有多个候选 Agent 时,发起拍卖 5. 拍卖超时:默认 5s,超时后按最低价直接分配 **Patterns to follow:** `CostAwareRouter` 的三层路由模式,`org_context.find_best_agent()` 的能力匹配模式 **Test scenarios:** - 单一竞标者 → 直接分配,支付 0 - 两个竞标者 → Vickrey 拍卖,低价者赢,支付第二低价 - 竞标者能力不匹配 → 过滤掉,不参与拍卖 - 拍卖超时 → 按已有标价分配 - 无竞标者 → fallback 到 IntentRouter - WealthTracker 正确累计收入/支出 **Verification:** 配置 `auction_enabled: true`,发送高复杂度消息,观察拍卖日志 --- ### U8. 流式首 Token 前端渲染 **Goal:** 前端收到首个 token 即开始渲染,不等 final_answer,降低感知延迟。 **Requirements:** R8 **Dependencies:** U2 **Files:** - `src/agentkit/server/static/index.html` — 修改 WebSocket 消息处理逻辑 - `src/agentkit/core/react.py` — 流式事件增加 `is_final` 标记 **Approach:** 1. 当前前端收到 `token` 事件时已经在渲染文本(`currentAgentBubble.textContent += msg.content`),但 LLM 决定调工具时需要"收回"已渲染的 token 2. 新增 `thinking` 事件类型:LLM 的思考过程(如 "Let me search for..."),前端渲染为灰色斜体 3. `token` 事件仅在 LLM 直接回答时发送(不调工具时) 4. 当 LLM 决定调工具时,发送 `tool_call` 事件,前端将 thinking 文本替换为工具调用卡片 5. `final_answer` 事件标记 `is_final: true`,前端完成渲染 **关键 UX 决策**:不在 LLM 可能调工具时渲染 token,避免"文字闪烁消失"问题。只在确认是最终回答时才渲染 token 流。 **Patterns to follow:** 现有 `token` / `final_answer` 事件处理模式 **Test scenarios:** - LLM 直接回答 → token 流式渲染,无闪烁 - LLM 先思考再调工具 → thinking 渲染为灰色,工具调用显示为卡片 - LLM 思考后直接回答 → thinking 后接 token 流式渲染 - 多轮工具调用 → 每轮工具调用显示为步骤卡片 **Verification:** 发送需要工具调用的消息,观察前端渲染无闪烁 --- ## Risks & Mitigations | Risk | Impact | Mitigation | |------|--------|------------| | 合并 LLM 调用格式不稳定 | 路由失败,走 fallback | JSON mode + 严格 schema 校验 + fallback 到默认 Agent | | 智能并行工具执行依赖误判 | 工具结果错误 | `parallel_tools="auto"` 默认保守(未标注=串行);`true` 模式需显式启用 | | 拍卖机制增加路由延迟 | 高复杂度任务响应更慢 | 拍卖超时 5s;单竞标者时跳过拍卖直接分配 | | ReActEngine 复用状态泄漏 | 上下文串扰 | `reset()` 方法严格清空所有内部状态;每次执行前强制调用 | | 流式渲染闪烁 | 用户体验差 | 只在确认不调工具时渲染 token;thinking 阶段渲染为灰色 | --- ## System-Wide Impact - **路由层**:`skill_routing.py` 变更最大(合并 LLM + 拍卖集成) - **引擎层**:`react.py` 变更(智能并行 + reset),`rewoo.py` 变更(配置化回退) - **服务层**:`chat.py` 变更(ReActEngine 复用),`app.py` 变更(热重载修复) - **前端**:`index.html` 变更(流式渲染优化) - **新增模块**:`marketplace/auction.py`、`marketplace/wealth.py` --- ## Open Questions - 拍卖机制的 `cost_estimate` 如何计算?当前 Agent 无自省能力,可能需要基于历史执行时间统计 - `parallel_tools="auto"` 的 LLM 标注格式是否需要与 OpenAI function calling 兼容?当前 `_parallelizable` 字段放在 arguments 中可能被 LLM 忽略 - 流式渲染的 thinking 文本是否需要持久化到 Session?当前不持久化,重载后丢失 --- ## Acceptance Examples - AE1: 发送一般问题,首 Token 在 1s 内出现(当前 3-5s) - AE2: 发送需要多工具的消息,工具并行执行,总耗时 < 串行执行 - AE3: 修改 rewoo_agent.yaml 的 fallback_strategies,重启后生效 - AE4: 配置 auction_enabled: true,高复杂度任务触发拍卖日志 - AE5: 修改 agentkit.yaml 后服务自动重载,无异常日志