fischer-agentkit/docs/plans/2026-06-12-022-feat-agentki...

21 KiB
Raw Permalink Blame History

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 存在三个核心问题:

  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 可视化 traceJaeger/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_stepsparallel_tools 配置,需要实例隔离。

KTD4: 拍卖机制 — Vickrey 拍卖 + 能力匹配

采用 Vickrey次价拍卖模型Agent 提交密封标价bid = cost_estimate出价最低者赢得任务但支付第二低价。结合能力匹配过滤不合格竞标者。

为什么选 Vickrey激励相容——Agent 的最优策略是如实报告成本,不需要策略性报价。比英式拍卖更简单,比固定分配更高效。

KTD5: 配置热重载线程安全 — asyncio.run_coroutine_threadsafe

_on_config_changewatchfiles 线程调用时,通过 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:

  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. FallbackLLM 格式异常时按 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.yamlparallel_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.pyFALLBACK_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_rewooreactdirectplan_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 — 新增 AuctioneerBidAuctionResult
  • src/agentkit/marketplace/wealth.py — 新增 WealthTracker
  • src/agentkit/chat/skill_routing.pyCostAwareRouter._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() 方法严格清空所有内部状态;每次执行前强制调用
流式渲染闪烁 用户体验差 只在确认不调工具时渲染 tokenthinking 阶段渲染为灰色

System-Wide Impact

  • 路由层skill_routing.py 变更最大(合并 LLM + 拍卖集成)
  • 引擎层react.py 变更(智能并行 + resetrewoo.py 变更(配置化回退)
  • 服务层chat.py 变更ReActEngine 复用),app.py 变更(热重载修复)
  • 前端index.html 变更(流式渲染优化)
  • 新增模块marketplace/auction.pymarketplace/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 后服务自动重载,无异常日志