---
title: "feat: fischer-agentkit TDD 验证与补全计划"
type: feat
status: active
date: 2026-06-05
origin: geo/docs/plans/2026-06-04-010-refactor-unified-agent-framework-plan.md
execution_posture: tdd
---

## Summary

对 fischer-agentkit 已实现的 6 大模块进行 TDD 验证：先补全缺失的单元测试覆盖（6 个零覆盖模块 + 4 个薄弱模块），再修复测试中发现的问题（pgvector 向量检索、datetime 弃用、测试基础设施缺失），最后补全 4 个集成测试验证端到端流程。采用真实 Redis/PostgreSQL 服务进行测试，确保验证结果可靠。

## Problem Frame

fischer-agentkit 的 6 大模块（Core/Tools/Memory/Evolution/Orchestrator/MCP）代码已全部实现，189 个现有测试全部通过，但存在以下结构性问题：

1. **6 个模块完全无测试**：dispatcher、registry、mcp/server、evolution_store、agent_tool、prompts — 代码存在但行为未验证
2. **4 个模块测试薄弱**：working_memory（无 Redis mock）、episodic_memory（仅测试衰减公式）、mcp/client（仅间接测试）、handoff（仅无 Redis 场景）
3. **集成测试完全缺失**：`tests/integration/` 目录为空，无法验证端到端流程
4. **代码质量问题**：21 处 `datetime.utcnow()` 弃用警告、EpisodicMemory pgvector 向量检索标记为 TODO
5. **测试基础设施缺失**：无 conftest.py、fixture 在 4 个文件中重复定义

这些问题意味着：虽然代码"能跑"，但核心功能（任务调度、Agent 注册、MCP 服务端、进化持久化）从未被自动化测试验证过。

---

## Requirements

本计划追溯至原始需求文档的以下条目：

| 需求 ID | 需求描述 | 验证状态 |
|---------|---------|---------|
| R2 | BaseAgent 统一生命周期 | 部分验证（缺 dispatcher/registry） |
| R6 | Tool 三种类型（Function/Agent/MCP） | AgentTool 未验证 |
| R7 | ToolRegistry 注册发现版本管理 | 基本验证 |
| R8 | MCP Server 暴露 Agent 能力 | **未验证** |
| R9 | MCP Client 调用外部工具 | 仅间接验证 |
| R11 | Working Memory Redis | **未验证** |
| R12 | Episodic Memory 向量检索 | **未验证**（TODO） |
| R13 | Semantic Memory RAG+Graph | 基本验证 |
| R14 | 混合检索策略 | 部分验证 |
| R15 | 经验积累自动记录 | 部分验证 |
| R20 | Handoff 任务转交 | 仅无 Redis 场景 |
| R22 | 事件驱动替代轮询 | **未实现**（不在本计划范围） |

---

## Key Technical Decisions

KTD1. **真实服务测试策略**：单元测试和集成测试均使用真实 Redis 和 PostgreSQL（pgvector）服务，通过 docker-compose 启动测试专用容器。理由：fakeredis 不支持所有 Redis 命令（如 Pub/Sub 的完整行为），mock SQLAlchemy session 无法验证真实 SQL 和 pgvector 查询。真实服务测试更可靠，且 GEO 项目已有 pgvector/pg15 和 Redis 7 的 docker 镜像。

KTD2. **测试基础设施先行**：先创建 conftest.py 提取公共 fixture，再逐模块补全测试。理由：4 个文件重复定义 `_make_task()` 等辅助函数，不统一会导致后续测试继续重复。

KTD3. **TDD 红绿循环**：每个模块先写测试定义期望行为（可能失败），再修复代码使测试通过。对于 EpisodicMemory 的 pgvector TODO，先写测试定义向量检索的期望行为，再实现 cosine distance 排序。

KTD4. **datetime.utcnow() 统一修复**：在补全测试之前先修复 21 处弃用警告，避免新测试继承技术债务。替换为 `datetime.now(timezone.utc)`，与项目后期代码（agent_tool.py、pipeline_engine.py 等）保持一致。

KTD5. **测试风格统一为类式**：新测试统一使用 `class TestXxx` 分组 + `async def` 方法（依赖 `asyncio_mode = "auto"`），不再使用 `@pytest.mark.asyncio` 装饰器。与项目较新的测试文件风格一致。

---

## High-Level Technical Design

### 测试分层架构

```mermaid
flowchart TB
    subgraph Infrastructure["测试基础设施"]
        DC["docker-compose.test.yml<br/>Redis 7 + pgvector/pg15"]
        Conf["conftest.py<br/>公共 fixture"]
        Env[".env.test<br/>测试环境变量"]
    end

    subgraph UnitTests["单元测试 (tests/unit/)"]
        P0["P0: 零覆盖模块<br/>dispatcher, registry<br/>mcp/server, evolution_store<br/>agent_tool, prompts"]
        P1["P1: 薄弱模块<br/>working_memory, episodic_memory<br/>mcp/client, handoff"]
        Fix["代码修复<br/>datetime.utcnow, pgvector TODO"]
    end

    subgraph IntegrationTests["集成测试 (tests/integration/)"]
        AL["test_agent_lifecycle.py<br/>完整生命周期"]
        TC["test_tool_composition.py<br/>工具组合端到端"]
        EL["test_evolution_loop.py<br/>进化闭环"]
        MR["test_mcp_roundtrip.py<br/>MCP 往返"]
    end

    Infrastructure --> UnitTests
    P0 --> Fix
    P1 --> Fix
    UnitTests --> IntegrationTests
```

### 测试执行流程

```mermaid
stateDiagram-v2
    [*] --> SetupInfra: 启动测试容器
    SetupInfra --> WriteTests: 编写测试（RED）
    WriteTests --> RunTests: 运行测试
    RunTests --> FixCode: 测试失败 → 修复代码（GREEN）
    FixCode --> RunTests: 重新运行
    RunTests --> WriteTests: 全部通过 → 下一模块
    RunTests --> Integration: 单元测试全部通过
    Integration --> [*]: 集成测试通过
```

---

## Implementation Units

### U1. 测试基础设施搭建

**Goal:** 创建 docker-compose 测试配置、conftest.py 公共 fixture、.env.test 环境变量，为后续 TDD 提供可靠基础。

**Requirements:** R2, R11, R12

**Dependencies:** 无

**Files:**
- `fischer-agentkit/docker-compose.test.yml`（新建）
- `fischer-agentkit/.env.test`（新建）
- `fischer-agentkit/tests/conftest.py`（新建）
- `fischer-agentkit/tests/unit/conftest.py`（新建）
- `fischer-agentkit/tests/integration/conftest.py`（新建）
- `fischer-agentkit/pyproject.toml`（修改：添加 pytest-docker 或 testcontainers 依赖）

**Approach:**

1. 创建 `docker-compose.test.yml`，包含 Redis 7 和 pgvector/pg15 服务，端口避免与 GEO 项目冲突（Redis 6379 → 6381，PostgreSQL 5432 → 5434）
2. 创建 `.env.test` 声明测试环境变量
3. 创建 `tests/conftest.py`，提取公共 fixture：
   - `make_task()` — 构建 TaskMessage
   - `make_result()` — 构建 TaskResult
   - `redis_client` — 连接测试 Redis 的 async fixture
   - `pg_session_factory` — 连接测试 PostgreSQL 的 async fixture
   - `clean_redis` — 每个测试前清空 Redis
   - `clean_db` — 每个测试前清空数据库
4. 创建 `tests/unit/conftest.py` 和 `tests/integration/conftest.py`，分别提供各自层级的 fixture
5. 在 pyproject.toml 的 dev 依赖中添加 `pytest-docker>=0.4` 或 `testcontainers[postgres,redis]>=4.0`
6. 添加 `pytest` 配置的 `env_file = ".env.test"` 或通过 fixture 管理环境变量

**Patterns to follow:** GEO 项目的 `geo/docker-compose.yml` 中 Redis 和 PostgreSQL 的配置模式

**Test scenarios:**
- docker-compose.test.yml 启动后 Redis 可连接并执行 PING
- docker-compose.test.yml 启动后 PostgreSQL 可连接并查询 pgvector 扩展
- conftest.py 的 redis_client fixture 可正常执行 set/get 操作
- conftest.py 的 pg_session_factory fixture 可创建表并执行查询
- make_task() fixture 生成的 TaskMessage 可被 BaseAgent.execute() 接受
- clean_redis fixture 在测试间正确隔离数据

**Verification:** `docker compose -f docker-compose.test.yml up -d && pytest tests/ -v` 全部通过

---

### U2. datetime.utcnow() 弃用修复

**Goal:** 将项目中 21 处 `datetime.utcnow()` 全部替换为 `datetime.now(timezone.utc)`，消除 DeprecationWarning。

**Requirements:** 代码质量（非功能性需求）

**Dependencies:** 无（可与 U1 并行）

**Files:**
- `fischer-agentkit/src/agentkit/core/protocol.py`（7 处）
- `fischer-agentkit/src/agentkit/memory/base.py`（1 处）
- `fischer-agentkit/src/agentkit/memory/working.py`（3 处）
- `fischer-agentkit/src/agentkit/memory/episodic.py`（2 处）
- `fischer-agentkit/src/agentkit/evolution/reflector.py`（1 处）
- `fischer-agentkit/src/agentkit/evolution/lifecycle.py`（2 处）
- `fischer-agentkit/tests/unit/test_memory_system.py`（4 处）
- `fischer-agentkit/tests/unit/test_protocol.py`（1 处）

**Approach:**

1. 在每个文件的 import 区域添加 `from datetime import timezone`（如尚未导入）
2. 将 `datetime.utcnow()` 替换为 `datetime.now(timezone.utc)`
3. 将 `field(default_factory=lambda: datetime.utcnow())` 替换为 `field(default_factory=lambda: datetime.now(timezone.utc))`
4. 运行现有 189 个测试确认无回归

**Execution note:** 先运行测试确认当前基线通过，修改后重新运行确认无回归且无 DeprecationWarning。

**Patterns to follow:** 项目中已正确使用 `datetime.now(timezone.utc)` 的文件：agent_tool.py、pipeline_engine.py、registry.py、dispatcher.py、base.py

**Test scenarios:**
- 修改后 `pytest tests/ -W error::DeprecationWarning` 无弃用警告
- 修改后 189 个现有测试全部通过
- TaskMessage.from_dict() 反序列化包含 UTC 时间戳的 JSON 正确

**Verification:** `pytest tests/ -W error::DeprecationWarning -v` 全部通过，零警告

---

### U3. 零覆盖模块单元测试（Core 层）

**Goal:** 为 `core/dispatcher.py` 和 `core/registry.py` 补全单元测试，验证任务调度和 Agent 注册发现的核心逻辑。

**Requirements:** R2

**Dependencies:** U1

**Files:**
- `fischer-agentkit/tests/unit/test_dispatcher.py`（新建）
- `fischer-agentkit/tests/unit/test_registry.py`（新建）

**Approach:**

1. **test_dispatcher.py**：
   - 测试 TaskDispatcher 在本地模式（无 Redis）下的任务分发
   - 测试任务队列的 FIFO 顺序
   - 测试任务重试逻辑
   - 测试任务取消
   - 测试回调机制
   - 测试并发分发（多个任务同时入队）
2. **test_registry.py**：
   - 测试 AgentRegistry 动态注册新 AgentType
   - 测试注册重复 AgentType 的处理
   - 测试 get_available_agent 的轮询策略
   - 测试 Agent 心跳和过期清理
   - 测试按能力查询 Agent

**Execution note:** TDD — 先写测试定义期望行为，运行确认结果，再根据需要调整。

**Patterns to follow:** 现有 test_base_agent.py 的类式测试风格

**Test scenarios:**

test_dispatcher.py:
- 本地模式分发任务到指定 Agent，返回 TaskResult
- 任务队列按 FIFO 顺序处理
- 任务执行失败时重试指定次数
- 取消正在等待的任务返回取消状态
- 回调函数在任务完成后被调用
- 多个任务并发分发，结果正确返回

test_registry.py:
- 动态注册新 AgentType 不报错
- 注册重复 AgentType 覆盖旧配置
- get_available_agent 轮询策略返回不同 Agent
- Agent 心跳超时后从可用列表移除
- 按 supported_tasks 查询匹配的 Agent
- 空注册表查询返回空列表

**Verification:** `pytest tests/unit/test_dispatcher.py tests/unit/test_registry.py -v` 全部通过

---

### U4. 零覆盖模块单元测试（Tools + Prompts 层）

**Goal:** 为 `tools/agent_tool.py` 和 `prompts/` 模块补全单元测试，验证 Agent 包装为 Tool 和模板渲染的逻辑。

**Requirements:** R6

**Dependencies:** U1

**Files:**
- `fischer-agentkit/tests/unit/test_agent_tool.py`（新建）
- `fischer-agentkit/tests/unit/test_prompt_template.py`（新建）
- `fischer-agentkit/tests/unit/test_prompt_section.py`（新建）

**Approach:**

1. **test_agent_tool.py**：
   - 测试 AgentTool 的输入映射（input_mapping）
   - 测试 AgentTool 的输出映射（output_mapping）
   - 测试 AgentTool 通过 Dispatcher 分发任务
   - 测试 AgentTool 超时处理
   - 测试 AgentTool 的 schema 自动生成
2. **test_prompt_template.py**：
   - 测试 PromptTemplate 变量替换 `${key}`
   - 测试缺失变量的处理
   - 测试模板渲染结果
3. **test_prompt_section.py**：
   - 测试 PromptSection 的条件渲染
   - 测试多 Section 组合渲染

**Execution note:** TDD — AgentTool 的轮询等待机制（1 秒间隔）在测试中需要 mock asyncio.sleep 加速。

**Patterns to follow:** 现有 test_tool_composition.py 的 Mock 模式

**Test scenarios:**

test_agent_tool.py:
- AgentTool 正确映射输入参数到 TaskMessage
- AgentTool 正确映射 TaskResult 到输出 dict
- AgentTool 通过 Dispatcher 分发任务并等待结果
- AgentTool 超时后抛出 TimeoutError
- AgentTool 的 input_schema 从 input_mapping 推断
- AgentTool 的 output_schema 从 output_mapping 推断

test_prompt_template.py:
- `${name}` 变量替换为实际值
- 缺失变量时抛出 KeyError 或保留原始占位符
- 多变量模板正确替换所有变量
- 空模板渲染返回空字符串

test_prompt_section.py:
- 条件为 True 的 Section 包含在渲染结果中
- 条件为 False 的 Section 排除在渲染结果外
- 多 Section 按顺序组合渲染
- 无条件 Section 始终包含

**Verification:** `pytest tests/unit/test_agent_tool.py tests/unit/test_prompt_template.py tests/unit/test_prompt_section.py -v` 全部通过

---

### U5. 零覆盖模块单元测试（MCP Server + Evolution Store）

**Goal:** 为 `mcp/server.py` 和 `evolution/evolution_store.py` 补全单元测试，验证 MCP 服务端点和进化持久化逻辑。

**Requirements:** R8, R15

**Dependencies:** U1

**Files:**
- `fischer-agentkit/tests/unit/test_mcp_server.py`（新建）
- `fischer-agentkit/tests/unit/test_evolution_store.py`（新建）

**Approach:**

1. **test_mcp_server.py**：
   - 使用 `httpx.AsyncClient` + `ASGITransport` 测试 FastAPI 端点
   - 测试 `/tools/list` 返回 ToolRegistry 中注册的工具
   - 测试 `/tools/call` 调用指定工具并返回结果
   - 测试调用不存在的工具返回错误
   - 测试 `/resources/read` 端点
   - 测试 JSON-RPC 2.0 协议格式
2. **test_evolution_store.py**：
   - 测试 EvolutionStore 记录进化变更
   - 测试按 agent_name 查询变更历史
   - 测试回滚操作
   - 测试变更状态管理（active/rolled_back）

**Execution note:** MCP Server 测试使用 httpx.AsyncClient + ASGITransport，无需启动真实 HTTP 服务器。

**Patterns to follow:** 现有 test_mcp_transport.py 的 httpx_mock 模式；FastAPI 官方推荐的 AsyncClient 测试模式

**Test scenarios:**

test_mcp_server.py:
- `/tools/list` 返回已注册工具的名称和 schema
- `/tools/call` 调用 FunctionTool 返回正确结果
- `/tools/call` 调用不存在的工具返回 JSON-RPC 错误
- `/resources/read` 返回可用资源列表
- JSON-RPC 2.0 请求格式正确解析
- JSON-RPC 2.0 响应包含 jsonrpc/version/id 字段

test_evolution_store.py:
- 记录 prompt 类型的进化变更
- 记录 strategy 类型的进化变更
- 按 agent_name 查询返回该 Agent 的所有变更
- 回滚操作将变更状态设为 rolled_back
- 回滚后查询返回 rolled_back 状态
- 空存储查询返回空列表

**Verification:** `pytest tests/unit/test_mcp_server.py tests/unit/test_evolution_store.py -v` 全部通过

---

### U6. 薄弱模块补强测试（Memory 层）

**Goal:** 为 WorkingMemory 和 EpisodicMemory 补全真实服务测试，验证 Redis 存取和 pgvector 向量检索。实现 EpisodicMemory 的 pgvector cosine distance 排序（当前标记为 TODO）。

**Requirements:** R11, R12, R14

**Dependencies:** U1, U2

**Files:**
- `fischer-agentkit/tests/unit/test_working_memory.py`（新建）
- `fischer-agentkit/tests/unit/test_episodic_memory.py`（新建）
- `fischer-agentkit/tests/unit/test_memory_retriever.py`（新建）
- `fischer-agentkit/src/agentkit/memory/episodic.py`（修改：实现 pgvector cosine distance）

**Approach:**

1. **test_working_memory.py**（真实 Redis）：
   - 测试 store/retrieve/delete 基本操作
   - 测试 TTL 自动过期
   - 测试 get_context() 格式化输出
   - 测试不同 Agent 实例的 key 隔离
   - 测试 Redis 连接失败时的降级处理
2. **test_episodic_memory.py**（真实 pgvector）：
   - 测试 store 写入任务经验并生成 embedding
   - 测试 search 按语义相似度检索（pgvector cosine distance）
   - 测试 search 按时间衰减排序
   - 测试 search 混合排序（语义 + 时间衰减）
   - 测试 delete 删除指定记录
3. **test_memory_retriever.py**：
   - 测试三层记忆并行检索
   - 测试权重融合排序
   - 测试 Token 预算管理（截断超限结果）
4. **实现 pgvector cosine distance**：
   - 在 `episodic.py` 的 search 方法中，将 `# TODO: 使用 pgvector 的 cosine distance 排序` 替换为真实的 pgvector 查询
   - 使用 `embedding <=> :query_embedding` 操作符进行 cosine distance 排序
   - 结合时间衰减因子：最终得分 = 语义相似度 × 时间衰减

**Execution note:** TDD — 先写 EpisodicMemory 的向量检索测试（期望行为），运行确认失败（TODO 未实现），再实现 pgvector cosine distance 排序使测试通过。

**Patterns to follow:** GEO 项目的 `backend/app/services/knowledge/retriever.py` 中 HybridRetriever 的 RRF 融合排序模式

**Test scenarios:**

test_working_memory.py:
- store + retrieve 返回相同值
- TTL 过期后 retrieve 返回空
- get_context() 返回格式化的上下文字符串
- 不同 Agent 的 working_memory key 互不干扰
- delete 后 retrieve 返回空
- 存储复杂对象（嵌套 dict）正确序列化/反序列化

test_episodic_memory.py:
- store 写入记录后可按 agent_name 查询
- search 按语义相似度返回最相关记录（cosine distance）
- search 时间衰减：近期记录排名高于远期
- search 混合排序：语义相似 + 时间衰减综合排序
- delete 删除指定 ID 的记录
- 空 store 的 search 返回空列表

test_memory_retriever.py:
- 并行查询三层记忆，结果合并
- 按权重融合排序（向量 0.5 + 关键词 0.2 + 图谱 0.3）
- Token 预算管理：总 token 不超过预算时保留所有结果
- Token 预算管理：超过预算时截断低分结果
- 某层记忆无结果时不影响其他层

**Verification:** `pytest tests/unit/test_working_memory.py tests/unit/test_episodic_memory.py tests/unit/test_memory_retriever.py -v` 全部通过，且 EpisodicMemory 的 TODO 已实现

---

### U7. 薄弱模块补强测试（MCP Client + Handoff）

**Goal:** 为 MCPClient 和 HandoffManager 补全测试，验证 MCP 客户端工具发现和 Handoff 的 Redis Pub/Sub 机制。

**Requirements:** R9, R20

**Dependencies:** U1, U2

**Files:**
- `fischer-agentkit/tests/unit/test_mcp_client.py`（新建）
- `fischer-agentkit/tests/unit/test_handoff.py`（新建）

**Approach:**

1. **test_mcp_client.py**：
   - 测试 MCPClient 通过 Transport 连接远程 Server
   - 测试 list_tools() 返回工具列表
   - 测试 call_tool() 调用远程工具
   - 测试 MCPClient 直接 HTTP 模式（无 Transport）
   - 测试连接失败时的错误处理
2. **test_handoff.py**（真实 Redis）：
   - 测试 HandoffManager 通过 Redis Pub/Sub 发送转交请求
   - 测试目标 Agent 监听并接收转交消息
   - 测试转交消息携带上下文
   - 测试无 Redis 时的降级处理（本地模式）
   - 测试多个 Agent 同时监听不同频道

**Execution note:** Handoff 测试使用真实 Redis Pub/Sub，需要确保测试间频道隔离。

**Patterns to follow:** 现有 test_mcp_transport.py 的 HTTP mock 模式

**Test scenarios:**

test_mcp_client.py:
- 通过 Transport 调用 list_tools 返回工具名称列表
- 通过 Transport 调用 call_tool 返回工具执行结果
- 直接 HTTP 模式调用工具
- 连接不存在的 Server 抛出连接错误
- call_tool 传入无效参数返回错误响应
- JSON-RPC 2.0 请求格式正确

test_handoff.py:
- send_handoff 通过 Redis Pub/Sub 发送消息
- listen_for_handoffs 接收到转交消息
- 转交消息包含 source_agent、target_agent、context、reason
- 无 Redis 时 HandoffManager 降级为本地调用
- 不同 Agent 监听不同频道互不干扰
- 转交消息序列化/反序列化正确

**Verification:** `pytest tests/unit/test_mcp_client.py tests/unit/test_handoff.py -v` 全部通过

---

### U8. 集成测试补全

**Goal:** 补全 4 个集成测试文件，验证端到端流程：Agent 完整生命周期、工具组合、进化闭环、MCP 往返。

**Requirements:** R2, R6, R8, R9, R15, R16, R18, R20

**Dependencies:** U1, U3, U4, U5, U6, U7

**Files:**
- `fischer-agentkit/tests/integration/test_agent_lifecycle.py`（新建）
- `fischer-agentkit/tests/integration/test_tool_composition.py`（新建）
- `fischer-agentkit/tests/integration/test_evolution_loop.py`（新建）
- `fischer-agentkit/tests/integration/test_mcp_roundtrip.py`（新建）

**Approach:**

1. **test_agent_lifecycle.py**：
   - 启动 Agent → 发送任务 → 接收结果 → 停止 Agent 的完整流程
   - 验证 on_task_start/on_task_complete 钩子调用顺序
   - 验证任务失败时 on_task_failed 钩子触发
   - 验证 Memory 在任务执行中的存取
2. **test_tool_composition.py**：
   - SequentialChain：两个工具顺序执行，前一个输出作为后一个输入
   - ParallelFanOut：三个工具并行执行，结果合并
   - DynamicSelector：LLM 根据任务选择工具
   - AgentTool：将 Agent 包装为 Tool 并调用
3. **test_evolution_loop.py**：
   - 反思 → 优化 → A/B 测试 → 应用/回滚 完整闭环
   - 验证 EvolutionStore 持久化进化记录
   - 验证 A/B 测试效果提升后自动应用
   - 验证 A/B 测试效果下降后自动回滚
4. **test_mcp_roundtrip.py**：
   - 启动 MCP Server → MCP Client 连接 → list_tools → call_tool → 结果返回
   - 验证 Server 暴露的 Tool 与 ToolRegistry 一致
   - 验证 Client 调用的结果与直接调用 Tool 一致

**Execution note:** 集成测试使用真实 Redis 和 PostgreSQL，标记为 `@pytest.mark.integration`，可通过 `pytest -m "not integration"` 跳过。

**Patterns to follow:** 现有 test_u8_geo_integration.py 的端到端测试模式

**Test scenarios:**

test_agent_lifecycle.py:
- ConfigDrivenAgent 从 YAML 加载 → 启动 → 执行任务 → 返回 TaskResult → 停止
- BaseAgent 生命周期钩子按序调用：start → on_task_start → handle_task → on_task_complete → stop
- 任务执行失败时 on_task_failed 触发，TaskResult 状态为 FAILED
- Agent 执行任务时 WorkingMemory 自动存取上下文
- Agent 执行任务后 EpisodicMemory 自动记录经验

test_tool_composition.py:
- SequentialChain 顺序执行两个 FunctionTool，第二个接收第一个的输出
- ParallelFanOut 并行执行三个 FunctionTool，结果合并
- DynamicSelector 根据 LLM 判断选择合适工具
- AgentTool 包装 Agent 并通过 Dispatcher 分发任务

test_evolution_loop.py:
- 执行 5 次任务后 Reflector 生成反思
- PromptOptimizer 从成功案例生成 few-shot 示例
- ABTester 分流测试，实验组效果提升后自动应用
- ABTester 分流测试，实验组效果下降后自动回滚
- EvolutionStore 记录所有变更，支持查询历史

test_mcp_roundtrip.py:
- MCP Server 启动后 Client 可 list_tools
- Client call_tool 返回与直接调用 Tool 相同的结果
- Server 暴露的工具列表与 ToolRegistry 注册一致
- JSON-RPC 2.0 协议端到端正确

**Verification:** `pytest tests/integration/ -v` 全部通过

---

## Scope Boundaries

### In Scope

- 补全 6 个零覆盖模块的单元测试
- 补强 4 个薄弱模块的单元测试
- 实现 EpisodicMemory 的 pgvector cosine distance 排序（当前 TODO）
- 修复 21 处 datetime.utcnow() 弃用警告
- 创建测试基础设施（docker-compose.test.yml、conftest.py）
- 补全 4 个集成测试文件

### Deferred for Later

- MIPROv2 多目标 Prompt 优化（R16 高级特性）
- Bayesian Optimization 策略调优（R17 高级特性）
- Pipeline 事件驱动替代轮询（R22）
- MCP Client 自动发现远程工具并注册到本地 ToolRegistry（R9 高级特性）
- MCP Server SSE 流式响应（R8 高级特性）
- EvolutionMixin 与 BaseAgent 的自动集成（R15 增强）
- AgentTool 轮询改为事件驱动
- CI/CD 配置
- mypy/pyright 类型检查配置

### Outside This Project's Identity

- GEO 业务系统的完整迁移（U8）
- 前端 Agent 管理界面
- A2A Protocol 支持

---

## Risks & Dependencies

| Risk | Impact | Mitigation |
|------|--------|------------|
| pgvector cosine distance 实现可能需要调整表结构 | 需要数据库迁移 | 先写测试定义期望行为，实现时如需迁移则同步更新 docker-compose.test.yml 的 init-db 脚本 |
| 真实服务测试需要 docker 环境 | CI 环境可能无 docker | 提供 pytest marker 标记集成测试，无 docker 时可跳过；单元测试中 Redis/PG 相关测试也用 marker 标记 |
| AgentTool 轮询等待在测试中耗时 | 测试执行缓慢 | mock asyncio.sleep 加速，或设置短超时 |
| 现有测试可能因 conftest.py 重构而受影响 | fixture 命名冲突 | conftest.py 使用新 fixture 名，逐步迁移旧测试 |
| pytest-httpx 未在 pyproject.toml 中声明 | 依赖缺失 | 在 U1 中添加到 dev 依赖 |

---

## System-Wide Impact

- **测试执行时间**：从当前 ~3 秒增加到预计 ~30 秒（真实服务 + 集成测试）
- **开发依赖**：新增 pytest-docker/testcontainers、pytest-httpx
- **Docker 需求**：开发环境需安装 Docker 以运行测试
- **CI/CD**：后续需配置 GitHub Actions 运行 docker-compose 启动测试服务
