343 lines
11 KiB
Markdown
343 lines
11 KiB
Markdown
# AgentKit 框架完善计划
|
||
|
||
## 问题框架
|
||
|
||
**目标**:完善 fischer-agentkit 框架本身,修复安全性问题、补全缺失功能、提升代码质量。
|
||
|
||
**范围**:仅修改 `fischer-agentkit/` 目录下的代码。GEO 项目集成留在 GEO 开发会话中完成。
|
||
|
||
**当前状态**:
|
||
- Phase 1(U1-U8)全部实现完成,535 个单元测试通过
|
||
- 61 个文件变更未提交(在 `feat/agentkit-v2-phase1` 分支)
|
||
- 代码审查发现 19 个问题(4 P0 + 6 P1 + 9 P2/P3),已全部修复
|
||
- 1 个 TODO 待解决(pgvector 向量检索)
|
||
- README 已编写
|
||
|
||
---
|
||
|
||
## 需求追踪
|
||
|
||
来自代码审查和框架分析的问题清单:
|
||
|
||
| ID | 分类 | 描述 | 严重度 |
|
||
|----|------|------|--------|
|
||
| R1 | 安全 | pgvector 向量检索未实现 | 高 |
|
||
| R2 | 安全 | custom_handler 缺少模块前缀白名单 | 高 |
|
||
| R3 | 安全 | Server 缺少 API 认证 | 高 |
|
||
| R4 | 安全 | CORS 配置不当(allow_origins=["*"] + allow_credentials=True) | 高 |
|
||
| R5 | 安全 | 缺少速率限制 | 高 |
|
||
| R6 | 安全 | Callback URL SSRF 风险 | 高 |
|
||
| R7 | 代码质量 | registry.py 死代码 | 中 |
|
||
| R8 | 代码质量 | pipeline_engine.py 死代码 | 中 |
|
||
| R9 | 代码质量 | reflector.py error_type 提取 bug | 低 |
|
||
| R10 | 功能 | get_task_status 返回 placeholder | 中 |
|
||
| R11 | 功能 | Quality Gate/Standardization 失败静默忽略 | 中 |
|
||
| R12 | 功能 | MCP Server 未使用官方 SDK | 中 |
|
||
| R13 | 依赖 | pyproject.toml 缺少 pgvector 依赖 | 中 |
|
||
| R14 | 依赖 | pyproject.toml 缺少 fastapi/uvicorn 依赖 | 低(Phase 1 已部分修复) |
|
||
| R15 | 测试 | 18 个模块测试覆盖不足 | 中 |
|
||
|
||
---
|
||
|
||
## 关键决策
|
||
|
||
### KTD1:安全修复优先于功能补全
|
||
所有安全问题(R1-R6)必须在功能补全之前修复。框架的安全性是生产就绪的前提。
|
||
|
||
### KTD2:API 认证采用 API Key 方案
|
||
不引入 JWT/OAuth 等复杂方案。Server 模式使用 API Key 认证即可满足需求。实现方式:
|
||
- 通过环境变量 `AGENTKIT_API_KEY` 配置
|
||
- 请求头 `X-API-Key` 验证
|
||
- 健康检查端点不需要认证
|
||
|
||
### KTD3:速率限制采用固定窗口算法
|
||
不引入 Redis 滑动窗口等复杂方案。使用内存中的固定窗口计数器即可,后续可升级为 Redis 方案。
|
||
|
||
### KTD4:Callback URL SSRF 防护采用白名单方案
|
||
只允许 `http://` 和 `https://` 协议,拒绝内网 IP(127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)。
|
||
|
||
### KTD5:pgvector 向量检索在 Phase 2 实现
|
||
当前使用时间衰减排序作为降级方案是可接受的。pgvector 实现需要 PostgreSQL 扩展支持,作为独立单元实现。
|
||
|
||
### KTD6:静默失败改为结构化日志记录
|
||
quality gate 和 output standardization 的失败不应静默忽略,应记录 warning 日志并在响应中附带质量状态信息。
|
||
|
||
---
|
||
|
||
## 实现单元
|
||
|
||
### U1. 提交 Phase 1 代码并创建新分支
|
||
|
||
**目标**:将 Phase 1 的 61 个文件变更提交到 git,创建新的开发分支。
|
||
|
||
**依赖**:无
|
||
|
||
**Files**:
|
||
- 当前工作目录所有变更
|
||
|
||
**Approach**:
|
||
1. 在 `feat/agentkit-v2-phase1` 分支上提交所有变更
|
||
2. 创建新分支 `feat/agentkit-framework-hardening`
|
||
3. 后续工作在新分支上进行
|
||
|
||
**验证**:`git log -1` 显示提交,`git status` 显示干净工作树
|
||
|
||
---
|
||
|
||
### U2. 修复安全:custom_handler 模块前缀白名单
|
||
|
||
**目标**:为 `ConfigDrivenAgent._import_handler()` 添加模块前缀白名单,防止任意代码执行。
|
||
|
||
**依赖**:无
|
||
|
||
**Files**:
|
||
- `src/agentkit/core/config_driven.py`
|
||
|
||
**Approach**:
|
||
1. 在 `ConfigDrivenAgent` 类中添加 `_ALLOWED_HANDLER_PREFIXES` 常量
|
||
2. 在 `_import_handler()` 方法开头添加白名单校验
|
||
3. 白名单前缀:`"agentkit."`, `"app.agent_framework."`
|
||
|
||
**Patterns to follow**:参考 `QualityGate._import_validator()` 的白名单实现
|
||
|
||
**Test scenarios**:
|
||
- 白名单前缀的 handler 可以正常导入
|
||
- 非白名单前缀的 handler 抛出 ImportError
|
||
- 空路径、畸形路径的处理
|
||
|
||
**验证**:`pytest tests/unit/test_config_driven.py -v` 新增测试通过
|
||
|
||
---
|
||
|
||
### U3. 修复安全:CORS 配置 + API Key 认证
|
||
|
||
**目标**:修复 CORS 配置不当问题,添加 API Key 认证中间件。
|
||
|
||
**依赖**:无
|
||
|
||
**Files**:
|
||
- `src/agentkit/server/app.py`
|
||
- `src/agentkit/server/middleware.py`(新建)
|
||
|
||
**Approach**:
|
||
1. 修复 CORS:移除 `allow_credentials=True`(与 `allow_origins=["*"]` 冲突)
|
||
2. 创建 `APIKeyAuthMiddleware`:
|
||
- 从环境变量 `AGENTKIT_API_KEY` 读取密钥
|
||
- 验证请求头 `X-API-Key`
|
||
- 健康检查端点(`/api/v1/health`)不需要认证
|
||
3. 在 `create_app()` 中注册中间件
|
||
|
||
**Test scenarios**:
|
||
- 无 API Key 的请求返回 401
|
||
- 正确 API Key 的请求通过
|
||
- 健康检查端点不需要 API Key
|
||
- CORS 预检请求正常响应
|
||
|
||
**验证**:`pytest tests/unit/test_server_middleware.py -v` 新增测试通过
|
||
|
||
---
|
||
|
||
### U4. 修复安全:速率限制
|
||
|
||
**目标**:添加请求速率限制中间件,防止 LLM 成本耗尽。
|
||
|
||
**依赖**:U3(需要中间件基础设施)
|
||
|
||
**Files**:
|
||
- `src/agentkit/server/middleware.py`(修改)
|
||
|
||
**Approach**:
|
||
1. 创建 `RateLimiter` 类:固定窗口计数器,基于 IP 或 API Key 限流
|
||
2. 默认配置:每分钟 60 次请求(可配置)
|
||
3. 在 `create_app()` 中注册速率限制中间件
|
||
4. 超过限制时返回 429 Too Many Requests
|
||
|
||
**Test scenarios**:
|
||
- 请求在限制内正常通过
|
||
- 超过限制返回 429
|
||
- 时间窗口过后计数器重置
|
||
- 不同 API Key 独立计数
|
||
|
||
**验证**:`pytest tests/unit/test_rate_limiter.py -v` 新增测试通过
|
||
|
||
---
|
||
|
||
### U5. 修复安全:Callback URL SSRF 防护
|
||
|
||
**目标**:为 `TaskDispatcher._trigger_callback()` 添加 URL 验证。
|
||
|
||
**依赖**:无
|
||
|
||
**Files**:
|
||
- `src/agentkit/core/dispatcher.py`
|
||
|
||
**Approach**:
|
||
1. 创建 `_validate_callback_url(url)` 函数
|
||
2. 校验规则:
|
||
- 只允许 `http://` 和 `https://` 协议
|
||
- 拒绝内网 IP:127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
|
||
- 拒绝 localhost/127.0.0.1
|
||
3. 无效 URL 抛出 `ValueError`
|
||
|
||
**Test scenarios**:
|
||
- 合法公网 URL 通过验证
|
||
- 内网 IP 被拒绝
|
||
- localhost 被拒绝
|
||
- 非 http/https 协议被拒绝(ftp, file, etc.)
|
||
|
||
**验证**:`pytest tests/unit/test_callback_url.py -v` 新增测试通过
|
||
|
||
---
|
||
|
||
### U6. 修复代码质量:清理死代码 + Bug
|
||
|
||
**目标**:清理发现的死代码和修复 reflector.py 的 error_type 提取 bug。
|
||
|
||
**依赖**:无
|
||
|
||
**Files**:
|
||
- `src/agentkit/core/registry.py`
|
||
- `src/agentkit/orchestrator/pipeline_engine.py`
|
||
- `src/agentkit/evolution/reflector.py`
|
||
|
||
**Approach**:
|
||
1. `registry.py:51`:删除无用的 `stmt = type(db).execute.__self__.__class__` 行
|
||
2. `pipeline_engine.py:73-74`:删除不可能的条件分支 `if sr.output_data and isinstance(sr, dict): pass`
|
||
3. `reflector.py:110`:修复 `error_type` 提取逻辑,不再使用 `type(result.error_message).__name__`(永远是 "str")
|
||
|
||
**Test scenarios**:
|
||
- 清理后原有测试全部通过
|
||
- reflector.py 修复后 error_type 能正确提取错误类型
|
||
|
||
**验证**:`pytest tests/unit/ -v --ignore=tests/unit/test_working_memory.py --ignore=tests/unit/test_handoff.py` 全部通过
|
||
|
||
---
|
||
|
||
### U7. 修复功能:get_task_status 实现 + 静默失败日志化
|
||
|
||
**目标**:实现真正的任务状态查询,将静默失败改为结构化日志记录。
|
||
|
||
**依赖**:无
|
||
|
||
**Files**:
|
||
- `src/agentkit/server/routes/tasks.py`
|
||
|
||
**Approach**:
|
||
1. `get_task_status` 端点:添加简单的任务状态追踪(内存字典或 Redis)
|
||
2. Quality Gate 失败:记录 warning 日志,在响应中附带 `quality_status: "skipped"` 字段
|
||
3. Output Standardization 失败:记录 warning 日志,在响应中附带 `standardization_status: "skipped"` 字段
|
||
|
||
**Test scenarios**:
|
||
- 提交任务后能查询到任务状态
|
||
- Quality Gate 失败时响应包含 quality_status 字段
|
||
- Standardization 失败时响应包含 standardization_status 字段
|
||
- 日志中包含失败原因
|
||
|
||
**验证**:`pytest tests/unit/test_server_routes.py -v` 更新后的测试通过
|
||
|
||
---
|
||
|
||
### U8. 修复功能:pgvector 向量检索实现
|
||
|
||
**目标**:实现 EpisodicMemory 的 pgvector 语义搜索。
|
||
|
||
**依赖**:无(需要 PostgreSQL 实例运行)
|
||
|
||
**Files**:
|
||
- `src/agentkit/memory/episodic.py`
|
||
- `pyproject.toml`
|
||
|
||
**Approach**:
|
||
1. 添加 `pgvector` 到 `pyproject.toml` 依赖
|
||
2. 修改 `EpisodicMemory.search()` 方法:
|
||
- 如果有 `_embedder` 且安装了 pgvector,使用 `embedding.cosine_distance(query_embedding)` 排序
|
||
- 否则回退到时间衰减排序
|
||
3. 添加迁移或建表语句(如果需要 vector 类型列)
|
||
|
||
**Test scenarios**:
|
||
- 有 pgvector 时按余弦距离排序返回结果
|
||
- 无 pgvector 时回退到时间衰减排序
|
||
- 空查询返回空列表
|
||
|
||
**验证**:`pytest tests/unit/test_episodic_memory.py -v` 更新后的测试通过
|
||
|
||
---
|
||
|
||
### U9. 修复依赖:完善 pyproject.toml
|
||
|
||
**目标**:确保所有运行时依赖正确声明。
|
||
|
||
**依赖**:U8(pgvector 依赖)
|
||
|
||
**Files**:
|
||
- `pyproject.toml`
|
||
|
||
**Approach**:
|
||
1. 添加 `pgvector>=0.2` 到 dependencies(episodic memory 需要)
|
||
2. 确认 `fastapi>=0.110`, `uvicorn>=0.27` 在 optional-dependencies.server 中(Phase 1 已添加)
|
||
3. 确认 `mcp>=1.0` 与实际使用一致(如果使用官方 SDK)
|
||
|
||
**验证**:`pip install -e ".[server]"` 成功安装所有依赖
|
||
|
||
---
|
||
|
||
### U10. 补充测试覆盖(可选)
|
||
|
||
**目标**:为测试覆盖不足的模块添加测试。
|
||
|
||
**依赖**:U1-U9 全部完成
|
||
|
||
**Files**:
|
||
- `tests/unit/test_registry.py`(扩展现有)
|
||
- `tests/unit/test_dispatcher.py`(扩展现有)
|
||
- `tests/unit/test_pipeline_engine.py`(新建)
|
||
- `tests/unit/test_handoff.py`(扩展现有)
|
||
- `tests/unit/test_mcp_*.py`(扩展现有)
|
||
|
||
**Approach**:
|
||
- 每个模块添加 5-10 个核心测试用例
|
||
- 优先覆盖 happy path 和错误路径
|
||
- 集成测试需要真实 Redis/PostgreSQL 的可以标记为 skip
|
||
|
||
**验证**:总测试数达到 600+,覆盖率提升到 80%+
|
||
|
||
---
|
||
|
||
## 执行顺序
|
||
|
||
```
|
||
U1(提交代码) → U2(白名单) → U3(CORS + 认证) → U4(速率限制)
|
||
↓
|
||
U6(死代码清理) → U7(任务状态 + 日志) → U8(pgvector) → U9(依赖完善)
|
||
↓
|
||
U10(补充测试,可选)
|
||
```
|
||
|
||
**并发性**:
|
||
- U2, U6, U7 可以并行执行(无依赖)
|
||
- U3 和 U4 有依赖关系(U3 先于 U4)
|
||
- U5 独立,可与任何单元并行
|
||
- U8 和 U9 有依赖关系(U9 需要 U8 的 pgvector 信息)
|
||
|
||
## 风险与缓解
|
||
|
||
| 风险 | 影响 | 缓解 |
|
||
|------|------|------|
|
||
| pgvector 需要 PostgreSQL 扩展 | 测试环境可能没有 pgvector | 使用 skip 标记,提供降级方案 |
|
||
| API Key 认证破坏现有测试 | 测试需要传递 API Key | 测试环境设置环境变量 |
|
||
| 速率限制影响 E2E 测试 | 测试可能被限流 | 测试环境提高限制或使用 mock |
|
||
|
||
## 范围边界
|
||
|
||
**本计划包含**:
|
||
- AgentKit 框架本身的安全修复
|
||
- 代码质量清理
|
||
- 缺失功能补全
|
||
- 依赖完善
|
||
|
||
**本计划不包含**:
|
||
- GEO 项目的任何改动(留在 GEO 开发会话中完成)
|
||
- 新的 Agent 类型或 Skill 类型
|
||
- 前端 UI 开发
|
||
- 生产环境部署配置(K8s、监控等)
|