docs(agent-runtime): 补充 SessionMemory 设计与多 context 切换备忘
- 在方案文档中新增 `SessionMemory` 作为会话级记忆桥接组件 - 将 AgentSession 的 `agent_name: String` 改为 `agent: Arc<dyn Agent>` - RuntimeBundle 新增 `session_memory_backend` 可选字段 - 新增 `docs/note-context-switch-design.md` 记录多 context 切换方案 - 更新 Roadmap 状态并补充 Phase 4 范围界定 - Phase 4 仅实现 SessionMemory 数据结构与 API,ContextManager 延后至 v0.2+
This commit is contained in:
+123
-34
@@ -27,6 +27,7 @@ Phase 4 目标是提供一个**薄胶水层 + 一组 trait 抽象**,让上层
|
|||||||
- **`AgentSession` struct** — 智能体的"会话"实例(绑定 session_id + 状态)
|
- **`AgentSession` struct** — 智能体的"会话"实例(绑定 session_id + 状态)
|
||||||
- **`TaskAgent` trait** — 任务型智能体的"规划/执行"抽象
|
- **`TaskAgent` trait** — 任务型智能体的"规划/执行"抽象
|
||||||
- **`RuntimeBundle`** — 显式依赖注入容器,集中管理 provider/registry/hook/memory 等依赖
|
- **`RuntimeBundle`** — 显式依赖注入容器,集中管理 provider/registry/hook/memory 等依赖
|
||||||
|
- **`SessionMemory`** — 会话级记忆,用于 context 间的信息桥接(基于 `MemoryStore` 后端)
|
||||||
- **`AgentBuilder`** — 链式构造入口
|
- **`AgentBuilder`** — 链式构造入口
|
||||||
- **`AgentError`** — 统一错误类型,聚合 LlmError / ToolError / MemoryError
|
- **`AgentError`** — 统一错误类型,聚合 LlmError / ToolError / MemoryError
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ Phase 4 严格遵循以下原则,所有范围决策都基于这些原则推导
|
|||||||
| **实体/会话分离** | 同一角色可被多 session 复用 | `Agent` + `AgentSession` 两层模型 |
|
| **实体/会话分离** | 同一角色可被多 session 复用 | `Agent` + `AgentSession` 两层模型 |
|
||||||
| **记忆弱引用** | 记忆是"被动能力",不内嵌循环 | `memory_store: Option<Arc<dyn MemoryStore>>` 弱引用 |
|
| **记忆弱引用** | 记忆是"被动能力",不内嵌循环 | `memory_store: Option<Arc<dyn MemoryStore>>` 弱引用 |
|
||||||
| **业务可注入** | Plan 拆解是业务能力,不在 core 库实现 | 暴露 `PlanParser` trait,上层注入 |
|
| **业务可注入** | Plan 拆解是业务能力,不在 core 库实现 | 暴露 `PlanParser` trait,上层注入 |
|
||||||
|
| **会话级记忆** | session 内共享、context 间桥接,不是持久层也不是对话历史 | `SessionMemory` 基于 `MemoryStore`,按 session_id 命名空间隔离 |
|
||||||
| **借鉴不照搬** | 4 个参考项目均非 Rust 实现 | 只取架构模式,不抄实现细节 |
|
| **借鉴不照搬** | 4 个参考项目均非 Rust 实现 | 只取架构模式,不抄实现细节 |
|
||||||
|
|
||||||
### 1.4 与已完成的 Phase 关系
|
### 1.4 与已完成的 Phase 关系
|
||||||
@@ -190,6 +192,7 @@ pub struct RuntimeBundle {
|
|||||||
pub hook_executor: Arc<HookExecutor>,
|
pub hook_executor: Arc<HookExecutor>,
|
||||||
pub memory_store: Option<Arc<dyn MemoryStore>>, // 弱引用
|
pub memory_store: Option<Arc<dyn MemoryStore>>, // 弱引用
|
||||||
pub retriever: Option<Arc<MemoryRetriever>>, // 弱引用
|
pub retriever: Option<Arc<MemoryRetriever>>, // 弱引用
|
||||||
|
pub session_memory_backend: Option<Arc<dyn MemoryStore>>, // SessionMemory 后端(选填)
|
||||||
pub config: AgentConfig,
|
pub config: AgentConfig,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -198,6 +201,7 @@ pub struct RuntimeBundle {
|
|||||||
- 所有运行时依赖**显式打包**(OpenHarness 风格)
|
- 所有运行时依赖**显式打包**(OpenHarness 风格)
|
||||||
- `memory_store` / `retriever` 均为 `Option`——上层应用**不传也能跑**(无记忆模式)
|
- `memory_store` / `retriever` 均为 `Option`——上层应用**不传也能跑**(无记忆模式)
|
||||||
- 当 `retriever` 存在时,`RuntimeBundle::new()` 内部自动注册一个名为 `"retrieve"` 的 tool(具体实现:在 `ToolRegistry` 里加一个 `RetrieveTool` 包装),让 LLM 在对话中**主动**调用检索能力
|
- 当 `retriever` 存在时,`RuntimeBundle::new()` 内部自动注册一个名为 `"retrieve"` 的 tool(具体实现:在 `ToolRegistry` 里加一个 `RetrieveTool` 包装),让 LLM 在对话中**主动**调用检索能力
|
||||||
|
- `session_memory_backend` 是 `SessionMemory` 的持久后端。传入时 `SessionMemory` 使用该后端(支持跨进程共享);不传时 `AgentSession` 内部自动创建 `InMemoryStore` 作为进程级隔离的后端
|
||||||
- `config` 集中管理所有可调参数(max_turns、max_tool_turns、session_ttl、compact_config)
|
- `config` 集中管理所有可调参数(max_turns、max_tool_turns、session_ttl、compact_config)
|
||||||
|
|
||||||
#### 3.2.3 `AgentSession` 与最小 reference impl
|
#### 3.2.3 `AgentSession` 与最小 reference impl
|
||||||
@@ -205,10 +209,11 @@ pub struct RuntimeBundle {
|
|||||||
```rust
|
```rust
|
||||||
pub struct AgentSession {
|
pub struct AgentSession {
|
||||||
pub session_id: String,
|
pub session_id: String,
|
||||||
pub agent_name: String,
|
pub agent: Arc<dyn Agent>,
|
||||||
bundle: Arc<RuntimeBundle>,
|
bundle: Arc<RuntimeBundle>,
|
||||||
turn_index: u32,
|
turn_index: u32,
|
||||||
cost_so_far: CostTracker,
|
cost_so_far: CostTracker,
|
||||||
|
session_memory: SessionMemory,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AgentSession {
|
impl AgentSession {
|
||||||
@@ -229,6 +234,8 @@ impl AgentSession {
|
|||||||
```
|
```
|
||||||
|
|
||||||
**设计意图**:
|
**设计意图**:
|
||||||
|
- `agent: Arc<dyn Agent>` 而非 `agent_name: String`——`submit_turn` 从 agent 获取 `system_prompt()` 和 `tool_definitions()`,同时为 v0.2+ 的"热切换 agent"预留:替换 `self.agent` 即可切换角色
|
||||||
|
- `session_memory` 是进程内共享的会话级记忆,context 间通过它桥接信息(详见 §3.2.8)
|
||||||
- "最小 reference impl" 只演示**最常见**的对话场景
|
- "最小 reference impl" 只演示**最常见**的对话场景
|
||||||
- 业务循环(多轮策略、错误重试、记忆回写时机)由上层应用或具体的 `TaskAgent` 实现决定
|
- 业务循环(多轮策略、错误重试、记忆回写时机)由上层应用或具体的 `TaskAgent` 实现决定
|
||||||
- `submit_turn` 不持有 `ConversationMemory`——上层应用可独立 new 一个 `ConversationMemory`,在合适的时机(如 OnTurnEnd hook)调 `add_message`
|
- `submit_turn` 不持有 `ConversationMemory`——上层应用可独立 new 一个 `ConversationMemory`,在合适的时机(如 OnTurnEnd hook)调 `add_message`
|
||||||
@@ -324,6 +331,7 @@ impl AgentBuilder {
|
|||||||
pub fn hook_executor(self, h: Arc<HookExecutor>) -> Self;
|
pub fn hook_executor(self, h: Arc<HookExecutor>) -> Self;
|
||||||
pub fn memory_store(self, m: Arc<dyn MemoryStore>) -> Self; // 选填
|
pub fn memory_store(self, m: Arc<dyn MemoryStore>) -> Self; // 选填
|
||||||
pub fn retriever(self, r: Arc<MemoryRetriever>) -> Self; // 选填
|
pub fn retriever(self, r: Arc<MemoryRetriever>) -> Self; // 选填
|
||||||
|
pub fn session_memory_backend(self, s: Arc<dyn MemoryStore>) -> Self; // 选填
|
||||||
pub fn config(self, c: AgentConfig) -> Self;
|
pub fn config(self, c: AgentConfig) -> Self;
|
||||||
pub fn build(self) -> Result<RuntimeBundle, AgentError>;
|
pub fn build(self) -> Result<RuntimeBundle, AgentError>;
|
||||||
}
|
}
|
||||||
@@ -332,7 +340,74 @@ impl AgentBuilder {
|
|||||||
**设计意图**:
|
**设计意图**:
|
||||||
- `AgentBuilder` 是**唯一**的 `RuntimeBundle` 构造入口
|
- `AgentBuilder` 是**唯一**的 `RuntimeBundle` 构造入口
|
||||||
- 必填字段在 `build()` 时校验(`provider` / `tool_registry` / `hook_executor` 不可缺)
|
- 必填字段在 `build()` 时校验(`provider` / `tool_registry` / `hook_executor` 不可缺)
|
||||||
- `memory_store` / `retriever` 选填,对应 §3.2.2 的"无记忆模式"
|
- `memory_store` / `retriever` / `session_memory_backend` 选填
|
||||||
|
- `session_memory_backend` 不传时,`AgentSession` 内部用 `InMemoryStore` 兜底(进程级隔离)
|
||||||
|
|
||||||
|
#### 3.2.8 `SessionMemory` — 会话级记忆
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct SessionMemory {
|
||||||
|
store: Arc<dyn MemoryStore>,
|
||||||
|
namespace: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionMemory {
|
||||||
|
/// 创建新的 session 级记忆实例。
|
||||||
|
/// store:后端存储(可跨进程共享的 MemoryStore 实现)。
|
||||||
|
/// namespace:按 session_id 隔离,防止跨 session 泄漏。
|
||||||
|
pub fn new(store: Arc<dyn MemoryStore>, namespace: &str) -> Self;
|
||||||
|
|
||||||
|
/// 写入一条 key-value 条目。
|
||||||
|
pub async fn set(&self, key: &str, value: &str) -> Result<(), AgentError>;
|
||||||
|
|
||||||
|
/// 读取指定 key 的值。
|
||||||
|
pub async fn get(&self, key: &str) -> Result<Option<String>, AgentError>;
|
||||||
|
|
||||||
|
/// 返回所有条目的格式化快照,适合注入 system prompt。
|
||||||
|
/// 格式:
|
||||||
|
/// <session-context>
|
||||||
|
/// key1: value1
|
||||||
|
/// key2: value2
|
||||||
|
/// </session-context>
|
||||||
|
pub async fn snapshot(&self) -> Result<String, AgentError>;
|
||||||
|
|
||||||
|
/// 删除指定 key。
|
||||||
|
pub async fn remove(&self, key: &str) -> Result<(), AgentError>;
|
||||||
|
|
||||||
|
/// 清空当前 namespace 下所有条目。
|
||||||
|
pub async fn clear(&self) -> Result<(), AgentError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**设计意图**:
|
||||||
|
- `SessionMemory` 是**会话级**记忆,不是持久层(`MemoryStore`)也不是对话历史(`ConversationMemory`)——它的定位是 session 内各 context 之间的信息桥接
|
||||||
|
- **复用 Phase 3 `MemoryStore` trait**:不引入新的存储后端机制。单进程场景用 `InMemoryStore`(零序列化开销),跨进程场景换 Redis / SQLite 等实现即可
|
||||||
|
- **按 `namespace` 隔离**:每个 session 一个独立命名空间(`"_session_{session_id}"`),避免跨 session 意外泄漏
|
||||||
|
- **`snapshot()` 格式化为标记文本**:专为注入 system prompt 设计,LLM 可以自然理解 `<session-context>` 标签中的内容
|
||||||
|
- **所有方法为 `async`**:因为后端可能是跨进程的(Redis / DB),虽然 `InMemoryStore` 本身是同步操作
|
||||||
|
- **不引入自己的错误类型**:错误通过 `AgentError::Memory` 传播(复用已有变体)
|
||||||
|
|
||||||
|
**三层记忆体系关系**:
|
||||||
|
|
||||||
|
```
|
||||||
|
持久层(Phase 3) MemoryStore / KnowledgeStore ── 跨 session 持久,长期知识
|
||||||
|
会话层(新增) SessionMemory ── 单 session 内共享,context 桥接
|
||||||
|
对话层(Phase 3) ConversationMemory ── 单 context 内消息历史
|
||||||
|
```
|
||||||
|
|
||||||
|
**典型使用模式**(v0.2+ context 切换场景):
|
||||||
|
|
||||||
|
```
|
||||||
|
context_a (build agent)
|
||||||
|
→ 在对话中决定某个关键结论值得记下来
|
||||||
|
→ 调用 session_memory.set("design_decision", "用 PostgreSQL")
|
||||||
|
→ 继续对话
|
||||||
|
|
||||||
|
创建 context_b (plan agent)
|
||||||
|
→ system_prompt 末尾追加 session_memory.snapshot()
|
||||||
|
→ LLM 看到 "<session-context>\ndesign_decision: 用 PostgreSQL\n</session-context>"
|
||||||
|
→ 无需看 context_a 的 50 轮完整历史,但知道关键上下文
|
||||||
|
```
|
||||||
|
|
||||||
### 3.3 状态机
|
### 3.3 状态机
|
||||||
|
|
||||||
@@ -440,24 +515,28 @@ pub struct HookContext {
|
|||||||
| `JsonPlanParser::parse` | `serde_json::from_str` | task.rs |
|
| `JsonPlanParser::parse` | `serde_json::from_str` | task.rs |
|
||||||
| `AgentError::from` | `LlmError` / `ToolError` / `MemoryError` | error.rs |
|
| `AgentError::from` | `LlmError` / `ToolError` / `MemoryError` | error.rs |
|
||||||
| `HookContext` 扩展 | `HookEvent::OnTurnStart/End/OnPlanStepComplete` | llm/hooks.rs |
|
| `HookContext` 扩展 | `HookEvent::OnTurnStart/End/OnPlanStepComplete` | llm/hooks.rs |
|
||||||
|
| `SessionMemory::set/get/snapshot` | `MemoryStore::save/load/search` | session_memory.rs |
|
||||||
|
|
||||||
**不调用的下层 API**(明确边界):
|
**不调用的下层 API**(明确边界):
|
||||||
- ❌ `ConversationMemory`(由上层独立 task 管理)
|
- ❌ `ConversationMemory`(由上层独立 task 管理)
|
||||||
- ❌ `KnowledgeStore`(由上层独立 task 管理)
|
- ❌ `KnowledgeStore`(由上层独立 task 管理)
|
||||||
- ❌ `McpClient`(已由 `ToolRegistry` 包装)
|
- ❌ `McpClient`(已由 `ToolRegistry` 包装)
|
||||||
- ❌ `StreamEvents::submit_stream`(v1 暂不暴露流式 `submit_turn`,v0.2 再说)
|
- ❌ `StreamEvents::submit_stream`(v1 暂不暴露流式 `submit_turn`,v0.2 再说)
|
||||||
|
- ❌ 多 context 切换管理(v0.2+ 实现,Phase 4 只预留 `SessionMemory` 桥接通道)
|
||||||
|
- ❌ `"session_memory_set"` 等 session memory tool 自动注册(v0.2+ 可选)
|
||||||
|
|
||||||
## 4. 实施计划
|
## 4. 实施计划
|
||||||
|
|
||||||
### 4.1 文件清单
|
### 4.1 文件清单
|
||||||
|
|
||||||
#### 新增文件(7 个)
|
#### 新增文件(8 个)
|
||||||
|
|
||||||
```
|
```
|
||||||
src/agent.rs # 模块根 + pub use 重导出
|
src/agent.rs # 模块根 + pub use 重导出
|
||||||
src/agent/agent.rs # Agent trait
|
src/agent/agent.rs # Agent trait
|
||||||
src/agent/runtime.rs # RuntimeBundle + AgentConfig
|
src/agent/runtime.rs # RuntimeBundle + AgentConfig
|
||||||
src/agent/session.rs # AgentSession(含 submit_turn reference impl)
|
src/agent/session.rs # AgentSession(含 submit_turn reference impl)
|
||||||
|
src/agent/session_memory.rs # SessionMemory(会话级记忆,基于 MemoryStore)
|
||||||
src/agent/task.rs # TaskAgent trait + Plan/Step + PlanParser + JsonPlanParser
|
src/agent/task.rs # TaskAgent trait + Plan/Step + PlanParser + JsonPlanParser
|
||||||
src/agent/builder.rs # AgentBuilder
|
src/agent/builder.rs # AgentBuilder
|
||||||
src/agent/error.rs # AgentError
|
src/agent/error.rs # AgentError
|
||||||
@@ -486,15 +565,16 @@ docs/7-agent-runtime.md # ✅ 本文件
|
|||||||
| 1 | 修改 `llm/hooks.rs` 追加 3 个事件 + 2 个字段 | `src/llm/hooks.rs` | `cargo build` 通过;现有测试不挂 |
|
| 1 | 修改 `llm/hooks.rs` 追加 3 个事件 + 2 个字段 | `src/llm/hooks.rs` | `cargo build` 通过;现有测试不挂 |
|
||||||
| 2 | 新建 `agent/error.rs` 定义 `AgentError` | `src/agent/error.rs` | `cargo build` 通过 |
|
| 2 | 新建 `agent/error.rs` 定义 `AgentError` | `src/agent/error.rs` | `cargo build` 通过 |
|
||||||
| 3 | 新建 `agent/agent.rs` 定义 `Agent` trait | `src/agent/agent.rs` | `cargo build` 通过 |
|
| 3 | 新建 `agent/agent.rs` 定义 `Agent` trait | `src/agent/agent.rs` | `cargo build` 通过 |
|
||||||
| 4 | 新建 `agent/runtime.rs` 定义 `RuntimeBundle` + `AgentConfig` | `src/agent/runtime.rs` | `cargo build` 通过 |
|
| 4 | 新建 `agent/runtime.rs` 定义 `RuntimeBundle` + `AgentConfig`(含 `session_memory_backend` 字段) | `src/agent/runtime.rs` | `cargo build` 通过 |
|
||||||
| 5 | 新建 `agent/builder.rs` 定义 `AgentBuilder` | `src/agent/builder.rs` | `cargo build` 通过 |
|
| 5 | 新建 `agent/session_memory.rs` 定义 `SessionMemory` | `src/agent/session_memory.rs` | `cargo build` 通过 |
|
||||||
| 6 | 新建 `agent/session.rs` 定义 `AgentSession` + `submit_turn` | `src/agent/session.rs` | `cargo build` 通过 |
|
| 6 | 新建 `agent/builder.rs` 定义 `AgentBuilder`(含 `.session_memory_backend()` 方法) | `src/agent/builder.rs` | `cargo build` 通过 |
|
||||||
| 7 | 新建 `agent/task.rs` 定义 `TaskAgent` + `Plan` / `Step` / `PlanParser` / `JsonPlanParser` | `src/agent/task.rs` | `cargo build` 通过 |
|
| 7 | 新建 `agent/session.rs` 定义 `AgentSession` + `submit_turn`(持 `Arc<dyn Agent>` + `SessionMemory`) | `src/agent/session.rs` | `cargo build` 通过 |
|
||||||
| 8 | 新建 `src/agent.rs` 模块根 + `pub use` 重导出 | `src/agent.rs` | `cargo build` 通过 |
|
| 8 | 新建 `agent/task.rs` 定义 `TaskAgent` + `Plan` / `Step` / `PlanParser` / `JsonPlanParser` | `src/agent/task.rs` | `cargo build` 通过 |
|
||||||
| 9 | 修改 `lib.rs` 导出 `pub mod agent;` | `src/lib.rs` | `cargo build` 通过 |
|
| 9 | 新建 `src/agent.rs` 模块根 + `pub use` 重导出 | `src/agent.rs` | `cargo build` 通过 |
|
||||||
| 10 | 编写 2-3 个烟雾测试 | `src/agent/*.rs` 内联 | `cargo test` 通过 |
|
| 10 | 修改 `lib.rs` 导出 `pub mod agent;` | `src/lib.rs` | `cargo build` 通过 |
|
||||||
| 11 | 更新 `roadmap.md` 状态翻转 | `docs/roadmap.md` | 文档 review |
|
| 11 | 编写 3-4 个烟雾测试(含 SessionMemory) | `src/agent/*.rs` 内联 | `cargo test` 通过 |
|
||||||
| 12 | 完整 `cargo test` 跑全量回归 | — | 所有已有测试不挂 |
|
| 12 | 更新 `roadmap.md` 状态翻转 | `docs/roadmap.md` | 文档 review |
|
||||||
|
| 13 | 完整 `cargo test` 跑全量回归 | — | 所有已有测试不挂 |
|
||||||
|
|
||||||
### 4.3 依赖关系
|
### 4.3 依赖关系
|
||||||
|
|
||||||
@@ -504,30 +584,33 @@ hooks.rs (1) ──┐
|
|||||||
│ │
|
│ │
|
||||||
│ ▼
|
│ ▼
|
||||||
│ agent/runtime.rs (4)
|
│ agent/runtime.rs (4)
|
||||||
|
│ │ │
|
||||||
|
│ │ ▼
|
||||||
|
│ │ agent/session_memory.rs (5)
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ agent/builder.rs (6)
|
||||||
│ │
|
│ │
|
||||||
│ ▼
|
│ ▼
|
||||||
│ agent/builder.rs (5)
|
│ agent/session.rs (7)
|
||||||
│ │
|
│ │
|
||||||
│ ▼
|
│ ▼
|
||||||
│ agent/session.rs (6)
|
└─────────────────► agent/task.rs (8)
|
||||||
│ │
|
|
||||||
│ ▼
|
|
||||||
└─────────────────► agent/task.rs (7)
|
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
src/agent.rs (8)
|
src/agent.rs (9)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
src/lib.rs (9)
|
src/lib.rs (10)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
cargo test (10)
|
cargo test (11)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
roadmap.md (11)
|
roadmap.md (12)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
回归 (12)
|
回归 (13)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4.4 预估工作量
|
### 4.4 预估工作量
|
||||||
@@ -535,11 +618,11 @@ hooks.rs (1) ──┐
|
|||||||
| 阶段 | 行数 | 说明 |
|
| 阶段 | 行数 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| 1(hooks 扩展) | ~15 | 3 个变体 + 2 个字段 + 文档 |
|
| 1(hooks 扩展) | ~15 | 3 个变体 + 2 个字段 + 文档 |
|
||||||
| 2-7(7 个 agent 文件) | ~600 | 含 import + trait + struct + impl + 文档 |
|
| 2-8(8 个 agent 文件) | ~640 | 含 import + trait + struct + impl + 文档(+ session_memory.rs ~40 行) |
|
||||||
| 8-9(lib.rs + agent.rs 模块根) | ~20 | 主要是 pub use 重导出 |
|
| 9-10(lib.rs + agent.rs 模块根) | ~20 | 主要是 pub use 重导出 |
|
||||||
| 10(烟雾测试) | ~100 | 2-3 个测试 |
|
| 11(烟雾测试) | ~120 | 3-4 个测试(含 SessionMemory) |
|
||||||
| 11(roadmap 同步) | ~5 | 状态翻转一行 |
|
| 12(roadmap 同步) | ~5 | 状态翻转一行 |
|
||||||
| **合计** | **~740** | 与 `note-agent-runtime-design.md` §6 预估一致 |
|
| **合计** | **~800** | 从 ~740 增加 ~60 行(SessionMemory ~40 + 测试 ~20) |
|
||||||
|
|
||||||
## 5. 风险评估
|
## 5. 风险评估
|
||||||
|
|
||||||
@@ -595,30 +678,34 @@ hooks.rs (1) ──┐
|
|||||||
- [ ] `cargo build --release` 0 错误 0 警告(clippy)
|
- [ ] `cargo build --release` 0 错误 0 警告(clippy)
|
||||||
- [ ] `cargo test` 所有 Phase 0-3 已有测试 + Phase 4 新增测试全部通过
|
- [ ] `cargo test` 所有 Phase 0-3 已有测试 + Phase 4 新增测试全部通过
|
||||||
- [ ] `cargo doc --no-deps` 所有公开 API 有 `///` 文档注释
|
- [ ] `cargo doc --no-deps` 所有公开 API 有 `///` 文档注释
|
||||||
- [ ] 新增代码 700-750 行(含测试 + 文档注释),与 §4.4 预估一致
|
- [ ] 新增代码 750-850 行(含测试 + 文档注释),与 §4.4 预估一致
|
||||||
- [ ] `src/lib.rs` 新增一行 `pub mod agent;`
|
- [ ] `src/lib.rs` 新增一行 `pub mod agent;`
|
||||||
- [ ] `src/llm/hooks.rs` 仅追加(不修改现有变体或字段)
|
- [ ] `src/llm/hooks.rs` 仅追加(不修改现有变体或字段)
|
||||||
|
|
||||||
### 6.2 接口验收
|
### 6.2 接口验收
|
||||||
|
|
||||||
- [ ] 7 个新文件全部存在(§4.1)
|
- [ ] 8 个新文件全部存在(§4.1)
|
||||||
- [ ] `Agent` trait 包含 `name` / `system_prompt` / `tool_definitions` 三个方法
|
- [ ] `Agent` trait 包含 `name` / `system_prompt` / `tool_definitions` 三个方法
|
||||||
- [ ] `RuntimeBundle` 包含 6 个字段(provider / tool_registry / hook_executor / memory_store? / retriever? / config)
|
- [ ] `RuntimeBundle` 包含 7 个字段(provider / tool_registry / hook_executor / memory_store? / retriever? / session_memory_backend? / config)
|
||||||
|
- [ ] `AgentSession` 持 `Arc<dyn Agent>` 而非 `agent_name: String`,含 `session_memory: SessionMemory` 字段
|
||||||
- [ ] `AgentSession::submit_turn` 实现约 30 行,含 OnTurnStart/End hook 触发
|
- [ ] `AgentSession::submit_turn` 实现约 30 行,含 OnTurnStart/End hook 触发
|
||||||
|
- [ ] `SessionMemory` 包含 5 个方法(set / get / snapshot / remove / clear),基于 `MemoryStore` 实现
|
||||||
|
- [ ] `SessionMemory::snapshot` 返回 `<session-context>` 标签包裹的格式化文本
|
||||||
- [ ] `TaskAgent` 提供双入口 `run` + `execute_plan`
|
- [ ] `TaskAgent` 提供双入口 `run` + `execute_plan`
|
||||||
- [ ] `JsonPlanParser` 实现约 20 行,基于 `serde_json`
|
- [ ] `JsonPlanParser` 实现约 20 行,基于 `serde_json`
|
||||||
- [ ] `AgentError` 聚合 8 个变体,含 `is_recoverable()`
|
- [ ] `AgentError` 聚合 8 个变体,含 `is_recoverable()`
|
||||||
- [ ] `AgentBuilder` 提供 6 个 setter + `build()` 校验
|
- [ ] `AgentBuilder` 提供 7 个 setter(含 `.session_memory_backend()`)+ `build()` 校验
|
||||||
- [ ] `HookEvent` 新增 3 个变体:`OnTurnStart` / `OnTurnEnd` / `OnPlanStepComplete`
|
- [ ] `HookEvent` 新增 3 个变体:`OnTurnStart` / `OnTurnEnd` / `OnPlanStepComplete`
|
||||||
- [ ] `HookContext` 新增 2 个 `Option` 字段:`turn_index` / `plan_step_index`
|
- [ ] `HookContext` 新增 2 个 `Option` 字段:`turn_index` / `plan_step_index`
|
||||||
|
|
||||||
### 6.3 测试验收
|
### 6.3 测试验收
|
||||||
|
|
||||||
至少 2-3 个烟雾测试通过:
|
至少 3-4 个烟雾测试通过:
|
||||||
|
|
||||||
- [ ] **测试 1**:`Agent` trait 可实现 + `RuntimeBundle` 可构造(builder 链式调用)
|
- [ ] **测试 1**:`Agent` trait 可实现 + `RuntimeBundle` 可构造(builder 链式调用)
|
||||||
- [ ] **测试 2**:`AgentSession::submit_turn` 跑通 mock provider(Phase 0 `MockProvider` 模式)
|
- [ ] **测试 2**:`AgentSession::submit_turn` 跑通 mock provider(Phase 0 `MockProvider` 模式)
|
||||||
- [ ] **测试 3(可选)**:`JsonPlanParser::parse` 能解析合法 JSON,失败时返回 `AgentError::PlanParse`
|
- [ ] **测试 3**:`SessionMemory` set / get / snapshot 基本读写(基于 `InMemoryStore`)
|
||||||
|
- [ ] **测试 4(可选)**:`JsonPlanParser::parse` 能解析合法 JSON,失败时返回 `AgentError::PlanParse`
|
||||||
|
|
||||||
### 6.4 文档验收
|
### 6.4 文档验收
|
||||||
|
|
||||||
@@ -630,9 +717,11 @@ hooks.rs (1) ──┐
|
|||||||
### 6.5 行为验收(人工 review)
|
### 6.5 行为验收(人工 review)
|
||||||
|
|
||||||
- [ ] `AgentSession::submit_turn` 不持有 `ConversationMemory`(grep 验证无 `use crate::memory::ConversationMemory`)
|
- [ ] `AgentSession::submit_turn` 不持有 `ConversationMemory`(grep 验证无 `use crate::memory::ConversationMemory`)
|
||||||
|
- [ ] `AgentSession` 持 `Arc<dyn Agent>`,可从 agent 获取 `system_prompt()` / `tool_definitions()`
|
||||||
- [ ] `RuntimeBundle::new` 当 `retriever` 为 `Some` 时自动注册 `"retrieve"` tool
|
- [ ] `RuntimeBundle::new` 当 `retriever` 为 `Some` 时自动注册 `"retrieve"` tool
|
||||||
- [ ] `AgentBuilder::build` 在必填字段缺失时返回 `AgentError::Config`(而非 panic)
|
- [ ] `AgentBuilder::build` 在必填字段缺失时返回 `AgentError::Config`(而非 panic)
|
||||||
- [ ] `AgentError::is_recoverable()` 对各变体返回正确分类
|
- [ ] `AgentError::is_recoverable()` 对各变体返回正确分类
|
||||||
|
- [ ] `SessionMemory` 在 `session_memory_backend` 未传入时自动使用 `InMemoryStore` 兜底
|
||||||
|
|
||||||
### 6.6 风险验收
|
### 6.6 风险验收
|
||||||
|
|
||||||
@@ -644,4 +733,4 @@ hooks.rs (1) ──┐
|
|||||||
|
|
||||||
## 7. 一句话总结
|
## 7. 一句话总结
|
||||||
|
|
||||||
> **Phase 4 = 1 个 trait(Agent)+ 1 个容器(RuntimeBundle)+ 1 个会话(AgentSession)+ 1 个任务抽象(TaskAgent)+ 4 个辅助组件(Builder / Error / PlanParser / Hook 扩展),约 740 行代码,把 Phase 0-3 已有能力"装配"成"智能体"的概念。**
|
> **Phase 4 = 1 个 trait(Agent)+ 1 个容器(RuntimeBundle)+ 1 个会话(AgentSession, 持 Arc\<dyn Agent\>)+ 1 个会话级记忆(SessionMemory)+ 1 个任务抽象(TaskAgent)+ 4 个辅助组件(Builder / Error / PlanParser / Hook 扩展),约 800 行代码,把 Phase 0-3 已有能力"装配"成"智能体"的概念。**
|
||||||
|
|||||||
@@ -0,0 +1,222 @@
|
|||||||
|
# Context 切换方案设计备忘
|
||||||
|
|
||||||
|
> 创建日期:2026-06-10
|
||||||
|
> 状态:备忘(Phase 4 不实现)
|
||||||
|
> 关联文档:
|
||||||
|
> - `docs/7-agent-runtime.md` — Phase 4 方案(含 SessionMemory 设计)
|
||||||
|
> - `docs/note-opencode-agent-switching.md` — OpenCode 切换机制调研
|
||||||
|
> - `docs/roadmap.md` — 项目总 Roadmap
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 背景
|
||||||
|
|
||||||
|
### 1.1 问题
|
||||||
|
|
||||||
|
在调研 OpenCode 的 Agent 切换机制后(详见 `docs/note-opencode-agent-switching.md`),发现其做法是:
|
||||||
|
|
||||||
|
- 切换 agent 时**不动消息历史**
|
||||||
|
- 在 user message 末尾追加 `synthetic: true` 的 `<system-reminder>` 提醒
|
||||||
|
- 同时**完全重新计算** system prompt
|
||||||
|
|
||||||
|
这个方法的问题是:**长上下文中频繁切换 agent 容易给 LLM 造成身份困惑**。同一个消息列表里有 `system: build` 的 identity,又出现 `system: plan` 的 identity,LLM 容易"串味"。
|
||||||
|
|
||||||
|
### 1.2 核心思路
|
||||||
|
|
||||||
|
以一个 session 里存在**多个独立的 context** 来解决,每个 context 有自己独立的 system prompt + 消息列表:
|
||||||
|
|
||||||
|
```
|
||||||
|
OpenCode 模式(一条流):
|
||||||
|
[system: build, user: A, ass: A', user: <切plan>, system: plan, user: B]
|
||||||
|
↑ 身份困惑
|
||||||
|
|
||||||
|
建议的多 context 模式:
|
||||||
|
session {
|
||||||
|
context_a: [system: build, user: A, ass: A'] ← 只有 build 的 identity
|
||||||
|
context_b: [system: plan, user: B, ass: B'] ← 只有 plan 的 identity
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 适用范围
|
||||||
|
|
||||||
|
| 场景 | 适用性 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| Agent 切换(build ↔ plan) | ✅ 核心场景 | 同一 session 内更换角色 |
|
||||||
|
| 主从 Agent 协作 | ✅ 核心场景 | primary 委派子任务给 subagent,subagent 独立运作 |
|
||||||
|
| 长 session 上下文压缩 | ✅ 附带收益 | 拆分 context 后,每个 context 独立累积消息,不会互相拖长 |
|
||||||
|
| 并行 context 执行 | ⚠️ 拓展场景 | context_a 和 context_b 可各自独立推进 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 三个候选方案
|
||||||
|
|
||||||
|
### 方案 A:OpenCode 式(system prompt 重算 + synthetic 追加)
|
||||||
|
|
||||||
|
**做法**:
|
||||||
|
- 单一消息列表
|
||||||
|
- 切换时重算 system prompt
|
||||||
|
- user message 末尾追加 `<system-reminder>` 标签
|
||||||
|
|
||||||
|
**优点**:
|
||||||
|
- 实现简单
|
||||||
|
- 消息历史完整可见
|
||||||
|
|
||||||
|
**缺点**:
|
||||||
|
- 长上下文身份困惑
|
||||||
|
- context 互相污染(每个 context 都要看全部历史)
|
||||||
|
|
||||||
|
**结论**:❌ 否决。不解决身份困惑问题。
|
||||||
|
|
||||||
|
### 方案 B:信息池 + 切换不重置(借鉴 OpenCode + 增强)
|
||||||
|
|
||||||
|
**做法**:
|
||||||
|
- 切换时保留历史
|
||||||
|
- 使用 `<system-reminder>` 标签
|
||||||
|
- 靠 prompt 工程让 LLM 理解身份变更
|
||||||
|
|
||||||
|
**优点**:
|
||||||
|
- 历史连贯
|
||||||
|
- 改动最小
|
||||||
|
|
||||||
|
**缺点**:
|
||||||
|
- 仍然有身份困惑风险
|
||||||
|
- 上下文不受控增长
|
||||||
|
|
||||||
|
**结论**:❌ 否决。治标不治本。
|
||||||
|
|
||||||
|
### 方案 C:多 context 隔离 + SessionMemory 桥接(推荐)
|
||||||
|
|
||||||
|
**做法**:
|
||||||
|
- 每个 agent 切换创建一个新的 context(独立消息列表 + 独立 system prompt)
|
||||||
|
- context 之间通过 `SessionMemory` 桥接关键信息
|
||||||
|
- 切换时新 context 的 system prompt 末尾注入 `SessionMemory::snapshot()`
|
||||||
|
|
||||||
|
```
|
||||||
|
context_a (build)
|
||||||
|
→ 对话 50 轮
|
||||||
|
→ 写入 SessionMemory: {"design_decision": "用 PostgreSQL",
|
||||||
|
"files_changed": "src/db.rs"}
|
||||||
|
→ 销毁(或沉睡)
|
||||||
|
|
||||||
|
创建 context_b (plan)
|
||||||
|
→ system_prompt += snapshot()
|
||||||
|
→ "<session-context>
|
||||||
|
design_decision: 用 PostgreSQL
|
||||||
|
files_changed: src/db.rs
|
||||||
|
</session-context>"
|
||||||
|
→ 对话 10 轮(不需要看 context_a 的 50 轮历史)
|
||||||
|
→ 读 SessionMemory: get("design_decision") → "用 PostgreSQL"
|
||||||
|
```
|
||||||
|
|
||||||
|
**优点**:
|
||||||
|
- ✅ 身份稳定:每个 context 只有一套 system prompt
|
||||||
|
- ✅ 上下文隔离:context_b 不受 context_a 的消息量影响
|
||||||
|
- ✅ 信息桥接:关键结论通过 SessionMemory 显式传递
|
||||||
|
- ✅ 并行潜力:两个 context 可各自运行
|
||||||
|
|
||||||
|
**缺点**:
|
||||||
|
- ❌ 实现复杂度:从"一个消息列表"到"多个消息列表 + 桥接"
|
||||||
|
- ❌ 信息完整性:LLM 自主决定"什么值得记",可能遗漏细节
|
||||||
|
- ❌ 上层理解成本:应用层需要理解 context 概念
|
||||||
|
|
||||||
|
**结论**:✅ 推荐。架构上最干净,但 Phase 4 不做全部实现。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. SessionMemory 桥接机制(方案 C 的核心)
|
||||||
|
|
||||||
|
### 3.1 设计决策
|
||||||
|
|
||||||
|
| 决策 | 结论 | 理由 |
|
||||||
|
|------|------|------|
|
||||||
|
| 复用 Phase 3 `MemoryStore` | ✅ 是 | 不引入新存储机制 |
|
||||||
|
| 跨进程支持 | ✅ 是 | 换后端即可(Redis / SQLite),`InMemoryStore` 兜底 |
|
||||||
|
| namespace 隔离 | ✅ 是 | `_session_{session_id}` 命名空间 |
|
||||||
|
| 谁写 SessionMemory | LLM 通过 tool 显式写(v0.2+)或上层应用 API 写 | 不支持自动写——避免 "写太多 = 噪音,写太少 = 遗漏" |
|
||||||
|
| snapshot 格式 | `<session-context>` XML 风格 | 专为注入 system prompt 设计 |
|
||||||
|
|
||||||
|
### 3.2 谁写 SessionMemory 的三种选项
|
||||||
|
|
||||||
|
| 选项 | 描述 | 评估 |
|
||||||
|
|------|------|------|
|
||||||
|
| **选项 1:AgentSession 自动写** | 每轮对话后自动摘录关键信息 | ❌ 摘录什么?容易变成精简版对话历史,失去"关键信息"的定位 |
|
||||||
|
| **选项 2:LLM 通过 tool 显式写** | 把 `SessionMemory::set` 暴露为 Tool 供 LLM 调用 | ✅ LLM 自主决定什么值得记;v0.2+ 实现自动注册 |
|
||||||
|
| **选项 3:上层应用 API 写** | `agent_session.session_memory.set("k", "v")` | ✅ Phase 4 即可用,最透明 |
|
||||||
|
|
||||||
|
**Phase 4 实现选项 3**,v0.2+ 补充选项 2(tool 自动注册)。
|
||||||
|
|
||||||
|
### 3.3 三层记忆体系
|
||||||
|
|
||||||
|
```
|
||||||
|
持久层(Phase 3) MemoryStore / KnowledgeStore ── 跨 session 持久,长期知识
|
||||||
|
会话层(Phase 4) SessionMemory ── 单 session 内共享,context 桥接
|
||||||
|
对话层(Phase 3) ConversationMemory ── 单 context 内消息历史
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Phase 4 范围 vs v0.2+ 范围
|
||||||
|
|
||||||
|
### ✅ Phase 4 做
|
||||||
|
|
||||||
|
| 组件 | 状态 | 行数 |
|
||||||
|
|------|------|------|
|
||||||
|
| `SessionMemory` struct | ✅ 做 | ~40 行 |
|
||||||
|
| `AgentSession` + `session_memory` 字段 | ✅ 做 | ~3 行 |
|
||||||
|
| `AgentSession` 持 `Arc<dyn Agent>` 替代 `agent_name: String` | ✅ 做 | ~3 行 |
|
||||||
|
| `RuntimeBundle` + `session_memory_backend` 字段 | ✅ 做 | ~1 行 |
|
||||||
|
| `AgentBuilder` + `.session_memory_backend()` | ✅ 做 | ~3 行 |
|
||||||
|
|
||||||
|
### ❌ 延后到 v0.2+
|
||||||
|
|
||||||
|
| 组件 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| Context 切换管理(`switch_context` / `create_context`) | ❌ 延后 | 需要 `ContextManager` 包装 |
|
||||||
|
| 多 context 生命周期管理 | ❌ 延后 | context 的创建/销毁/切换策略 |
|
||||||
|
| `"session_memory_set"` tool 自动注册 | ❌ 延后 | 在 `ToolRegistry` 里注册特殊 tool |
|
||||||
|
| Context 级别的 `ConversationMemory` 自动管理 | ❌ 延后 | 每个 context 独立消息历史 |
|
||||||
|
|
||||||
|
### 延后的理由
|
||||||
|
|
||||||
|
1. **最小范围原则**:Phase 4 定位是"薄胶水层 + trait 抽象",多 context 管理属于业务编排的范畴
|
||||||
|
2. **稳定 API 优先**:先把 `AgentSession` / `RuntimeBundle` / `SessionMemory` 的 API 定稳,v0.2+ 在上面搭建 context 切换
|
||||||
|
3. **降低实施风险**:Phase 4 已有 13 个交付任务,加 context 切换会增加 2-3 倍复杂度
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. v0.2+ Context 切换的设想接口
|
||||||
|
|
||||||
|
> 以下为未来实现的草案,非承诺。记录在这里避免 v0.2+ 重新设计时丢失上下文。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct ContextManager {
|
||||||
|
contexts: HashMap<String, AgentSession>,
|
||||||
|
active_context: String,
|
||||||
|
session_memory: SessionMemory,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContextManager {
|
||||||
|
/// 创建一个新的 context,绑定指定 agent
|
||||||
|
pub fn create_context(&mut self, id: &str, agent: Arc<dyn Agent>) -> Result<(), AgentError>;
|
||||||
|
|
||||||
|
/// 切换到已有 context
|
||||||
|
pub fn switch_context(&mut self, id: &str) -> Result<&mut AgentSession, AgentError>;
|
||||||
|
|
||||||
|
/// 销毁 context
|
||||||
|
pub fn destroy_context(&mut self, id: &str) -> Result<(), AgentError>;
|
||||||
|
|
||||||
|
/// 从 context_a 桥接关键信息到 context_b 的 system prompt
|
||||||
|
pub fn bridge(&mut self, from: &str, to: &str) -> Result<(), AgentError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
切换流程:
|
||||||
|
1. `context_manager.create_context("plan", plan_agent)` — 新 context 的 system prompt 自动附加 `session_memory.snapshot()`
|
||||||
|
2. `context_manager.switch_context("plan")` — 返回 context 的 `AgentSession`,应用层调 `submit_turn`
|
||||||
|
3. context 销毁时,关键信息经由 LLM 或上层应用写入 `SessionMemory`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 一句话总结
|
||||||
|
|
||||||
|
> **多 context 切换方案 = `SessionMemory`(Phase 4 做信息桥接基础) + `ContextManager`(v0.2+ 做切换管理)。Phase 4 只铺"水管接口",不装"水循环系统"。**
|
||||||
+19
-13
@@ -1,13 +1,13 @@
|
|||||||
# AG Core Roadmap
|
# AG Core Roadmap
|
||||||
|
|
||||||
> 定稿日期:2026-05-11
|
> 定稿日期:2026-05-11
|
||||||
> 最后更新:2026-06-09(Phase 4 设计讨论收尾;扩展计划补充 v0.2+ 候选项)
|
> 最后更新:2026-06-10(Phase 4 方案定稿 + SessionMemory 扩展 + Context 切换备忘)
|
||||||
|
|
||||||
## 愿景
|
## 愿景
|
||||||
|
|
||||||
AG Core 定位为构建 AI 智能体的底层工具箱,通过模块化、可插拔的架构,提供大模型调用、提示词工程、工具系统、记忆检索四大核心能力,支持快速组合出符合业务需求的智能体应用。
|
AG Core 定位为构建 AI 智能体的底层工具箱,通过模块化、可插拔的架构,提供大模型调用、提示词工程、工具系统、记忆检索四大核心能力,支持快速组合出符合业务需求的智能体应用。
|
||||||
|
|
||||||
**当前状态**:Phase 0 基础设施已全部完成,Phase 1 提示词工程已全部完成,Phase 2 工具系统已全部完成,Phase 3 记忆系统已全部完成,等待 Phase 4 启动。
|
**当前状态**:Phase 0 基础设施已全部完成,Phase 1 提示词工程已全部完成,Phase 2 工具系统已全部完成,Phase 3 记忆系统已全部完成,Phase 4 方案文档已完成(含 SessionMemory 扩展),待编码实施。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ AG Core 定位为构建 AI 智能体的底层工具箱,通过模块化、可
|
|||||||
| 提示词工程 | ✅ 完整 | `docs/4-prompt-engineering.md` | P1 |
|
| 提示词工程 | ✅ 完整 | `docs/4-prompt-engineering.md` | P1 |
|
||||||
| 工具系统 + 权限 | ✅ 完整 | `docs/5-tool-system.md` | P1 |
|
| 工具系统 + 权限 | ✅ 完整 | `docs/5-tool-system.md` | P1 |
|
||||||
| 记忆检索 | ✅ 完整 | `docs/6-memory-system.md` | P2 |
|
| 记忆检索 | ✅ 完整 | `docs/6-memory-system.md` | P2 |
|
||||||
| Agent 运行时 | ❌ 缺失 | — | P2 |
|
| Agent 运行时 | ✅ 方案已完成 | `docs/7-agent-runtime.md` | P2 |
|
||||||
| 生命周期钩子 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(LLM Cycle 扩展) |
|
| 生命周期钩子 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(LLM Cycle 扩展) |
|
||||||
| Provider 注册发现 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(Provider 接口扩展) |
|
| Provider 注册发现 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(Provider 接口扩展) |
|
||||||
| 流式事件系统 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(流式接口前置) |
|
| 流式事件系统 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(流式接口前置) |
|
||||||
@@ -123,20 +123,25 @@ AG Core 定位为构建 AI 智能体的底层工具箱,通过模块化、可
|
|||||||
|
|
||||||
### Phase 4 — Agent Runtime(智能体运行时)
|
### Phase 4 — Agent Runtime(智能体运行时)
|
||||||
|
|
||||||
**目标**:实现多轮对话编排与任务规划。
|
**目标**:实现多轮对话编排、任务规划与会话级记忆桥接。
|
||||||
|
|
||||||
**交付物**:
|
**交付物**:
|
||||||
1. `agent.rs` + `agent/` 模块
|
1. `agent.rs` + `agent/` 模块(8 个文件)
|
||||||
2. `Agent` trait — 智能体接口定义
|
2. `Agent` trait — 智能体角色定义(name / system_prompt / tool_definitions)
|
||||||
3. `ConversationAgent` — 对话型智能体实现
|
3. `AgentSession` — 会话实例(绑定 `Arc<dyn Agent>` + `RuntimeBundle` + `SessionMemory`)
|
||||||
4. `TaskAgent` — 任务型智能体(规划 → 执行 → 反馈)
|
4. `RuntimeBundle` — 显式依赖注入容器(7 个字段,含 `session_memory_backend`)
|
||||||
5. `specs/agent-runtime.md` — 方案文档
|
5. `SessionMemory` — 会话级记忆(基于 `MemoryStore`,context 间信息桥接)
|
||||||
|
6. `TaskAgent` — 任务型智能体(规划 → 执行 → 反馈)
|
||||||
|
7. `AgentBuilder` — 链式构造入口
|
||||||
|
8. `AgentError` — 统一错误类型(聚合 LlmError / ToolError / MemoryError)
|
||||||
|
9. Hook 事件扩展(OnTurnStart / OnTurnEnd / OnPlanStepComplete)
|
||||||
|
10. `docs/7-agent-runtime.md` — 方案设计文档
|
||||||
|
|
||||||
**依赖**:Phase 0, 1, 2, 3(整合所有模块)
|
**依赖**:Phase 0, 1, 2, 3(整合所有模块)
|
||||||
|
|
||||||
**优先级**:Could Have
|
**优先级**:Could Have
|
||||||
|
|
||||||
**预估规模**:约 600 行代码
|
**预估规模**:约 800 行代码
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -232,6 +237,7 @@ graph BT
|
|||||||
|-------|---------|------|--------|------|
|
|-------|---------|------|--------|------|
|
||||||
| Agent 身份切换(角色轮换) | `agent` | 借鉴 OpenCode Tab 键切换 build/plan:同一 `AgentSession` 持有可热替换的 `Agent` 引用,切换时不重置消息历史,在末尾追加 `synthetic: true` 的状态变更消息。详见 `docs/note-opencode-agent-switching.md` §4 | P2 | v0.2 待评估 |
|
| Agent 身份切换(角色轮换) | `agent` | 借鉴 OpenCode Tab 键切换 build/plan:同一 `AgentSession` 持有可热替换的 `Agent` 引用,切换时不重置消息历史,在末尾追加 `synthetic: true` 的状态变更消息。详见 `docs/note-opencode-agent-switching.md` §4 | P2 | v0.2 待评估 |
|
||||||
| System Prompt 多层动态拼接 | `agent/session` | 借鉴 OpenCode `request.ts:58-66`:拆分 `base_prompt + agent_prompt + env_context` 三层,`AgentSession::submit_turn` 每轮重算(不缓存),便于按 agent 类型动态切换 | P2 | v0.2 待评估 |
|
| System Prompt 多层动态拼接 | `agent/session` | 借鉴 OpenCode `request.ts:58-66`:拆分 `base_prompt + agent_prompt + env_context` 三层,`AgentSession::submit_turn` 每轮重算(不缓存),便于按 agent 类型动态切换 | P2 | v0.2 待评估 |
|
||||||
|
| **多 Context 切换** | `agent` | **Phase 4 的 SessionMemory 数据结构已预留信息桥接通道,v0.2+ 在其上包装 `ContextManager` 实现完整的多 context 切换:创建/销毁/切换 context、通过 SessionMemory 桥接关键信息。详见 `docs/note-context-switch-design.md`** | P2 | v0.2 待评估 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -241,15 +247,15 @@ graph BT
|
|||||||
2. **并行可能性**:Phase 0 和 Phase 1 可并行开展(无相互依赖),可加速早期交付
|
2. **并行可能性**:Phase 0 和 Phase 1 可并行开展(无相互依赖),可加速早期交付
|
||||||
3. **MCP 协议复杂性**:MCP 涉及协议握手、session 管理、长期连接,建议预留充足时间调研协议细节
|
3. **MCP 协议复杂性**:MCP 涉及协议握手、session 管理、长期连接,建议预留充足时间调研协议细节
|
||||||
4. **Scope 蔓延风险**:当前 specs 只有 1 份文档,建议每个模块上线前都产出对应 spec,避免边实现边设计
|
4. **Scope 蔓延风险**:当前 specs 只有 1 份文档,建议每个模块上线前都产出对应 spec,避免边实现边设计
|
||||||
5. **Phase 4 抽象化边界**:AG Core 定位为"支持库"而非"Agent 产品",Phase 4 需严格控制范围——只暴露 trait + 最小 reference impl,业务循环(多轮 turn 编排、记忆自动回写、Task 拆解策略)留给上层应用,避免与 OpenHarness / Hermes / OpenHuman 等已有 Agent 产品竞争实现细节。详细设计决策见 Phase 4 设计讨论记录(待 `docs/7-agent-runtime.md` 落盘)
|
5. **Phase 4 抽象化边界**:AG Core 定位为"支持库"而非"Agent 产品",Phase 4 需严格控制范围——只暴露 trait + 最小 reference impl,业务循环(多轮 turn 编排、对话记忆自动回写、Task 拆解策略)留给上层应用。`SessionMemory`(会话级记忆)已在范围内——它提供信息桥接通道但不实现 context 切换逻辑。多 context 切换管理延后至 v0.2+。详细设计决策见 `docs/7-agent-runtime.md`
|
||||||
6. **参考项目语言差异**:OpenClaw / Hermes / OpenHarness 均为 Python/TypeScript 实现,OpenHuman 虽是 Rust + Tauri 但定位是桌面应用。借鉴时**只取架构模式**,不照搬具体实现(如 Pydantic 工具校验、SQLite Memory Tree、Node+Python 双进程等)
|
6. **参考项目语言差异**:OpenClaw / Hermes / OpenHarness 均为 Python/TypeScript 实现,OpenHuman 虽是 Rust + Tauri 但定位是桌面应用。借鉴时**只取架构模式**,不照搬具体实现(如 Pydantic 工具校验、SQLite Memory Tree、Node+Python 双进程等)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 下一步行动
|
## 下一步行动
|
||||||
|
|
||||||
1. **Phase 4 设计讨论收尾**:Phase 4 范围已收窄为「`Agent` trait + `RuntimeBundle` 依赖注入容器 + `AgentSession` 实体/会话分离 + `TaskAgent` 双入口 + 记忆弱引用 + Hook 事件扩展 3 个」。决策记录已固化,待写 `docs/7-agent-runtime.md` 方案文档后启动编码实现
|
1. **Phase 4 实施方案**:`docs/7-agent-runtime.md` 方案文档已完成(含 SessionMemory 扩展),下一步启动编码实现,按依赖顺序完成 13 个交付任务后翻转 Roadmap 状态
|
||||||
2. **Phase 4 方案文档**:将 Phase 4 设计决策沉淀为方案文档,沿用 `docs/4-prompt-engineering.md` / `5-tool-system.md` / `6-memory-system.md` 的 6 段式结构,文件名 `docs/7-agent-runtime.md`
|
2. **Context 切换备忘**:`docs/note-context-switch-design.md` 记录了多 context 切换方案讨论,作为 v0.2+ 扩展项的输入
|
||||||
3. **参考项目调研沉淀**:已完成 OpenClaw / Hermes / OpenHuman / OpenHarness 横向调研,结果沉淀至 `docs/note-agent-harness-references.md`,作为 v0.2+ 扩展项的输入
|
3. **参考项目调研沉淀**:已完成 OpenClaw / Hermes / OpenHuman / OpenHarness 横向调研,结果沉淀至 `docs/note-agent-harness-references.md`,作为 v0.2+ 扩展项的输入
|
||||||
4. **Phase 3 备用设计就绪**:`docs/note-knowledge-graph-design.md` 记录了 KnowledgeGraph、高级评分、RecallBased 淘汰等设计,v0.2+ 记忆扩展可直接参考
|
4. **Phase 3 备用设计就绪**:`docs/note-knowledge-graph-design.md` 记录了 KnowledgeGraph、高级评分、RecallBased 淘汰等设计,v0.2+ 记忆扩展可直接参考
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user