21 KiB
| title | status | created | plan-type | depth | origin |
|---|---|---|---|---|---|
| feat: AgentKit Phase 9 — Integrated Next-Stage Plan | active | 2026-06-12 | feat | deep | 整合 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 存在三个核心问题:
- 对话响应仍不够快:启发式分类器已消除路由层 LLM 调用,但当启发式不确定时仍走独立 IntentRouter LLM 调用;Chat 管线中每次消息新建 ReActEngine、串行 Session I/O 等仍有优化空间
- 安全加固和测试覆盖有缺口:配置热重载的线程安全问题、ReWOO 回退链不可配置、集成测试覆盖不足
- 拍卖机制未实现: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 要求同时输出:
{"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
路由合并流程
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
智能并行工具执行
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
拍卖机制
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:
- 在
CostAwareRouter中新增_classify_merged()方法,构建单次 LLM prompt 要求同时输出 complexity + intent + skill_hint - 修改
_route_layer1():当HeuristicClassifier返回不确定区间(0.3-0.7)时,调用_classify_merged()而非分别调用quick_classify()和IntentRouter._classify_with_llm() - LLM 返回格式:
{"complexity": float, "intent": str, "skill_hint": str|null},使用 JSON mode 确保格式可靠 - Fallback:LLM 格式异常时按
complexity=0.5走默认 Agent - 配置开关:
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 获取已有 ReActEnginesrc/agentkit/core/react.py— 新增reset()方法重置内部状态tests/unit/test_chat_routes.py— 新增测试tests/unit/test_react_engine.py— 新增test_reset测试
Approach:
- 在
ReActEngine中新增reset()方法,清空内部对话历史、step count、cancellation token - 在
AgentPool.create_agent()中创建ReActEngine实例并绑定到agent._react_engine - 修改
_handle_chat_message():从agent._react_engine获取实例,调用reset()后执行 - 若 Agent 无
_react_engine(向后兼容),仍新建实例 - 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 标注 parallelizabletests/unit/test_react_engine.py— 新增并行测试configs/agentkit.yaml—parallel_tools支持"auto"值
Approach:
- 修改
parallel_tools参数类型为bool | str,支持True/False/"auto" - 在 ReActEngine 的 system prompt 中添加指引:当返回多个 tool_calls 时,在每个 tool_call 的 arguments 中包含
_parallelizable: true/false _execute_loop()中:parallel_tools=True→ 全部asyncio.gatherparallel_tools=False→ 全部串行parallel_tools="auto"→ 收集parallelizable=true的工具并行执行,其余串行
- 执行顺序:先执行所有串行工具(按顺序),再并行执行所有可并行工具
- 结果按
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:
_on_config_change()从 watchfiles 线程调用时,通过asyncio.run_coroutine_threadsafe(_async_reload_config(app, config), loop)调度到事件循环- 新增
_async_reload_config()异步方法,包含原重载逻辑 - 添加
_config_reload_lock的线程安全版本(threading.Lock+asyncio.Lock双锁) - 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:
ReWOOEngine.__init__()接受fallback_strategies: list[str]参数,默认["simplified_rewoo", "react", "direct"]- Skill YAML 中新增
fallback_strategies字段,覆盖默认值 _plan_phase()失败时按配置的策略顺序尝试 fallback- 支持的策略名:
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:
- 路由链测试:用户消息 → HeuristicClassifier → 合并 LLM 调用 → Skill 匹配 → ReActEngine 执行 → 结果
- ReWOO 回退测试:Planning 失败 → simplified_rewoo → react → direct
- 并行工具测试:LLM 返回多个 tool_calls + parallelizable 标注 → 验证执行顺序
- 合并路由测试:不确定区间消息 → 单次 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:
Bid数据类:agent_id、cost_estimate、capability_score、quality_historyAuctioneer类:announce_task(task_desc, required_capabilities)→ 广播给合格 Agentsubmit_bid(bid)→ 收集标价resolve_auction()→ Vickrey 拍卖:最低价者赢,支付第二低价- 能力过滤:先按
required_capabilities过滤不合格竞标者
WealthTracker类:跟踪每个 Agent 的累计收入/支出,用于后续经济分析- 集成到
CostAwareRouter._route_layer2():当auction_enabled=True且有多个候选 Agent 时,发起拍卖 - 拍卖超时:默认 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:
- 当前前端收到
token事件时已经在渲染文本(currentAgentBubble.textContent += msg.content),但 LLM 决定调工具时需要"收回"已渲染的 token - 新增
thinking事件类型:LLM 的思考过程(如 "Let me search for..."),前端渲染为灰色斜体 token事件仅在 LLM 直接回答时发送(不调工具时)- 当 LLM 决定调工具时,发送
tool_call事件,前端将 thinking 文本替换为工具调用卡片 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 后服务自动重载,无异常日志