docs(agent): 补充 Phase 4 Agent Runtime 方案文档与设计决策记录
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
# Phase 4 Agent Runtime — 设计决策记录
|
||||
|
||||
> 决策固化日期:2026-06-09
|
||||
> 用途:记录 Phase 4 设计阶段的关键决策、接口签名草案、文件清单,作为 `docs/7-agent-runtime.md` 方案文档的输入约束。
|
||||
> 关联:
|
||||
> - `docs/7-agent-runtime.md` — 完整方案文档(待写 / 已写)
|
||||
> - `docs/note-agent-harness-references.md` — 参考项目调研(OpenClaw / Hermes / OpenHuman / OpenHarness)
|
||||
> - `docs/roadmap.md` — 项目总 Roadmap
|
||||
> - `docs/2-llm-call-lifecycle.md` / `3-phase0-remaining.md` / `4-prompt-engineering.md` / `5-tool-system.md` / `6-memory-system.md` — Phase 0-3 方案
|
||||
|
||||
本文件是 Phase 4 设计阶段的"事实基础"——所有决策都有明确的对话出处与依据。后续 Phase 4 实施时应与本记录保持一致;如需调整,应先更新本记录再改代码。
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
AG Core Phase 4 的定位是**「Phase 0-3 的薄胶水层 + 一组 trait 抽象」**,遵循 OpenHarness 的"显式依赖注入"模式 + Hermes 的"两层实体/会话"模型。**不**实现业务循环,**不**做产品级功能,**不**假设上层如何使用 memory。
|
||||
|
||||
## 2. 范围与边界
|
||||
|
||||
### 2.1 必须实现(12 项)
|
||||
|
||||
| # | 交付物 | 文件 | 关键决策 |
|
||||
|---|--------|------|---------|
|
||||
| 1 | `Agent` trait | `src/agent/agent.rs` | 角色定义:name / system_prompt / 工具集 / 引用 session 句柄 |
|
||||
| 2 | `RuntimeBundle` | `src/agent/runtime.rs` | 依赖注入容器(OpenHarness 风格) |
|
||||
| 3 | `AgentSession` | `src/agent/session.rs` | 会话实例 + **最小 reference impl**(`submit_turn` ~30 行) |
|
||||
| 4 | `TaskAgent` + `Plan` / `Step` | `src/agent/task.rs` | 双入口:`run(goal)` 自主式 + `execute_plan(plan)` 外部驱动式 |
|
||||
| 5 | `PlanParser` trait + `JsonPlanParser` 参考实现 | `src/agent/task.rs` | 注入式(澄清 3 选项 C) |
|
||||
| 6 | `AgentError` | `src/agent/error.rs` | 聚合 LlmError / ToolError / MemoryError,含 `is_recoverable()` |
|
||||
| 7 | `AgentConfig` / `AgentBuilder` | `src/agent/builder.rs` | 链式构造 `RuntimeBundle` |
|
||||
| 8 | Hook 事件扩展 | `src/llm/hooks.rs` | 追加 `OnTurnStart` / `OnTurnEnd` / `OnPlanStepComplete` 3 个事件 + 上下文扩展(澄清 4) |
|
||||
| 9 | `lib.rs` 导出 | `src/lib.rs` | 一行 `pub mod agent;` |
|
||||
| 10 | 烟雾测试 | `src/agent/tests.rs` 或内联 | 2-3 个:trait 可装配 / RuntimeBundle 可构造 / `submit_turn` 跑通 mock |
|
||||
| 11 | 方案文档 | `docs/7-agent-runtime.md` | 编号 `7`(最大编号是 `6`,已确认无冲突) |
|
||||
| 12 | Roadmap 同步 | `docs/roadmap.md` | 状态从 ❌ 缺失 改为 ✅ |
|
||||
|
||||
### 2.2 明确不做(v0.2+ 边界)
|
||||
|
||||
| 推迟项 | 理由 |
|
||||
|--------|------|
|
||||
| 完整 `BasicAgent` 多轮 turn 循环 | core 库不假设业务循环 |
|
||||
| `ConversationAgent` 自动回写 | 记忆在独立 task 处理,由上层回写 |
|
||||
| 强绑定 `ConversationMemory` 字段 | 改 `Option<Arc<dyn MemoryStore>>` 弱引用 |
|
||||
| Plan 拆解的提示词模板 | 由上层注入 `PlanParser` |
|
||||
| Multi-Agent / Swarm | 接口未稳定,独立 phase |
|
||||
| Markdown 技能按需加载 | 属于知识层 |
|
||||
| 三级权限模式 UI | 应用层 |
|
||||
| 干运行 / TUI / Gateway | 应用层 |
|
||||
| 完整的集成测试套件 | 2-3 个烟雾测试足够(呼应"最小范围") |
|
||||
|
||||
详细 v0.2+ 候选项见 `docs/roadmap.md` 扩展计划(v0.2+)小节与 `docs/note-agent-harness-references.md` 第 8 节。
|
||||
|
||||
## 3. 核心架构
|
||||
|
||||
### 3.1 分层(与 OpenHarness 5 层一致)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 应用层 (上层 crate / 二进制 / Gateway) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Agent Runtime ← Phase 4:trait + RuntimeBundle + Session │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ LLM / Tool / Prompt / Memory ← Phase 0/1/2/3(已完成) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 实体关系
|
||||
|
||||
```
|
||||
┌────────────┐ ┌──────────────────┐
|
||||
│ Agent │ 1 * │ AgentSession │
|
||||
│ (trait) ├────────►│ (struct) │
|
||||
│ - name │ │ - session_id │
|
||||
│ - prompt │ │ - bundle: Arc │
|
||||
│ - tools │ │ - turn_index │
|
||||
└────────────┘ │ - cost_so_far │
|
||||
└──────────────────┘
|
||||
│
|
||||
▼ 共享
|
||||
┌──────────────────┐
|
||||
│ RuntimeBundle │
|
||||
│ - provider │
|
||||
│ - tool_registry │
|
||||
│ - hook_executor │
|
||||
│ - memory_store? │ ◄── 弱引用(澄清 2 选项 B)
|
||||
│ - retriever? │
|
||||
│ - config │
|
||||
└──────────────────┘
|
||||
│
|
||||
▼ 注册为 tool
|
||||
┌──────────────────┐
|
||||
│ "retrieve" tool │ ◄── 如果 retriever 存在则自动注册
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
### 3.3 决策对照表
|
||||
|
||||
| 决策点 | 选择 | 来源 |
|
||||
|--------|------|------|
|
||||
| 实体 vs 会话 | 两层模型(`Agent` + `AgentSession`) | 讨论第 4 轮第 1 条 / OpenHarness / Hermes |
|
||||
| 范围控制 | trait + 最小 reference impl(~30 行) | 讨论第 4 轮第 2 条 / 澄清 1 选项 B |
|
||||
| 记忆处理 | 弱引用 + 自动注册 retriever 为 tool | 讨论第 4 轮第 3 条 / 澄清 2 选项 B |
|
||||
| Hook 扩展 | 3 个新事件 + 上下文扩展 | 讨论第 4 轮第 4 条 / 澄清 4 |
|
||||
| 方案文档位置 | `docs/7-agent-runtime.md` | 讨论第 4 轮第 5 条 |
|
||||
| TaskAgent 入口 | 双入口(自主 + 外部驱动) | 讨论第 4 轮第 6 条 |
|
||||
| 自主式 Plan 解析 | 注入式 `PlanParser` trait + `JsonPlanParser` 参考实现 | 澄清 3 选项 C |
|
||||
| 依赖注入 | `RuntimeBundle` 显式容器 | 讨论第 4 轮第 7 条 / OpenHarness |
|
||||
| 文档撰写 | 推迟到 Proposal 阶段 | 讨论第 4 轮第 8 条 |
|
||||
|
||||
## 4. 接口签名草案
|
||||
|
||||
> ⚠️ **这些是"设计约束",不是最终代码**。方案文档(`docs/7-agent-runtime.md`)与实施阶段可微调字段顺序、文档注释、错误变体等,但**核心 trait 形状**和**方法名**应保持稳定。
|
||||
|
||||
### 4.1 `Agent` trait
|
||||
|
||||
```rust
|
||||
pub trait Agent: Send + Sync {
|
||||
fn name(&self) -> &str;
|
||||
fn system_prompt(&self) -> Option<&str>;
|
||||
/// 列出该 Agent 想要暴露给 LLM 的工具定义。
|
||||
/// 默认实现:从 RuntimeBundle.tool_registry 取全部(最常用)。
|
||||
/// 子 trait 可覆盖做白名单/过滤。
|
||||
fn tool_definitions(&self, bundle: &RuntimeBundle) -> Vec<ToolDefinition>;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 `RuntimeBundle`
|
||||
|
||||
```rust
|
||||
pub struct RuntimeBundle {
|
||||
pub provider: Arc<dyn LlmProvider>,
|
||||
pub tool_registry: Arc<ToolRegistry>,
|
||||
pub hook_executor: Arc<HookExecutor>,
|
||||
pub memory_store: Option<Arc<dyn MemoryStore>>, // 弱引用(澄清 2 选项 B)
|
||||
pub retriever: Option<Arc<MemoryRetriever>>, // 弱引用(澄清 2 选项 B)
|
||||
pub config: AgentConfig,
|
||||
}
|
||||
|
||||
impl RuntimeBundle {
|
||||
/// 构造时如果 retriever 存在,自动注册为 "retrieve" tool。
|
||||
pub fn new(/* ... */) -> Self;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 `AgentSession`
|
||||
|
||||
```rust
|
||||
pub struct AgentSession {
|
||||
pub session_id: String,
|
||||
pub agent_name: String,
|
||||
bundle: Arc<RuntimeBundle>,
|
||||
turn_index: u32,
|
||||
cost_so_far: CostTracker,
|
||||
}
|
||||
|
||||
impl AgentSession {
|
||||
pub fn new(agent: &dyn Agent, session_id: impl Into<String>, bundle: Arc<RuntimeBundle>) -> Self;
|
||||
|
||||
/// 最小 reference impl:组装 LlmCycle + submit + 累计 cost。
|
||||
/// 不做 memory 回写(呼应"记忆在独立 task 处理"原则)。
|
||||
pub async fn submit_turn(
|
||||
&mut self,
|
||||
user_input: impl Into<String>,
|
||||
) -> Result<ChatResponse, AgentError>;
|
||||
|
||||
pub fn usage(&self) -> &CostTracker;
|
||||
pub fn turn_index(&self) -> u32;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 `TaskAgent` + `Plan` + `Step`
|
||||
|
||||
```rust
|
||||
pub struct Plan {
|
||||
pub id: String,
|
||||
pub goal: String,
|
||||
pub steps: Vec<Step>,
|
||||
}
|
||||
|
||||
pub struct Step {
|
||||
pub index: usize,
|
||||
pub description: String,
|
||||
pub status: StepStatus,
|
||||
}
|
||||
|
||||
pub enum StepStatus {
|
||||
Pending,
|
||||
Running,
|
||||
Completed(ChatResponse),
|
||||
Failed(AgentError),
|
||||
Skipped,
|
||||
}
|
||||
|
||||
/// 注入式 Plan 解析器。
|
||||
#[async_trait]
|
||||
pub trait PlanParser: Send + Sync {
|
||||
async fn parse(&self, raw: &str, goal: &str) -> Result<Plan, AgentError>;
|
||||
}
|
||||
|
||||
/// 基于 serde_json 的参考实现(约 20 行)。
|
||||
pub struct JsonPlanParser;
|
||||
|
||||
#[async_trait]
|
||||
impl PlanParser for JsonPlanParser { /* ... */ }
|
||||
|
||||
/// TaskAgent 双入口。
|
||||
#[async_trait]
|
||||
pub trait TaskAgent: Agent {
|
||||
/// 自主式:内部用 LLM 拆 Plan → execute_plan
|
||||
async fn run(&mut self, session: &mut AgentSession, goal: &str) -> Result<Plan, AgentError>;
|
||||
|
||||
/// 外部驱动式:用户预定义 Plan → 逐步执行
|
||||
async fn execute_plan(
|
||||
&mut self,
|
||||
session: &mut AgentSession,
|
||||
plan: Plan,
|
||||
) -> Result<Plan, AgentError>;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.5 `AgentError`
|
||||
|
||||
```rust
|
||||
pub enum AgentError {
|
||||
Llm(LlmError),
|
||||
Tool(ToolError),
|
||||
Memory(MemoryError),
|
||||
PlanParse(String),
|
||||
HookBlocked(String),
|
||||
LimitExceeded(String),
|
||||
Config(String),
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl AgentError {
|
||||
pub fn is_recoverable(&self) -> bool { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
### 4.6 `AgentConfig` + `AgentBuilder`
|
||||
|
||||
```rust
|
||||
pub struct AgentConfig {
|
||||
pub max_turns: u32,
|
||||
pub max_tool_turns: u32,
|
||||
pub session_ttl: Option<Duration>,
|
||||
pub compact_config: Option<CompactConfig>,
|
||||
}
|
||||
|
||||
pub struct AgentBuilder { /* ... */ }
|
||||
|
||||
impl AgentBuilder {
|
||||
pub fn new() -> Self;
|
||||
pub fn provider(self, p: Arc<dyn LlmProvider>) -> Self;
|
||||
pub fn tool_registry(self, r: Arc<ToolRegistry>) -> Self;
|
||||
pub fn hook_executor(self, h: Arc<HookExecutor>) -> Self;
|
||||
pub fn memory_store(self, m: Arc<dyn MemoryStore>) -> Self; // 选填
|
||||
pub fn retriever(self, r: Arc<MemoryRetriever>) -> Self; // 选填
|
||||
pub fn config(self, c: AgentConfig) -> Self;
|
||||
pub fn build(self) -> Result<RuntimeBundle, AgentError>;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.7 Hook 扩展(`src/llm/hooks.rs` 改动)
|
||||
|
||||
```rust
|
||||
pub enum HookEvent {
|
||||
// ... 现有 4 个 ...
|
||||
|
||||
// 新增 3 个:
|
||||
OnTurnStart,
|
||||
OnTurnEnd,
|
||||
OnPlanStepComplete,
|
||||
}
|
||||
|
||||
// HookContext 扩展 2 个 Option 字段(澄清 4):
|
||||
pub struct HookContext {
|
||||
// ... 现有字段 ...
|
||||
pub turn_index: Option<u32>, // OnTurnStart/End 用
|
||||
pub plan_step_index: Option<usize>, // OnPlanStepComplete 用
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 文件清单
|
||||
|
||||
### 5.1 新增文件(7 个)
|
||||
|
||||
```
|
||||
src/agent.rs # 模块根 + pub use 重导出
|
||||
src/agent/agent.rs # Agent trait
|
||||
src/agent/runtime.rs # RuntimeBundle + AgentConfig
|
||||
src/agent/session.rs # AgentSession
|
||||
src/agent/task.rs # TaskAgent trait + Plan/Step + PlanParser + JsonPlanParser
|
||||
src/agent/builder.rs # AgentBuilder
|
||||
src/agent/error.rs # AgentError
|
||||
```
|
||||
|
||||
### 5.2 修改文件(3 个)
|
||||
|
||||
```
|
||||
src/lib.rs # + pub mod agent;
|
||||
src/llm/hooks.rs # + 3 个事件变体 + 2 个上下文字段(极小改)
|
||||
docs/roadmap.md # 状态翻转 + Phase 4 交付物清单更新(实施时再做)
|
||||
```
|
||||
|
||||
### 5.3 关联文档(已存在 / 待写)
|
||||
|
||||
```
|
||||
docs/note-agent-harness-references.md # 参考项目调研(已存在)
|
||||
docs/7-agent-runtime.md # 完整方案文档(路径 A 输出)
|
||||
docs/note-agent-runtime-design.md # 本文件
|
||||
```
|
||||
|
||||
## 6. 预估规模
|
||||
|
||||
- **新增代码**:约 **600-700 行**(含 2-3 个烟雾测试)
|
||||
- **修改代码**:约 **10-20 行**(`hooks.rs` 改动 + `lib.rs` + `roadmap.md`)
|
||||
- **方案文档**:约 **450-550 行 Markdown**(沿用 6-memory-system.md 的 6 段式结构)
|
||||
|
||||
## 7. 待办事项(按依赖顺序)
|
||||
|
||||
1. ✅ Phase 4 范围已收窄(§2.1)
|
||||
2. ✅ 核心架构已对齐 OpenHarness / Hermes(§3)
|
||||
3. ✅ 接口签名草案已固化(§4)
|
||||
4. ✅ 文件清单已确定(§5)
|
||||
5. ✅ 编号冲突已验证(最大是 `6`,新文件用 `7`)
|
||||
6. ⏳ 写 `docs/7-agent-runtime.md` 方案文档
|
||||
7. ⏳ 按文档实施 7 个新文件 + 3 个修改
|
||||
8. ⏳ 跑通 2-3 个烟雾测试
|
||||
9. ⏳ 更新 `docs/roadmap.md` 状态翻转
|
||||
|
||||
## 8. 一句话总结
|
||||
|
||||
> **Phase 4 = Phase 0-3 的薄胶水层 + 一组 trait 抽象**。**不**实现业务循环,**不**做产品级功能,**不**假设上层如何使用 memory。借鉴 OpenHarness 的"显式依赖注入容器"与 Hermes 的"实体/会话分离"模型,记忆以弱引用方式接入,`MemoryRetriever` 在 `RuntimeBundle::new()` 时自动注册为 LLM 可调用的 `retrieve` 工具。
|
||||
Reference in New Issue
Block a user