# 自动化记忆任务设计方案(v2) ## 1. 背景与目标 本方案用于重构自动化记忆能力,目标是: - 保持单一运行时框架,不并行维护第二套执行系统; - 在运行时中新增一层抽象,使 `router` 与 `executor` 的启用策略可配置; - 将记忆处理职责从通用 worker 中剥离为独立 `memory agent` 角色; - 保留审计能力与用户可见性隔离(自动输入可审计、默认对用户隐藏); - 维持与现有 `/api/v1/agent`、SSE、history 协议的兼容演进路径。 该版本是架构重构设计文档,重点解决职责边界与扩展性问题。 ## 2. 设计原则 1. **单框架,多角色** - 仍复用同一套 runtime、队列、持久化、SSE 通道; - 不再让 worker 承担所有领域职责。 2. **配置驱动执行拓扑** - 运行路径由配置决定:是否经过 router、最终由哪个 executor 执行; - 执行拓扑可被审计并可回放。 3. **记忆职责显式化** - 记忆提取、写入、遗忘由 `memory agent` 执行; - worker 继续承担通用对话/工具编排场景。 4. **默认安全最小权限** - 工具集必须是 `declared_tools ∩ allowlist`; - memory executor 默认仅开放记忆域工具。 5. **协议先行** - 任何对运行协议和数据结构的变更,先更新 `docs/protocols/` 再落地代码。 ## 3. 范围与非目标 ### 3.1 范围 - `automation_jobs` 引入执行拓扑配置,支持是否启用 router 与 executor 选择; - 运行时新增抽象层:`Execution Profile`; - 支持 executor 类型:`worker`、`memory`; - 自动任务默认使用 memory executor; - 消息可见性和审计策略保持增强。 ### 3.2 非目标 - 不引入复杂 DSL 编排语言; - 不开放无限制策略字段; - 不新增独立部署形态的第二运行时; - 不在本阶段改造前端交互形态(仅保证协议兼容)。 ## 4. 核心决策 1. **新增抽象层:Execution Profile(关键)** - 在 scheduler/orchestrator 与具体 agent 之间新增执行配置层; - 该层决定是否调用 router、调用哪个 executor、可用工具策略。 2. **executor 职责分离** - `worker executor`:通用任务、复杂工具编排、常规聊天; - `memory executor`:记忆提取、记忆写入、记忆遗忘、记忆总结。 3. **router 可配置启用** - 自动记忆任务默认 `enable_router=false`,减少不必要决策成本; - 普通 chat 默认 `enable_router=true`。 4. **拓扑合法性约束** - 必须保证至少有一个 executor; - 禁止出现 `enable_router=false` 且 `executor` 为空; - executor 仅允许枚举值:`worker | memory`。 5. **保持事件/审计统一出口** - 无论 executor 类型,SSE 与消息持久化走同一通道; - 仅扩展阶段字段枚举,不拆协议体系。 ## 5. 目标架构 ## 5.1 运行链路(重构后) ```text scheduler/api trigger -> execution profile resolver -> (optional) router step -> executor step (worker | memory) -> persistence + redis stream -> history/sse consumers ``` 与旧链路相比,变化点是新增 `execution profile resolver` 和 `memory executor`。 ## 5.2 Execution Profile 抽象 建议抽象(运行时内部模型): ```json { "name": "automation_memory_default", "enable_router": false, "executor": "memory", "tool_policy": { "mode": "intersection", "allowlist": ["memory_write", "memory_forget"] }, "history_policy": { "window": "today_yesterday" } } ``` 说明: - `enable_router`:是否执行 router 决策步骤; - `executor`:最终执行角色; - `tool_policy`:工具授权策略,默认交集模式; - `history_policy`:上下文窗口策略(保持最小化,不扩展过多字段)。 ## 5.3 默认 Profile 建议 - `chat_default` - `enable_router=true` - `executor=worker` - `automation_memory_default` - `enable_router=false` - `executor=memory` ## 6. 数据模型设计 ## 6.1 `automation_jobs` 调整 保留现有调度相关字段: - `id`, `owner_id`, `title`, `schedule_type`, `run_at`, `next_run_at`, `timezone`, `last_run_at`, `status` 新增/调整字段: - `config JSONB NOT NULL`:任务输入与工具声明; - `execution_profile JSONB NOT NULL`:运行拓扑配置(MVP 可先内联,后续可抽到 profile registry)。 建议结构: ```json { "config": { "prompt": "提取最近对话中的稳定记忆并写入", "tools": ["memory_write", "memory_forget"] }, "execution_profile": { "enable_router": false, "executor": "memory" } } ``` ## 6.2 Schema 约束 - `config.prompt`:必填非空,建议长度 `<= 2000`; - `config.tools`:必填数组,元素为已注册工具名; - `execution_profile.enable_router`:必填布尔; - `execution_profile.executor`:必填枚举 `worker|memory`; - `extra=forbid`,拒绝未知字段; - 执行前二次校验:`declared_tools ∩ runtime_allowlist`。 ## 6.3 `messages.metadata` 扩展 建议标准化字段: - `hidden_from_user: bool` - `origin: "chat" | "automation"` - `executor: "worker" | "memory"` - `execution_profile_name: string` 用途: - 用户视图过滤自动输入; - 审计可按 executor/profile 追踪行为; - 支持后续灰度比较(同任务不同 profile)。 ## 7. 运行时行为约束 ## 7.1 自动任务 - 会话类型:`session_type=automation`; - 自动输入消息:`role=user` + `hidden_from_user=true`; - 默认 profile:`automation_memory_default`; - executor:`memory`。 ## 7.2 普通对话 - 会话类型:`session_type=chat`; - 默认 profile:`chat_default`; - executor:`worker`。 ## 7.3 工具授权 - 输入工具集合来自 `config.tools`; - 实际可调用集合来自 `config.tools ∩ profile_allowlist ∩ system_allowlist`; - 对被拒绝工具记录审计日志与拒绝原因。 ## 8. 调度器设计 ## 8.1 扫描与触发 - 扫描条件: - `status='active'` - `next_run_at <= now_utc` - 命中后投递执行命令,命令中携带 `execution_profile` 快照。 ## 8.2 幂等与并发 - 幂等键:`job_id + scheduled_slot`; - 通过原子更新或行级锁抢占,防止重复执行; - 失败重试并保留错误上下文。 ## 8.3 时区策略 - 调度语义按用户本地时区(例如每日 10:00); - 存储执行点统一使用 UTC `next_run_at`; - 调度器仅按 UTC 扫描,避免多时区计算分散。 ## 9. 协议影响与兼容策略 本阶段是设计重构,协议建议如下: 1. `docs/protocols/agent/sse-events.md` - `STEP_STARTED/STEP_FINISHED.stepName` 从 `router|worker` 扩展为 `router|worker|memory`; - 当 `enable_router=false` 时,不产出 router step 事件。 2. `docs/protocols/agent/run-agent-input.md` - 增补运行上下文说明:内部执行可由 profile 决定 executor; - 对外 API 入参保持兼容,不强制前端传 executor。 3. `docs/protocols/agent/api-endpoints.md` - 增补说明:`/runs` 的运行阶段由后端 profile 决定,历史与 SSE 保持统一消费方式。 兼容要求: - 老客户端仍可消费现有事件; - 仅新增枚举值,不删除既有字段; - 如客户端未识别 `memory`,按未知阶段容错处理。 ## 10. 默认任务创建 用户创建后自动创建 daily 记忆任务: - `schedule_type='daily'` - 本地时区目标时间 `10:00` - `timezone` 优先用户设置,缺省 `Asia/Shanghai` - `config.prompt` 使用内置记忆提取模板 - `config.tools=["memory_write","memory_forget"]` - `execution_profile={"enable_router":false,"executor":"memory"}` ## 11. 安全与审计 安全约束: - 禁止越权工具调用; - memory 读写必须强制 owner 作用域; - 日志不输出敏感内容与完整私密上下文。 审计能力: - 自动输入、工具调用、输出全链路可追踪; - 可按 `origin/executor/execution_profile_name` 回放。 ## 12. 迁移与发布步骤 1. 更新 `docs/protocols`(先协议); 2. 新增 `execution_profile` schema 与运行时模型; 3. 数据迁移:历史任务写入默认 profile; 4. 运行时接入 profile resolver; 5. 引入 `memory executor` 并接管自动记忆任务; 6. 灰度:先新建任务使用 memory executor,再迁移存量任务; 7. 稳定后收敛旧逻辑分支。 ## 13. 测试与验收 ## 13.1 单元测试 - profile schema 校验(非法枚举、空 executor、未知字段); - 工具授权交集逻辑; - `next_run_at` 跨时区计算; - 隐藏消息过滤与审计字段落库。 ## 13.2 集成测试 - 自动任务触发后进入 memory executor; - `enable_router=false` 时无 router step 事件; - SSE `stepName=memory` 可被稳定消费; - 自动输入审计可见、用户历史不可见。 ## 13.3 验收标准 - 每日 10:00(用户本地时区)稳定执行; - memory 任务不经过 router 亦可稳定完成; - 工具权限边界有效; - 审计链路完整; - 对现有 chat 流程零回归。 ## 14. 实施顺序建议 1. 协议文档更新(`docs/protocols/agent/*`); 2. `automation_jobs` 数据结构改造与迁移; 3. profile resolver 与 executor 抽象接入; 4. memory executor 接入与工具边界验证; 5. 调度器联调与默认任务创建; 6. 端到端压测与灰度发布。 --- 本版(v2)将“抽象 Agent 运行”落到可执行的配置模型,核心是: - 新增一层 `Execution Profile`; - 将 `router` 和 `executor` 拓扑配置化; - 使用独立 `memory executor` 承载记忆职责; - 在不引入第二运行时的前提下完成大规模重构演进。