fischer-agentkit/docs/plans/2026-06-16-006-refactor-arc...

430 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

```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 重命名为 RequestPreprocessorroute() 方法重命名为 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 CodeTask 工具深度=1子 Agent 不能再生子 Agent
- Codexspawn_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 ModeSpec 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. 重写 TeamOrchestratorLead Expert 自主规划 + 并行 spawn Task
2. 删除 CollaborationPlan 的 phase 依赖图Lead Expert 自主决定执行顺序
3. 删除 HandoffTransport 的 Agent 间通信Task 结果直接返回 Lead Expert
4. 删除 SharedWorkspace 的跨阶段状态共享Lead Expert 持有所有状态
5. 保留 MergeStrategy.BESTLead 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 深度=1Task 不能再 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**: U1RequestPreprocessor 重命名完成后更新调用点)
**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. 工具分为 coreread/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/<plan_id>.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用户输入和 EventQueueAgent 输出)
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