```yaml title: "refactor: AgentKit 架构优化演进 — 对齐业界最佳实践" status: active plan_id: "2026-06-16-006" created: 2026-06-16 depth: deep origin: "基于对 Codex/Claude Code/Trae/Qoder 的深入分析,优化 AgentKit 架构" ``` # AgentKit 架构优化演进计划 ## Summary 基于对 Codex CLI、Claude Code、Trae Agent 2.0、Qoder 的深入分析,对 AgentKit 进行架构优化演进。核心变更:(1) 消除"路由"概念改为请求预处理,(2) 专家团从去中心化协作简化为 hub-and-spoke,(3) PlanExec 简化为 Spec-Driven 模式,(4) 聊天记录 SQLite 持久化,(5) 删除旧路由层代码,(6) 新增可验证执行和工具描述精简。 ## Problem Frame AgentKit 当前架构存在三类问题: 1. **概念误导**:SimpleRouter 仍暗示"路由层"存在,但实际只做 @skill 前缀解析 + greeting fast-path,核心决策已交给 REACT agent loop 中的 LLM 2. **过度设计**:ExpertTeam 的去中心化协作(CollaborationPlan + HandoffTransport + SharedWorkspace + 3 种 MergeStrategy)远超业界实践,增加 ~1500 行代码但无对应价值 3. **能力缺口**:PlanExecEngine 默认使用 _LLMStepExecutor(纯 LLM 调用无工具),聊天记录不持久化,无自动验证循环 ## Requirements - R1: 消除"路由"概念,SimpleRouter 重命名为 RequestPreprocessor,语义从"路由决策"变为"请求预处理" - R2: 专家团简化为 hub-and-spoke 模式(Lead Expert + 并行 Task,深度=1),删除 CollaborationPlan/HandoffTransport/SharedWorkspace 的 ExpertTeam 专用逻辑 - R3: PlanExecEngine 默认使用 ReActStepExecutor,删除 _LLMStepExecutor - R4: 聊天记录 SQLite 持久化(参考 Codex 的 Thread 持久化) - R5: 删除 CostAwareRouter 及相关代码(HeuristicClassifier、IntentRouter、QualityGate、SemanticRouter) - R6: 新增可验证执行(Test-and-Verify 循环,参考 Codex Cloud) - R7: 工具描述分层注入(核心工具全量 + 扩展工具一行描述 + tool_search 按需获取) - R8: 默认启用上下文压缩 - R9: 新增 Spec 文档作为一等公民(参考 Qoder Quest Mode) - R10: 统一事件模型(SQ/EQ 双队列,参考 Codex) ## Key Technical Decisions ### KTD1: SimpleRouter 重命名为 RequestPreprocessor **决策**:将 SimpleRouter 重命名为 RequestPreprocessor,route() 方法重命名为 preprocess() **依据**: - Codex 无路由层,Claude Code 无路由层,Trae 移除了 Proposal 阶段——业界共识是没有路由层 - SimpleRouter 的 3 个功能(@skill 前缀、greeting regex、default REACT)都是预处理而非路由决策 - "路由"概念误导开发者认为存在意图预测层,实际上 LLM 在 agent loop 中自主决策 **替代方案**:完全删除 SimpleRouter,所有请求直接进入 REACT loop。被否决——greeting fast-path 每次请求节省 ~100 tokens + 500ms,@skill 前缀是用户显式指令需要代码级解析 ### KTD2: 专家团 hub-and-spoke 模式 **决策**:ExpertTeam 从去中心化协作简化为 Lead Expert + 并行 Task(深度=1) **依据**: - Claude Code:Task 工具深度=1,子 Agent 不能再生子 Agent - Codex:spawn_agent 层级式,结果返回父 Agent - Qoder:多专家并行独立执行,主 Agent 汇总 - 去中心化协作的通信复杂度 O(N²),hub-and-spoke 为 O(N) - 同一 LLM 扮演不同"专家"不产生真正的观点多样性,等价于多次采样+合并 **保留**:ExpertConfig/ExpertTemplate/Registry(定义专家 persona)、BEST 合并策略(Lead Agent 选择最佳结果) **删除**:CollaborationPlan 的 phase 依赖图、HandoffTransport 的 Agent 间通信、SharedWorkspace 的跨阶段状态共享、VOTE/FUSION 合并策略 ### KTD3: PlanExec 默认 ReActStepExecutor + Spec-Driven **决策**:默认使用 ReActStepExecutor(已实现),删除 _LLMStepExecutor;新增 Spec 文档持久化 **依据**: - _LLMStepExecutor 不支持工具调用 = 没有执行能力 - ReActStepExecutor 已实现并使用 ReActEngine,支持工具调用和多步推理 - Qoder Quest Mode:Spec First 是人和 AI 的契约,用户确认后再执行 - 当前 PlanExec 的计划对用户不可见,用户无法在执行前纠正方向 ### KTD4: 聊天记录 SQLite 持久化 **决策**:使用 SQLite 做聊天记录持久化(参考 Codex 的 Thread 持久化) **依据**: - Codex 使用 SQLite(轻量、零配置、跨平台),支持 resume/fork/archive - Claude Code 使用 append-only JSONL(更简单但搜索能力弱) - 当前 ConversationStore 纯内存,服务重启后丢失 - SQLite 支持会话搜索、分页加载,且无需额外服务 --- ## Implementation Units ### U1. SimpleRouter 重命名为 RequestPreprocessor **Goal**: 消除"路由"概念,将 SimpleRouter 重命名为 RequestPreprocessor **Dependencies**: 无 **Files**: - `src/agentkit/chat/simple_router.py` → 重命名为 `src/agentkit/chat/request_preprocessor.py` - `src/agentkit/chat/skill_routing.py` — 更新引用 - `src/agentkit/server/routes/portal.py` — 更新 import 和调用 - `src/agentkit/server/routes/chat.py` — 更新 import 和调用 - `src/agentkit/server/app.py` — 更新 import 和调用 - `tests/unit/chat/test_simple_router.py` → 重命名并更新 **Approach**: 1. 创建 `request_preprocessor.py`,类名 `RequestPreprocessor`,方法 `route()` → `preprocess()` 2. `_is_direct_chat()` 重命名为 `_is_trivial_input()` 3. `SkillRoutingResult` 保留(它是数据结构,不涉及路由概念) 4. 更新所有调用点 5. 删除旧文件 **Patterns to follow**: 现有 SimpleRouter 的代码结构 **Test scenarios**: - @skill:xxx 前缀正确解析为 SKILL_REACT 模式 - Greeting regex 匹配返回 DIRECT_CHAT - 默认输入返回 REACT 模式 - 未知 skill 回退到 REACT - preprocess() 方法签名与 route() 兼容 **Verification**: `ruff check src/ && pytest tests/unit/chat/ -v` --- ### U2. 删除 CostAwareRouter 及相关代码 **Goal**: 删除已被 SimpleRouter 替代的旧路由层代码 **Dependencies**: U1 **Files**: - `src/agentkit/router/` 目录下大部分文件(保留 __init__.py 和必要的导出) - `src/agentkit/server/app.py` — 清理注释掉的引用 - `src/agentkit/chat/cost_aware_router.py` — 删除 **Approach**: 1. 确认 CostAwareRouter 在代码中无活跃引用(app.py 已注释) 2. 删除 `cost_aware_router.py`、`heuristic_classifier.py`、`intent.py`(IntentRouter)、`quality_gate.py`、`semantic_router.py` 3. 保留 `router/__init__.py` 导出必要的类型(如 ExecutionMode,如果前端依赖) 4. 清理 app.py 中的注释引用 5. 更新 `router/` 目录的 `__init__.py` **Test scenarios**: - 删除后 `ruff check` 无错误 - `pytest -m "not integration"` 全部通过 - 无 import 错误 **Verification**: `ruff check src/ && pytest -m "not integration" -x` --- ### U3. 专家团简化为 hub-and-spoke **Goal**: 将 ExpertTeam 从去中心化协作简化为 Lead Expert + 并行 Task 模式 **Dependencies**: 无(可与 U1/U2 并行) **Files**: - `src/agentkit/experts/orchestrator.py` — 重写为 hub-and-spoke - `src/agentkit/experts/team.py` — 简化,移除 CollaborationPlan 依赖 - `src/agentkit/experts/plan.py` — 简化,保留 MergeStrategy.BEST - `src/agentkit/core/handoff_transport.py` — 移除 ExpertTeam 专用逻辑 - `src/agentkit/core/shared_workspace.py` — 移除 ExpertTeam 专用逻辑 - `src/agentkit/experts/router.py` — 简化为 @team 前缀 + RequestPreprocessor 集成 - `tests/unit/experts/test_orchestrator.py` — 更新 **Approach**: 1. 重写 TeamOrchestrator:Lead Expert 自主规划 + 并行 spawn Task 2. 删除 CollaborationPlan 的 phase 依赖图,Lead Expert 自主决定执行顺序 3. 删除 HandoffTransport 的 Agent 间通信,Task 结果直接返回 Lead Expert 4. 删除 SharedWorkspace 的跨阶段状态共享,Lead Expert 持有所有状态 5. 保留 MergeStrategy.BEST(Lead Agent 选择最佳结果),删除 VOTE/FUSION 6. 简化 ExpertTeamRouter 为 @team 前缀触发 7. 保留 ExpertConfig/ExpertTemplate/Registry 不变 **Technical design**: ``` 新 TeamOrchestrator 流程: 1. 用户输入 → @team:xxx 前缀 → ExpertTeamMode 2. Lead Expert 接收任务,自主分解为子任务 3. 并行 spawn Task(每个 Task 是独立 ReActEngine 实例) 4. 等待所有 Task 完成 5. Lead Expert 汇总结果(BEST 策略) 6. 返回最终结果 约束: - Task 深度=1(Task 不能再 spawn Task) - Task 之间无通信 - Lead Expert 持有所有状态 ``` **Test scenarios**: - Lead Expert 正确分解任务为子任务 - 并行 Task 独立执行并返回结果 - Lead Expert 汇总结果 - 单个 Task 失败不影响其他 Task - 所有 Task 失败时回退到 Lead Expert 单独执行 - @team 前缀正确触发 ExpertTeamMode **Verification**: `ruff check src/ && pytest tests/unit/experts/ -v` --- ### U4. PlanExec 默认 ReActStepExecutor + 删除 _LLMStepExecutor **Goal**: PlanExecEngine 默认使用 ReActStepExecutor,删除 _LLMStepExecutor **Dependencies**: 无 **Files**: - `src/agentkit/core/plan_exec_engine.py` — 删除 _LLMStepExecutor 和 _LLMStepAgent,默认 step_executor_type="react" - `tests/unit/core/test_plan_exec_engine.py` — 更新 **Approach**: 1. 删除 `_LLMStepExecutor` 和 `_LLMStepAgent` 类 2. `_create_executor()` 方法移除 step_executor_type 参数,始终使用 ReActStepExecutor 3. 清理相关 import **Test scenarios**: - PlanExecEngine 默认创建 ReActStepExecutor - ReActStepExecutor 正确执行带工具调用的步骤 - 步骤失败时触发重规划 **Verification**: `ruff check src/ && pytest tests/unit/core/test_plan_exec_engine.py -v` --- ### U5. 聊天记录 SQLite 持久化 **Goal**: 使用 SQLite 持久化聊天记录,服务重启后不丢失 **Dependencies**: U1(RequestPreprocessor 重命名完成后更新调用点) **Files**: - `src/agentkit/chat/sqlite_conversation_store.py` — 新建 - `src/agentkit/server/routes/portal.py` — 替换 ConversationStore - `src/agentkit/chat/conversation_store.py` — 保留作为接口/内存实现 **Approach**: 1. 新建 `SqliteConversationStore`,实现与 `ConversationStore` 相同接口 2. SQLite 表结构:conversations(id, session_id, role, content, timestamp, metadata) 3. 支持按 session_id 查询、分页加载、搜索 4. 数据库文件路径:`~/.agentkit/conversations.db` 5. 在 portal.py 中替换 ConversationStore 为 SqliteConversationStore 6. 保留 ConversationStore 作为内存实现(测试用) **Test scenarios**: - 消息正确持久化到 SQLite - 按 session_id 查询返回完整对话 - 分页加载正确 - 服务重启后数据不丢失 - SQLite 文件不存在时自动创建 **Verification**: `ruff check src/ && pytest tests/unit/chat/test_sqlite_conversation_store.py -v` --- ### U6. 可验证执行(Test-and-Verify 循环) **Goal**: ReActEngine 执行后可选自动运行项目测试验证结果 **Dependencies**: U4 **Files**: - `src/agentkit/core/verification_loop.py` — 新建 - `src/agentkit/core/react.py` — 集成验证循环 - `src/agentkit/tools/builtin.py` — 新增 run_tests 工具 **Approach**: 1. 新建 `VerificationLoop`:执行后运行 pytest/ruff/typecheck,失败则自动重试 2. 最大重试次数可配置(默认 2) 3. 验证结果附加到 ReActResult 4. 新增 `run_tests` 内置工具,LLM 可主动调用 5. 验证循环默认关闭,通过参数 `verification_enabled=True` 启用 **Test scenarios**: - 验证循环关闭时行为不变 - 验证循环开启时,执行后自动运行测试 - 测试通过时返回成功 - 测试失败时自动重试 - 达到最大重试次数后返回失败结果 **Verification**: `ruff check src/ && pytest tests/unit/core/test_verification_loop.py -v` --- ### U7. 工具描述分层注入 + tool_search **Goal**: 核心工具全量注入,扩展工具只注入名称+一行描述,LLM 可通过 tool_search 获取完整描述 **Dependencies**: 无 **Files**: - `src/agentkit/core/react.py` — 修改 `_build_tool_use_prompt` - `src/agentkit/tools/builtin.py` — 新增 tool_search 工具 - `src/agentkit/tools/search.py` — 新建,BM25 工具搜索 **Approach**: 1. 工具分为 core(read/write/bash/search)和 extended(其余) 2. core 工具全量注入 prompt 3. extended 工具只注入 name + one-line description 4. 新增 `tool_search` 工具:BM25 搜索工具描述,返回完整描述 5. LLM 在 agent loop 中按需调用 tool_search **Test scenarios**: - core 工具全量出现在 prompt 中 - extended 工具只出现名称和一行描述 - tool_search 正确返回工具完整描述 - BM25 搜索相关性排序 **Verification**: `ruff check src/ && pytest tests/unit/tools/test_tool_search.py -v` --- ### U8. 默认启用上下文压缩 **Goal**: ReActEngine 默认启用滑动窗口压缩 **Dependencies**: 无 **Files**: - `src/agentkit/core/react.py` — 修改默认 compressor 参数 - `src/agentkit/core/compressor.py` — 确认滑动窗口实现 **Approach**: 1. ReActEngine 的 `__init__` 中 compressor 默认值从 None 改为 SlidingWindowCompressor 2. 保留最近 N 轮 + 系统提示 + 工具描述 3. N 可配置(默认 10) **Test scenarios**: - 长对话自动压缩 - 压缩后系统提示和工具描述保留 - 压缩不影响最近 N 轮对话 **Verification**: `ruff check src/ && pytest tests/unit/core/test_compressor.py -v` --- ### U9. Spec 文档作为一等公民 **Goal**: PlanExec 生成的计划持久化为 Spec 文档,用户可查看、编辑、确认后再执行 **Dependencies**: U4 **Files**: - `src/agentkit/core/spec_manager.py` — 新建 - `src/agentkit/core/plan_exec_engine.py` — 集成 SpecManager - `src/agentkit/server/routes/tasks.py` — 新增 Spec 相关 API **Approach**: 1. 新建 `SpecManager`:管理 Spec 文档的 CRUD 2. Spec 文件路径:`.agentkit/specs/.yaml` 3. PlanExecEngine 生成计划后,先持久化为 Spec 4. 新增 API:`GET /api/v1/specs`、`GET /api/v1/specs/{id}`、`PUT /api/v1/specs/{id}`、`POST /api/v1/specs/{id}/confirm` 5. 用户确认后才开始执行 **Test scenarios**: - 计划正确持久化为 Spec 文件 - Spec 文件可读取和编辑 - 未确认的 Spec 不会执行 - 确认后触发执行 **Verification**: `ruff check src/ && pytest tests/unit/core/test_spec_manager.py -v` --- ### U10. 统一事件模型(SQ/EQ 双队列) **Goal**: 统一 CLI 和 WebSocket 的事件模型为 SQ/EQ 双队列 **Dependencies**: U3 **Files**: - `src/agentkit/core/protocol.py` — 新增 SQ/EQ 事件类型 - `src/agentkit/server/routes/portal.py` — 对接 EQ - `src/agentkit/cli/chat.py` — 对接 EQ **Approach**: 1. 定义 SubmissionQueue(用户输入)和 EventQueue(Agent 输出) 2. 事件类型:Session/Task/Turn 三级模型 3. Portal WebSocket 和 CLI 共享同一事件流 4. 前端可以统一渲染 **Test scenarios**: - SQ 正确接收用户输入 - EQ 正确推送 Agent 事件 - WebSocket 和 CLI 共享事件流 - 事件类型正确分类 **Verification**: `ruff check src/ && pytest tests/unit/core/test_protocol.py -v` --- ## Scope Boundaries ### In Scope - 上述 10 个 Implementation Unit - 单元测试覆盖 ### Out of Scope - DockerComputerUseSession 实现(P3,等用户需求验证) - 前端组件更新(后续迭代) - Agent 配置热重载(P4) - 渐进式上下文加载(P4) - Soul 演变多维度触发(关闭) - OTel 埋点(延后) ### Deferred to Follow-Up Work - 前端 ExpertTeamView 接入真实数据 - SWE-bench 端到端验证 - 性能监控和成本追踪 --- ## Risks & Dependencies | Risk | Impact | Mitigation | |------|--------|------------| | U3 专家团重写可能影响现有 @team 功能 | 中 | 保留 ExpertConfig/ExpertTemplate/Registry,只重写 Orchestrator | | U5 SQLite 在高并发下可能有锁竞争 | 低 | 聊天场景写频率低,SQLite WAL 模式足够 | | U7 tool_search 可能增加 LLM 调用轮次 | 中 | 核心工具全量注入,只有扩展工具需要搜索 | | U9 Spec 文档可能增加用户操作步骤 | 低 | 默认自动确认(可配置),不阻塞自动化流程 | --- ## Phased Delivery **Phase 1(清理收尾)**: U1 → U2 → U4 → U8 **Phase 2(核心能力)**: U5 → U6 → U9 **Phase 3(多 Agent)**: U3 → U7 → U10