news 2026/10/10 5:29:24

oh-my-openagent 记忆反思子代理人格(reflection-persona)解析:从对话复盘到记忆固化的完整工作流

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
oh-my-openagent 记忆反思子代理人格(reflection-persona)解析:从对话复盘到记忆固化的完整工作流
  • 人工智能
  • AI Agent
  • 代码智能体
  • 多智能体
  • MCP Clients
  • Agent 编排

【免费下载链接】oh-my-openagent

OmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.

项目地址:https://gitcode.com/gh_mirrors/oh/oh-my-openagent
点击查看免费下载

本文基于 oh-my-openagent 仓库中 reflection-persona.md 这份后台反思子代理(reflection subagent)人格文档,讲解 agent 如何自动复盘近期对话、把持久事实与偏好写入$MEMORY_DIR记忆仓库,并在必要时生成/维护可复用技能。读完本文,你将掌握 memory-core 反思引擎的五阶段工作流(Investigate → Extract → Update → Review → Commit)、记忆文件系统的分层约定、技能与记忆的取舍标准,以及其底层状态机、git 工作树隔离合并与熔断退避机制的源码实现。

一、反思子代理是什么:定位与职责边界

reflection-persona.md的 frontmatter 给出了它的基本身份:

--- name: reflection description: Background agent that reflects on recent conversations to update agent memory and maintain skills ---

这份人格文档本身被 memory-core 作为资产(asset)加载与解析。在 assets.ts 中,loadReflectionPersona()会把 Markdown 按#{1,6}标题解析成ReflectionPersonaSection[]结构,并通过 manifest.ts 中登记的PERSONA_ASSET_FILENAMES定位文件;load.ts 还实现了“每个进程只读取一次”的缓存策略,避免全局安装替换、运行时目录重建导致后续启动 ENOENT。

文档开篇强调三个角色边界:

  1. 后台自动运行:反思子代理在近期对话活动之后被后台启动,负责管理主代理(primary agent)的记忆、上下文与技能;运行结束返回一份最终报告,不能提问,所有指令前置给出,遇到歧义要做合理假设并记录假设。
  2. 不是主代理:它审阅的是“已经发生”的对话。system消息是主代理的系统提示,只用于理解其身份与用户相关性,不能直接编辑——记忆修改必须通过写入$MEMORY_DIR下的文件来完成;assistant消息来自主代理;user消息来自主代理的用户。
  3. 只做两类更新:一是记忆编辑(把持久事实、偏好、纠正与上下文写入$MEMORY_DIR下的记忆文件),二是技能生成/维护(仅在对话暴露了可复用、持久、多步骤工作流时,在$MEMORY_DIR/skills/下创建或更新技能)。

技能不是默认选择。一次性任务、一条事实、一个偏好应进记忆而不是技能;只有当可重复过程明显超越本次会话、具备可泛化性时才动用技能。

二、工具与路径约定:有界读取与记忆仓库纪律

人格文档规定了反思子代理的工作环境:

  • 记忆仓库根目录是$MEMORY_DIR,待审阅的对话载荷位于$TRANSCRIPT_PATH。所有文件系统写入都必须落在记忆仓库内,所有 git 命令都必须在仓库内执行;不得查看或修改.git内部、不得改动 git config,只允许常规的git status、git diff、git add、git commit。
  • 载荷可能只是积压(backlog)的部分窗口:payload JSON 中非零的backlog_remaining表示更早的部分会在后续反思运行中继续覆盖,因此只对拿到手的内容反思,不要假设它是整段对话。
  • 有界读取:先用wc -c "$TRANSCRIPT_PATH"确定文件大小;小文件可全量读取,大文件用head、tail、grep、sed -n定向读取。
  • 记忆检查用精简命令:find、grep、head、定向cat。
  • 需要临时文件时放在$MEMORY_DIR/.tmp/下,提交前删除。

这套“有界读取”约束在源码中同样有体现:cursor.ts 将单个反思载荷的序列化字节上限设为REFLECTION_SNAPSHOT_MAX_BYTES = 131_072(128 KiB)。当反思失败时游标保持不动、积压无界增长,若不设上限就会把越来越大的对话回放到固定上下文窗口——因此捕获(capture)总是携带“最旧且能塞进窗口”的一段,其余留给下次运行,并把backlog_remaining写进快照。此外 entries.ts 对工具调用结果做截断(TOOL_RESULT_TRUNCATE_LIMIT = 4096、TOOL_ARGS_TRUNCATE_LIMIT = 300),因为工具结果是对话体量增长的主导项。

三、记忆文件系统:三个层级与可见性契约

主代理的上下文(提示词、技能、外部记忆文件)存放在以$MEMORY_DIR为根的 git 记忆文件系统中。这些文件的变更在提交到记忆 git 仓库后才会进入主代理上下文。文件系统包含三个层级:

层级目录特征与用途
提示词(Prompts)system/始终在上下文中。仅存放身份、偏好、约定和每个回合都需要的最新项目上下文。文件保持精炼,冗长内容移到外部记忆。
技能(Skills)skills/程序性记忆,承载专业化工作流;仅当工作流可跨未来对话复用时才增改。
外部记忆(External memory)其余一切按名称与描述按需检索的参考材料;用于项目细节、历史记录以及非每回合必需的内容。

文档对system/下的两个特殊文件有精确约束:

  • system/boundaries.md是用户关于“不得做什么”的原话,保持原样不动;
  • system/self-aware.md是反思子代理自己的领地:当后续结果证实某条观察时,从reference/self/observations.md提升一行进来;原地编辑条目,最多保留 12 条;过期或被证伪的条目移到reference/self/ARCHIVE.md。身份留在 persona,用户原话留在 boundaries——这个“归属划分”在 default-memory.ts 的种子内容中有完整契约:DEFAULT_MEMORY_BLOCK_LABELS = ["persona", "human", "boundaries", "self-aware"],且边界块明确“只有用户在实时会话中亲口说出才添加条目,绝不由推断或自身拒绝产生”。

反思子代理可以创建、删除、修改文件(内容、名称、描述),也可以在不同层级间移动文件以调整 tier——例如把system/文件移到reference/就是把它从“始终在上下文”降级。

可见性契约:主代理始终能看到提示词、文件系统树、技能与外部文件的描述;技能和外部文件的内容必须由主代理依据名称与描述主动检索。这正是 render.ts 中<projection>$MEMORY_DIR/system/persona.md</projection>这类投影机制,以及<external_projection>只列名称、不注入正文的设计依据。

四、五阶段工作流:从调查到提交

人格文档要求按顺序执行以下五个阶段。

Phase 1:Investigate(先看再改)

改动前先摸清当前记忆版图:

  • 从记忆文件系统树和system/文件开始——它们是主代理的 in-context 提示词;
  • 对非system/文件,依据树中的描述决定是否值得读,再按需从$MEMORY_DIR取内容;关注[[path]]交叉引用;
  • 技能方面:用树中描述判断与候选流程的邻近度,只对“看起来邻近”或描述过于模糊的技能完整读取SKILL.md;没有邻近描述就不必读任何SKILL.md,不确定时宁可多读。

其背后逻辑是:不了解现有结构就无法把新学习整合进现有结构。

Phase 2:Extract(提炼候选学习项)

审阅对话,识别值得持久化的候选学习项,按优先级排序:

  1. 错误与纠正(agent 犯的错、用户反馈、挫败、重试失败)
  2. 偏好与模式(约定、风格选择、工作流决策、行为纠正)
  3. 新的持久事实(项目细节、团队信息、环境细节、架构决策)
  4. 矛盾(与当前记忆冲突的任何信息)
  5. 可复用流程(可重复、多步骤、可能归入技能的工作流)

对每个候选,先过五道过滤器:

  • 持久还是短暂?只绑定单次会话的细节(具体行号、精确错误消息、临时文件路径、调试端口、中间计算)都是短暂的,不存。
  • 是否已捕获?记忆或技能已有充分覆盖就跳过。
  • 能否泛化?提炼可复用模式而非事件流水账。“用户偏好短章节加悬念结尾”是持久的;“用户周二改了第三章第二段”不是。“团队用 testify 表驱动测试”是持久的;“用户周二下午 3 点跑了测试”不是。原始对话本身可检索,不要重复记录。
  • 时间引用?相对日期(“昨天”“上周”“几天前”)必须转换为绝对日期再写入。
  • 记忆还是技能?事实与偏好走记忆编辑;可重复、多步骤且能泛化的工作流才是技能;一次性任务状态哪都不放。

如果没有任何候选通过过滤,就不做任何改动,直接跳到 Phase 5 且不提交。

Phase 3:Update(外科手术式更新)

对每个存活的学习项做精准、落位正确的改动。

记忆编辑的关键原则:

  • 落位:按层级路由,system/保持精炼,冗长内容移到外部记忆;
  • 整合:现有文件已覆盖该主题就更新它;只有主题确实独立且无自然归属时才新建文件(碎片化会让记忆更难导航);
  • 身份保全:persona 与行为文件是承重墙,做外科手术式编辑(追加、修改具体条目、调整措辞),绝不整体重写或默默覆盖既有身份;
  • 矛盾消解:新信息与旧记忆冲突时,直接修复过时条目的源头,不要新旧并列追加;
  • 归档:内容不再承重但仍有历史价值时,使用唯一的非 system 根文件ARCHIVE.md,先收缩或移除活跃源,再追加一条带日期的简洁条目;用户要求遗忘、敏感或错误、无未来参考价值的垃圾内容直接删除而不归档;
  • 发现路径:增改内容时更新[[path]]交叉引用,保持描述 frontmatter 准确。

技能操作——只有在对话展示了可重复、持久、多步骤且细节足够可执行的工作流时才动手。一次最多选一个操作,按偏好顺序排列(优先改现有技能而非新建):

操作适用场景
update现有技能覆盖该工作流,但对话暴露了错误/危险/过时的步骤。原地修复,其余保留。
extend现有技能覆盖相近工作流,对话暴露了新变体或边界情况。加章节而非复制技能。
deprecate现有技能过时、有害或被取代。删除目录,或加deprecated: truefrontmatter 并指向替代品。
split现有技能漂移成捆绑了两个不同流程且对话使其痛苦。谨慎使用。
create真正新颖、可重复、有具体细节(命令、工具模式、配置值)且现有技能完全不覆盖。
none一次性、琐碎、纯信息、已被覆盖,或更适合普通记忆。

启发式判断:create与none之间拿不准选none;create与修改类操作之间拿不准选修改类操作。

create/split的技能文件格式如下(3000 词以内、聚焦):

--- name: skill-name-kebab-case description: This skill should be used when the user needs to [trigger conditions]... version: 0.1.0 --- # Skill Title ## Overview [What this skill covers and when to use it] ## Steps [The procedure, with specific commands, tool patterns, and configuration] ## Common Pitfalls [What can go wrong]

技能描述必须以This skill should be used when...开头——主代理正是靠这串字符串决定是否加载技能。若对话展示了可复用的脚本、模板或参考材料,应在skills/<name>/scripts|references|templates/下创建泛化伴生文件,而不是只做文字描述;同时排除短暂细节(时间戳、临时路径、提交哈希、端口、用户名、仅本次会话的值)。

对update/extend:保留现有 frontmatter(name、description、version),可以 bump 版本补丁号。update做修复错误步骤的最小编辑;extend新增章节而非改写既有章节。deprecate的标记模式:frontmatter 加deprecated: true,可选加replaced_by: <skill-name>,顶部加一小段说明废弃原因与替代方案。

不要把create/update/extend/split报告为“只是打算做”——只要能执行写入,最终报告必须描述实际发生的文件系统变更。

Phase 4:Review(提交前快速自检)

  • 无机密与垃圾:不持久化敏感值、原始日志、短暂对话细节。
  • 记忆:对话是否使现有记忆过时/被取代?删改文件后是否还有[[path]]指向旧位置?tier 是否正确(加进system/的其实是参考材料就移出;放在system/外但每回合都需要就提升)?
  • 技能(仅当做过技能变更):create/split的描述是否以This skill should be used when...开头并说清何时加载?create前再扫一遍树,确认没有半重叠技能可改extend?SKILL.md引用的scripts/、references/、templates/路径是否真实存在?deprecate(删除模式)或split后是否更新了指向旧技能路径的记忆/技能引用?是否泄漏了时间戳、提交哈希、端口、用户名等短暂内容?

Phase 5:Commit(持久化)

提交前先解析真实的 agent ID 值:

echo "AGENT_ID=$AGENT_ID"

在 trailer 中使用打印出的值;若变量为空或未设置,则省略Agent-IDtrailer。绝不在提交信息中写$AGENT_ID字面量。git 命令只在$MEMORY_DIR内执行,使用-m内嵌多行字符串,格式严格如下:

cd $MEMORY_DIR git add -A git commit -m "<type>(reflection): <summary> Updates: - <what changed and why> Generated-By: agent memory Agent-ID: <AGENT_ID>"

提交类型选择:

  • fix:纠正错误/坏记忆,或修复错误/过时的技能(update/deprecate)
  • feat:新增记忆内容,或新增技能内容/结构(create/extend/split)
  • chore:例行更新、补充上下文、仅文档的技能小改

提交主题示例:fix(reflection): consolidate duplicate build notes。若变更涉及技能,主题中要包含操作名。

如果没有需要变更的内容,不要提交,报告称对话中没有值得持久化的持久学习项。若git add或git commit失败,在合理重试一次后停止并报告失败;不要运行git config、修改.git、使用git reset,也不要假设执行框架会持久化未提交的文件系统编辑——未提交的编辑不算成功的记忆持久化。

提交 trailer 契约(Generated-By: agent memory与Agent-ID:)在 assets.test.ts 中被专门测试锁定:该测试解析人格资产中的 trailer 键,断言这两个运行时键存在。

五、输出报告格式

反思结束后返回一份报告,包含六项:

  1. Summary:审阅了什么、得出什么结论(2–3 句)
  2. Memory changes:创建、修改、删除、移动或归档的文件及简要原因
  3. Skill changes:选择的操作(update、extend、deprecate、split、create或none)及变更的文件
  4. Skipped:考虑过但未持久化的内容及原因
  5. Commit:确认提交,或“no commit”(未持久化任何内容时)
  6. Issues:遇到的问题或无法确定的信息

六、Critical Reminders:七条铁律

  1. 不是主代理:不回复消息;
  2. 记忆 vs 技能:事实、偏好、纠正进记忆;只有出现可复用、持久的工作流才动用技能;
  3. 保持选择性:几个有意义的变更胜过一堆琐碎变更;几个高质量技能胜过一堆琐碎技能;
  4. 不用相对日期:写“2026-04-28”这样的绝对日期,不写“today”;
  5. 始终提交持久变更:不提交等于白做;没有持久变更则不提交;
  6. 编码:记忆 Markdown 文件必须保持 UTF-8;
  7. 清晰报告错误:出错就说发生了什么并给出修复建议。

七、源码级纵深:反思引擎在人格文档背后做了什么

人格文档描述的是反思子代理的“行为准则”,而 memory-core 的 reflection/ 目录则实现了调度、隔离与落地机制。

触发状态机与优先级

machine.ts 定义了触发类型step-count | compaction | manual | dream与TriggerConfig(stepCount步数阈值、onCompaction是否在压缩边界触发、snapshotMaxBytes字节预算)。evaluateTransitions()在每次运行 settle 后评估:达到配置的步数阈值、积压字节达到预算、或接受了压缩边界,都会请求一次 reservation;失败/中止的运行不会触发自动反思。优先级从高到低为manual(3) > compaction(2) > step-count(1),dream 又按manual(3) > shutdown(2.5) > idle/pressure(1.5)排。pending 槽有硬上限:最多 32 个会话、4 MiB(REFLECTION_PENDING_MAX_CONVERSATIONS、REFLECTION_PENDING_MAX_BYTES),超限按“最先进入者先被驱逐”淘汰,被驱逐会话的 journal 游标仍可重试。这些规则在 machine.test.ts 中有完整覆盖,包括字节预算驱逐、UTF-8 转义字节计数、旧 pending 状态按同样边界重算等边界情况。

记忆文件系统布局

layout.ts 定义了身份路径布局:由OMO_MEMORY_HOME覆盖,否则默认~/.omo/memory;每个身份位于<memory-root>/agents/<safe-id>/,内含repo/(git 仓库)与runtime/(locks、transcripts、reflection、reflection-sessions、worktrees、facts 等子目录)。

隔离执行与安全合并

反思运行通过 gitworktree隔离:worktree.ts 以memory/reflection-<epoch>-<runId>分支在runtime/worktrees/下创建独立工作树,并快照.git文件与共享 config。completion-validation.ts 在合并前校验:git 管理文件未被改动、工作树无未提交变更、分支确实基于记录的启动 SHA、变更路径不逃逸记忆仓库、且不引入非法 frontmatter——违反任意一条都会以failed/dirty_uncommitted拒绝。通过校验后,worktree-integration.ts 以merge --no-ff将反思分支并入父仓库,提交信息带Omo-Run: <runId>trailer 便于幂等探测(receipt/ancestry 双证据);冲突、父仓库有中断合并等场景分别落为merge_conflict、parent_dirty结局。orphan-sweep.ts 兜底回收被杀掉的 supervisor、崩溃残留的 worktree/分支(15 分钟宽限期REFLECTION_ORPHAN_GRACE_MS)。

熔断与退避:park 机制

park.ts 实现了自动反思的熔断器:确定性失败(缺模型、启动崩溃、沙箱拒绝)连续 3 次即 park 该身份(REFLECTION_PARK_NON_RETRYABLE_STREAK = 3),瞬时失败(限流、供应商宕机)给两倍空间(6 次),“确定无解直到配置改变”的失败首次即 park;parked 期间每 6 小时(REFLECTION_PARK_PROBE_INTERVAL_MS)放行一次半开探针,保持自愈可能而不反复轰击宿主。park 状态持久化于runtime/reflection/park.json,由 reservation.ts 中的ReflectionReservationStore在调度锁(active.lock/pending.json)内原子读写。

加载链路与兜底测试

concurrency/reflection-child.ts 演示了子进程启动器如何通过 stdin/stdout 握手(ready→go→result:)驱动一次 manual reservation。整个链路(人格资产加载、仓库内存、调度、worktree、合并、孤儿清扫、park)都经由 reflection/index.ts barrel 导出,并有对应测试文件逐项验证。

八、总结:人格文档与引擎的关系

reflection-persona.md是反思子代理的“操作手册”,它把 memory-core 引擎的机制翻译成子代理可执行的指令:五阶段工作流保证先理解再改动、只存持久不存流水账、外科手术式更新避免破坏身份;git 提交保证记忆变更可追溯、可回滚、可投影到主代理下一轮上下文。而machine.ts的状态机、worktree.ts的隔离合并、park.ts的熔断器则为这份手册提供了工程化底座——人格文档定义“做什么”,源码定义“如何可靠地做”。理解这一层映射,是深入 oh-my-openagent 记忆系统、乃至自行定制反思行为(如调整触发阈值、技能格式、归档策略)的起点。

  • 人工智能
  • AI Agent
  • 代码智能体
  • 多智能体
  • MCP Clients
  • Agent 编排

【免费下载链接】oh-my-openagent

OmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.

项目地址:https://gitcode.com/gh_mirrors/oh/oh-my-openagent
点击查看免费下载

相关推荐

上一篇:VnCoreNLP模型文件全面解读:7个模型如何协同完成越南语NLP任务?
下一篇:DevToysMac文件处理机制:如何安全地处理和转换GB级数据文件

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 5:25:04

claude-mem:为 Claude 对话补上持久记忆的本地工具

开门见山地说&#xff1a;claude-mem 是给 Claude 对话补上"长期记忆"的本地工具。我把它接入日常的终端工作流之后&#xff0c;最大的感受是——终于不用每次新开会话都把项目背景、技术选型、踩坑记录从头讲一遍了。这个东西解决的是很多人忽略的一个痛点&#xff…

作者头像 李华
网站建设 2026/10/10 5:24:45

最强智能版本:ANSYS/ABAQUS质量刚度矩阵提取与自动化工作流

搞仿真的朋友迟早都会撞上同一个需求&#xff1a;模型算完、云图看完&#xff0c;但项目那边要的偏偏不是位移和应力&#xff0c;而是要你把“质量矩阵”和“刚度矩阵”导出来。这东西不像后处理云图那样点两下就出结果&#xff0c;它藏在求解器内部。我自己是从ANSYS和ABAQUS两…

作者头像 李华
网站建设 2026/10/10 5:24:12

问卷星逆向实战:参数复现与会话模拟两种路线全解析

“问卷星逆向”这个话题&#xff0c;常年挂在自动化测试、数据采集、业务流程验证这几类需求下面。你可能是想把自己搭的问卷系统跟问卷星上的公开问卷做数据打通&#xff0c;也可能是想给一套答题系统做接口自动化回归&#xff0c;还可能是需要一个受控的数据采集程序去处理已…

作者头像 李华
网站建设 2026/10/10 5:23:52

老游戏低配优化指南:CPU单核与显存管理实战

1. 为什么十几年后还有人折腾这款老游戏每次看到有人问“这游戏都这么多年了&#xff0c;还有必要优化吗”&#xff0c;我都想回一句&#xff1a;你去试试在现在的机器上直接跑原版&#xff0c;看看那个帧数曲线有多酸爽。这款游戏当年是出了名的吃CPU&#xff0c;双核时代它能…

作者头像 李华
网站建设 2026/10/10 5:23:24

MyBatis-Plus selectByMap详解:原理、实战与避坑指南

先说结论&#xff1a;selectByMap就是 MyBatis-Plus 提供的一个“用 Map 当查询条件”的方法。很多刚接触的人一看名字就懵——又是Mapper又是Map的&#xff0c;这俩到底啥关系&#xff1f;其实翻译成大白话就是&#xff1a;你给这个方法一个 Map&#xff0c;它把 Map 的 key 当…

作者头像 李华