# Reson Agent 设计文档 > **设计目标**:可扩展、可学习的 Agent 框架,支持执行追踪和持久记忆。 --- ## 1. 核心洞察 **单次调用是 Agent 的特例**: | 特性 | 单次调用 | Agent 模式 | |------|---------|-----------| | 循环次数 | 1 | N (可配置) | | 工具调用 | 可选 | 常用 | | 状态管理 | 无 | 有 (Task State) | | 记忆检索 | 无 | 有 (Experience/Skill) | | 执行图 | 1 个节点 | N 个节点的 DAG | **统一抽象**:用同一套数据结构描述两者。 --- ## 2. 三层记忆模型 ``` ┌─────────────────────────────────────────────────────────────┐ │ Layer 3: Skills(技能库) │ │ - 从 Experience 归纳的高层策略 │ │ - 层次化组织,按领域/任务类型分类 │ │ - 执行前注入到 System Prompt │ └─────────────────────────────────────────────────────────────┘ ▲ │ 归纳 ┌─────────────────────────────────────────────────────────────┐ │ Layer 2: Experience(经验库) │ │ - 条件 + 规则 + 证据 │ │ - 来源:执行反馈、人工标注 │ │ - 持久存储,跨任务复用 │ └─────────────────────────────────────────────────────────────┘ ▲ │ 提取 ┌─────────────────────────────────────────────────────────────┐ │ Layer 1: Task State(任务状态) │ │ - 当前任务的工作记忆 │ │ - 计划、进度、中间结论 │ │ - 任务结束时重置 │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 3. 执行图(Execution Graph) 每次任务执行产生一张 DAG: ``` TaskNode(任务根节点) │ ├─▶ LLMCallNode(第1次推理) │ │ │ ├─▶ ToolCallNode(搜索工具) │ │ │ │ │ └─▶ ToolResultNode(搜索结果) │ │ │ └─▶ ConclusionNode(中间结论) │ ├─▶ LLMCallNode(第2次推理) │ │ │ └─▶ ConclusionNode(最终结论) │ └─▶ FeedbackNode(人工反馈) │ └─▶ ExperienceNode(提取的经验) ``` **节点类型**: | 类型 | 说明 | 数据 | |------|------|------| | `llm_call` | LLM 调用 | messages, response, model, tokens, cost | | `tool_call` | 工具调用 | tool_name, arguments | | `tool_result` | 工具结果 | result, duration_ms | | `conclusion` | 中间/最终结论 | content, is_final | | `feedback` | 人工反馈 | feedback_type, content, target_step_id | | `memory_read` | 读取记忆 | skills, experiences | | `memory_write` | 写入记忆 | experience_id | --- ## 4. 数据模型 ### 4.1 Trace(执行轨迹) ```python @dataclass class Trace: trace_id: str mode: Literal["call", "agent"] prompt_name: Optional[str] = None # Agent 模式特有 task: Optional[str] = None agent_type: Optional[str] = None # 状态 status: Literal["running", "completed", "failed"] = "running" # 统计 total_steps: int = 0 total_tokens: int = 0 total_cost: float = 0.0 # 上下文 uid: Optional[str] = None context: Dict[str, Any] = field(default_factory=dict) # 时间 created_at: datetime completed_at: Optional[datetime] = None ``` ### 4.2 Step(执行步骤) ```python @dataclass class Step: step_id: str trace_id: str step_type: StepType sequence: int # DAG 结构 parent_ids: List[str] = field(default_factory=list) # 类型相关数据 data: Dict[str, Any] = field(default_factory=dict) created_at: datetime ``` ### 4.3 Experience(经验) ```python @dataclass class Experience: exp_id: str scope: str # "agent:{type}" 或 "user:{uid}" # 核心三元组 condition: str rule: str evidence: List[str] # step_ids # 元数据 source: Literal["execution", "feedback", "manual"] confidence: float = 0.5 usage_count: int = 0 success_rate: float = 0.0 created_at: datetime updated_at: datetime ``` ### 4.4 Skill(技能) ```python @dataclass class Skill: skill_id: str scope: str name: str description: str category: str # 层次结构 parent_id: Optional[str] = None # 内容 guidelines: List[str] derived_from: List[str] # experience_ids version: int = 1 created_at: datetime updated_at: datetime ``` --- ## 5. 存储抽象 ### Protocol 定义 ```python class TraceStore(Protocol): async def create_trace(self, trace: Trace) -> str: ... async def get_trace(self, trace_id: str) -> Optional[Trace]: ... async def update_trace(self, trace_id: str, **updates) -> None: ... async def add_step(self, step: Step) -> str: ... async def get_trace_steps(self, trace_id: str) -> List[Step]: ... class MemoryStore(Protocol): async def add_experience(self, exp: Experience) -> str: ... async def search_experiences(self, scope: str, context: str, limit: int) -> List[Experience]: ... async def add_skill(self, skill: Skill) -> str: ... async def search_skills(self, scope: str, context: str, limit: int) -> List[Skill]: ... ``` --- ## 6. 事件系统 ```python @dataclass class AgentEvent: type: Literal[ "trace_started", "memory_loaded", "step_started", "llm_delta", "tool_executing", "tool_result", "conclusion", "feedback_received", "experience_extracted", "trace_completed", "trace_failed" ] data: Dict[str, Any] ``` --- ## 7. 与 LLM 提供商的集成 Agent 模块**不绑定**特定 LLM 提供商。通过 `LLMProvider` Protocol 抽象: ```python class LLMProvider(Protocol): async def chat( self, messages: List[Dict], model: str, tools: Optional[List[Dict]] = None, **kwargs ) -> AsyncIterator[LLMEvent]: ... ``` 宿主项目实现具体的 Provider(OpenAI、Anthropic、Azure 等)。 --- ## 8. 模块结构 ``` reson_agent/ ├── __init__.py ├── runner.py # AgentRunner ├── events.py # AgentEvent ├── models/ │ ├── __init__.py │ ├── trace.py # Trace, Step │ └── memory.py # Experience, Skill ├── storage/ │ ├── __init__.py │ ├── protocols.py # TraceStore, MemoryStore │ └── memory_impl.py # 内存实现 └── tools/ ├── __init__.py ├── registry.py # ToolRegistry, @tool └── schema.py # SchemaGenerator ``` --- ## 9. 设计决策 ### 为什么 Trace/Step 而不是复用 llm_call_history? - `llm_call_history` 是扁平的调用日志 - `Trace/Step` 是带因果关系的执行图 - Step 支持多种类型(llm_call, tool_call, conclusion, feedback) - Step 之间可以形成 DAG(不只是链表) ### 为什么存储可插拔? - 不同项目有不同的存储需求(PostgreSQL、Neo4j、MongoDB) - MVP 阶段用内存实现,快速验证 - 生产环境再接入持久化存储 ### 为什么工具系统要独立? - 工具注册和 Schema 生成是通用能力 - 可以在没有 Agent 的场景单独使用 - 与 LLM Provider 解耦 --- ## 10. 后续计划 ### Phase 1(当前):MVP - [x] 数据模型 - [x] 存储接口 + 内存实现 - [x] 工具系统 - [ ] AgentRunner 基础循环 - [ ] 测试 ### Phase 2:完善 - [ ] Experience 提取 - [ ] Skill 归纳 - [ ] PostgreSQL 存储实现 - [ ] 与 Resonote 集成 ### Phase 3:重构 LLM 模块 - [ ] 将验证过的设计合并回 Resonote/llm - [ ] 统一 call/stream/run