AinoWork v2.0 不是一个功能堆叠版本,而是一次方向性的重新思考。本文从 Harness 工程的弹性设计出发,拆解「记忆」和「计划模式」两个核心功能的实现思路------不做 RAG、不写死流程,而是用更灵活的方式让模型能力真正发挥出来。
一、从 v1.0 到 v2.0:一次方向性的重新思考
v1.0 做的事情很朴素:把 Hermes-Agent 从 CLI 搬上 Web,加上 Docker 沙箱和多用户 RBAC,让一个原本只能单人命令行使用的 AI Agent 变成团队可用的效率工具。这个目标基本达成了------一条命令部署,开箱即用,每个 Agent 拥有独立的 Docker 容器作为"工位"。
但 v1.0 发布后我意识到一个问题:把 Agent 搬上 Web 只是第一步,真正的挑战在于 Harness 层的工程深度。
什么是 Harness?简单说就是模型和用户之间的"中间层"------它决定模型能看到什么上下文、以什么方式接收指令、在什么约束下执行任务。Harness 工程是基于模型能力的衍生工程,这意味着一个核心矛盾:

真正好的 Harness 设计,不是选一边站,而是在同一个系统里同时容纳这两种策略。 就像给 AI 的"工位"------你不会给实习生和架构师完全相同的工具配置,但他们应该在同一个办公室里工作。
带着这个思路,v2.0 选择了「记忆」和「计划模式」两个方向来深化 Harness 工程。这两个方向不是随手选的------它们是 Harness 工程中最能体现差异化能力的两个环节,也是我从长期 AI Coding 实践经验中提炼出的有效模式。
二、记忆功能:不做 RAG,做「读小说」式的记忆整合
提起"记忆"功能,技术圈的第一反应往往是:上 RAG(检索增强生成)。分片、Embedding、向量检索、调召回率------这套流水线已经被讨论了无数次。
但经过一段时间的探索和实验,我发现 RAG 在记忆场景下存在两个难以逾越的问题。
2.1 RAG 为什么不够好
第一个问题:语义鸿沟。
向量模型和生成模型之间存在天然的"理解差异"。Embedding 认为语义相近的片段,LLM 可能认为毫无关联;反之亦然。这不是调优召回率能解决的问题------两个模型的语义空间本质上不对齐。即使你把 Top-K 从 5 调到 20,多召回的片段可能只是"看起来相关"的噪音。
第二个问题:片段式理解的危害。
分片检索天然丢失了上下文。一段记忆被切成三块,每块单独看语义都没问题,但拼回去的理解却是歪的------就像一个故事被剪成碎片随机排列,你得到的不是一个完整叙事,而是一堆孤立的、可能互相矛盾的陈述。
2.2 换个思路:从「检索」到「回忆」
试想一下,当你在读一本 100 万字的小说,不可能一次性读完,甚至要读好几天。那么,当隔天重新拿起这本书时,你是怎么"召回"前文的?
你不是把全书切成 512-token 的片段再向量检索。你是在大脑里快速过一遍:上次发生了什么?关键人物是谁?核心矛盾是什么? 形成几个压缩过的心理锚点,然后继续往下读。
AinoWork v2.0 的 Auto-Memory 就是按这个思路设计的:
每次发起新对话时,用一个 LLM 把所有记忆文件重新整理成一份结构化摘要,注入系统提示词。 不做检索,做"回忆"。

具体实现上,Auto-Memory 是一个双层整合系统:
全局整合层: 每次新对话启动时,检查是否有记忆文件被创建或修改。如果有变更(change-gated,而非 time-gated),按重要性从高到低分批发送给一个专用的整合模型(temperature=0.3,max_tokens=2048),合并为一份不超过 8,000 字符的结构化摘要,按 Preferences、Conventions、Environment、Decisions 四个主题组织,写入 AUTO-MEMORY.md。
项目级提取层: 在项目会话中,每 N 轮(默认 10 轮)分析对话记录,提取项目相关的知识(技术栈偏好、架构决策、环境配置等),写入项目作用域的 AUTO-MEMORY.md。
一个值得注意的设计:整合是 change-gated 而不是 time-gated 的。 如果用户没有写入新记忆,就不会触发 LLM 调用------这意味着 LLM 成本与实际写入活动成正比,而不是随时间累积。
2.3 艾宾浩斯遗忘曲线:记忆需要「遗忘」机制
一个反直觉的设计:好的记忆系统不是记住越多越好。无关记忆挤占上下文窗口就是噪音。
v2.0 引入了一个基于艾宾浩斯遗忘曲线的衰减引擎:
- 每条记忆拥有
importance_score(0-1)和decay_factor(默认 0.9,即每天衰减 10%) - 重要性随时间递减:
new_score = importance_score × decay_factor^days_since_access - 当记忆被检索(通过
memory_search读取),重要性自动 boost ×1.05(模拟间隔重复强化),上限 1.0 - 当日被访问的记忆不衰减
三个关键阈值控制整个生命周期:
| 阈值 | 默认值 | 含义 |
|---|---|---|
| 注入阈值(injection) | 0.2 | 低于此分数的记忆不注入系统提示词 |
| 归档阈值(archive) | 0.05 | 低于此分数的记忆进入归档候选 |
| 连续归档周期 | 3 次 | 连续 N 次低于归档阈值才真正归档 |
以默认参数计算:一条初始重要性 1.0 的记忆,如果从未被访问,大约 30 天后 会降到 0.05 以下,再经过 3 个衰减周期确认后进入 archive/ 目录。

2.4 记忆注入的优先级链
系统提示词中记忆的注入遵循一条明确的优先级链:

这套链路的设计要点:当 AUTO MEMORY 可用时,它替代而非叠加 PERSISTENT MEMORY。 两者不会同时注入------因为 AUTO MEMORY 本身已经是从 PERSISTENT MEMORY 中提炼出的精华,同时注入反而是冗余。此外,整合是变化驱动的------没有新写入就不触发 LLM 调用,成本与写入活动成正比。
三、计划模式:澄清 → 计划 → 执行的三段式工作流
计划模式是人与模型之间沟通的重要机制。它承担着几个核心职责:「澄清事实」、「对齐见解」、「让工作流可视」、「尽可能完整地执行一个任务」。在模型尚未完全能自主做事之前,这些可控性显然是非常重要的。
3.1 同类工具的实践对比
在讨论 AinoWork 的实现之前,先看看市面上几种典型的计划模式设计:
| 工具 | 实现方式 | 特点 | 推测 |
|---|---|---|---|
| Hermes-Agent 原生 | Plan 作为 Skill,通过增强用户消息实现 | 单一职责------"写 plan.md,不干别的" | 源码可见,简单直接 |
| Trae Solo | 拆分为 /Spec 和 /Plan 两个指令 |
独立的 Loop 工作流,编程场景优化的提示词 | 推测内置指令 + 独立流程 |
| Claude Code | 内置计划文件追踪,当前会话与计划文件绑定态 | 状态追踪 + 可见性措施,系统提示词 + 增强用户消息 | 推测双层注入 + 独立 Loop |
| AinoWork v2.0 | 连续多轮对话形式,澄清/计划/执行三阶段 | AI 自主选择工作流深度,弱限制提示词 | 消息增强 + 状态机 + plan_id 跨轮持久化 |
每种实现都在回答同一个问题:如何在不限制模型能力的前提下,让人类参与到决策过程中?
3.2 AinoWork 的设计:AI 自主选择深度
v2.0 的计划模式引入了三个工作流深度,由 AI 根据任务复杂度自主选择:

核心实现上,计划模式的关键设计决策有四个:
1. 消息增强而非系统提示词修改。 PlanModeExecutor 读取当前 round 的 spec_state 和 spec_file_path,构建阶段适配的消息增强文本,以 volatile_context_override 的方式前置到用户消息之前------而不是去改系统提示词。这意味着计划模式的引导信息与用户的原始消息在同一个"通道"里到达模型,模型的注意力分配更自然。
2. plan_id 跨轮持久化。 进入计划模式时生成 plan-{12位hex} 的唯一 ID,同一会话内的后续轮次继承这个 ID。所有产物(spec.md、plan.md、相关文件)都在 .aino/plans/{plan_id}/ 目录下。取消计划时清空 plan_id,下次进入生成新的。
3. 弱限制提示词。 这是全文最核心的设计理念。计划模式的提示词不写"你必须先做 X 再做 Y",而是:
- 不设负面工具约束("trust the LLM's judgment")
- 不强制的模式声明("autonomous assessment, not a rule")
- 丰富的计划编写指导("makes planning engaging rather than something the LLM wants to skip")
- 自然的暂停点("the user will review" 而非 "STOP and WAIT")
4. 三段式用户消息增强。 根据当前阶段,注入不同的上下文:
| 阶段 | spec_state | 增强内容 |
|---|---|---|
| 初始评估 | null(首次进入) |
Plan Mode 介绍 + 三种工作流深度说明 + 计划编写指导 |
| 需求澄清 | 已有 spec.md 但未确认 |
SPEC 完善引导 + 代码库研究方法提示 |
| 计划生成 | spec_ready + spec.md 已确认 |
"读 SPEC → 写 plan.md → 等用户确认" |
| 执行 | plan.md 已确认 | 按计划逐项执行 |
3.3 「弱限制」设计哲学的实战验证
从源码中可以看到,build_spec_phase_context() 的三个分支总共不到 100 行提示词。对比一些商业产品动辄数百行的 system prompt 模板,v2.0 选择了克制。
这个选择的依据是:2026 年的主流模型已经足够强了。 当模型能自主推理、自主探索代码库、自主判断复杂度时,Harness 的职责不是"告诉模型每一步该做什么",而是"告诉模型当前处于什么阶段、有哪些选项可用",然后信任模型的判断。
但弱限制不等于没限制。三段式设计本身就是一个温和的约束框架------模型知道自己在澄清阶段应该多提问、在计划阶段应该写 plan.md、在执行阶段应该按计划行事。这些约束足够轻量,不会压制强模型的能力,但对于弱模型来说又提供了足够的结构引导。
这正是文章开头提到的 Harness 弹性设计在实践中的体现。
四、避坑指南
以下是在设计和实现记忆系统、计划模式时踩过的坑。每个坑背后都是一个被推翻的假设。
避坑 1:RAG 分片大小是伪命题
在尝试 RAG 方案时,我花了不少时间调 chunk size------256、512、1024 token 都试过。最终发现无论怎么切,语义碎片化的问题都不会消失。根因不在分片策略,在于向量检索和 LLM 语义理解之间的架构性 mismatch:Embedding 衡量的是"文本表面相似度",而 LLM 需要的是"上下文关联性"------这两者之间的鸿沟无法通过调参弥合。如果你发现记忆系统总是"差点意思",别纠结分片参数了,考虑换架构。
避坑 2:记忆不"遗忘"等于噪音
一开始设计记忆系统时很容易陷入"存越多越好"的陷阱。但实际跑起来后发现:30 天前某次临时调试的配置和当前项目毫无关系,却依然占据着系统提示词的 token 配额。没有遗忘机制的记忆系统,最终会退化为一个"什么都有、什么都找不到"的垃圾堆。引入艾宾浩斯衰减后,注入提示词的记忆条目从平均 40+ 条降到了 15 条左右------少了一半,但每条都跟当前上下文相关。
避坑 3:定时触发不如变更触发
最初的 Auto-Memory 设计是每 24 小时运行一次整合。很快发现这很蠢:用户可能一周不写新记忆,却每天白白消耗一次 LLM 调用。改为 change-gated------只在 MemoryRecord 有实际变更时才触发整合------LLM 成本直接跟写入活动挂钩,零写入就是零成本。这对个人开发者和小团队尤为重要,毕竟不是每个项目都需要每天"回忆"。
避坑 4:阶段控制放在 system prompt 里效果很差
早期把计划模式的阶段信息("你处于澄清阶段")放在系统提示词中。结果发现当用户消息很长时------比如贴了一大段代码或日志------模型几乎完全忽略了阶段信息。推测原因是 system prompt 在注意力机制中属于"背景",而用户消息是"前景"。改为消息增强------把阶段上下文直接 prepend 到用户消息前面------模型对当前阶段的感知准确率提升非常明显。这个教训可以推广:不是所有"给模型的指令"都适合放 system prompt------跟当前任务直接相关的阶段性引导,放在消息里更有效。
避坑 5:弱限制不是零限制
在追求"最小干预"时,我一度把计划模式的提示词减到几乎只剩一句话:"你处于计划模式,请制定计划。"结果弱模型完全不知道该干什么------它既可能直接执行跳过计划,也可能陷入无限的分析循环。后来才意识到:弱限制不等于零限制。 三段式设计(澄清 → 计划 → 执行)本身就是一种温和的约束框架------它不告诉模型每一步该做什么,但明确告诉模型"你现在处于什么阶段、有哪些选项"。这个层级的引导对强模型来说几乎感觉不到束缚,对弱模型来说却是能正常工作的底线。
五、总结
AinoWork v2.0 不是一次功能堆叠,而是一次对 Harness 工程深度的重新思考。从"把 Agent 搬上 Web"到"让 Agent 拥有真正的记忆和计划能力",本质上是在回答一个问题:当模型越来越强,人类应该以什么姿势与 AI 协作?
记忆功能放弃 RAG 而选择"读小说"式的整合模式,计划模式放弃强限制而选择弱限制的三段式------这两个选择背后的逻辑是一致的:Harness 的职责不是替代模型思考,而是为模型创造一个能充分施展的「工位」。
下一步,我会继续观察不同模型在弱限制计划模式下的表现差异,以及艾宾浩斯衰减参数在不同使用场景下的最优配置。如果你对 Harness 工程设计有想法或踩过类似的坑,欢迎交流。
常见问题
Q:不做 RAG 做"回忆",是不是意味着放弃了精确检索?
A:这是一个需要正视的取舍。RAG 的优势在于"找到包含关键词 X 的那段话"------精确、可复现。但记忆场景的核心需求往往不是"找到那段话",而是"在当下时刻,我需要知道什么"。整合模式牺牲了精确检索的确定性,换来了跨文件关联理解和冗余消除------比如三份记忆分别记录了同一台服务器的不同配置细节,RAG 会返回三个片段让你自己拼,整合模型会直接给你一句"服务器配置:xxx,位于 yyy"。如果你的场景是知识库问答,RAG 仍然更好;如果你的场景是"让 Agent 在每次对话开始时建立对用户和项目的整体认知",整合模式更合适。两者不互斥,可以在不同层级配合使用。
Q:用 LLM 做记忆整合,成本会不会失控?
A:这是我最开始也担心的。实际跑下来,两个设计让成本很可控:一是 change-gated------不写新记忆就不触发,不是按时间累积的固定开销;二是整合模型可以独立配置一个便宜的小模型(比如 GPT-4o-mini 或 DeepSeek-V3),不需要用主对话模型。几百条记忆文件整合一次的成本通常在几美分级别。对个人开发者来说,一天写几次记忆,一个月花不了一美元。
Q:艾宾浩斯衰减参数怎么定?0.9 的衰减因子有什么依据?
A:说实话,0.9 这个值不是从论文里推导出来的,是从使用习惯反推的。以默认参数算,一条记忆从创建到归档大约 30 天------这大致对应一个开发迭代周期。一个 sprint 结束后,上个 sprint 的临时调试笔记确实应该"降温"了。boost 因子 1.05 设得比较保守,是为了防止一次偶然的检索就把无关记忆永久钉在活跃区。这些参数最终应该开放给用户调整,因为不同场景(日常开发 vs 学术研究 vs 运维巡检)的记忆"保质期"差别很大。
Q:为什么选择消息增强而不是 system prompt 来做阶段控制?
A:这个问题在避坑 4 里详细展开了,补充一点设计层面的考量:system prompt 每轮对话都会被模型重新处理,如果你频繁修改 system prompt(比如每轮切换阶段状态),会破坏 prompt caching,大幅增加首 token 延迟和成本。而消息增强是 per-round 的自然行为,不影响缓存策略。另外从模型行为观察来看,prepend 到用户消息前的内容在注意力分布中明显比 system prompt 末段更"重"------这可能跟大多数模型的训练数据分布有关。
Q:弱限制的设计,在弱模型上真的能正常工作吗?
A:诚实地说------取决于"多弱"。对于当前主流的云端模型(GPT-4o、Claude Sonnet、DeepSeek-V3 等),弱限制完全够用,甚至比强限制表现更好------因为模型有足够的判断力来利用自由度。对于早期的开源小模型(7B 以下),三段式结构本身提供的基本框架("你在澄清阶段,多提问")也勉强能跑,但偶尔会出现跳过计划直接执行的情况。有意思的是,同样弱限制的提示词,在不同模型上的"越界"方式各不相同------有的过于保守(反复确认),有的过于激进(跳步)------这本身就反映了模型的"性格"差异。在模型能力快速提升的 2026 年,我个人倾向于押注弱限制方向:给模型留余地,比替模型做决定,保质期更长。
AinoWork 是开源·可私有化的团队 AI 工作台。给 AI 一个工位,而不只是一个对话框。
- GitHub:github.com/oinone/aino...
- Gitee:gitee.com/oinone/aino...
你在设计 AI 应用的记忆系统时,用的是 RAG 还是其他方案?计划模式在你的工作流中扮演什么角色?欢迎在评论区分享你的实践和踩坑经验。