摘要同一次 call 里压缩会把 9 条工作历史换成 1 条摘要加 3 条尾部模型还记得“夜莺”却复述不出原话记忆则在不碰历史的情况下把事实写进 daily、合并进 MEMORY.md。我用三个实验拆开这两条流水线默认值、切点保护、三笔额外 LLM 调用以及 160K 兜底和缓存这两笔账。共约 8191 字 · 阅读约 20 分钟1、开场没让它调工具它还是把话写进了磁盘本以为禁掉工具就等于禁掉写盘。E2 第一步我把指令砍到只剩一句不要调用任何工具返回确实是 0 次工具调用call 结束memory/2026-10-30.md里多了一段## Memory Flush — 2026-10-30T12:33:04Z两条事实躺在里面。E1/E2/E3 是本课三个实验0003/0007/0009 是前几课编号后面不再解释。另一头更别扭。9 条变 4 条的那套压缩挪到真机上跑到第 4 轮它还记得暗号是夜莺我追问第一轮原话它承认已经不在上下文里了只剩摘要。一个没动手却记了一个记得结论却丢了原话。到底谁在写盘谁在丢话我一开始都往 bug 上想翻完两边的日志两个结果都指向同一件事方向却相反。口径先钉住AgentScope Java 2.0.3模型 deepseek-flash。E2 跑在 2026-10-30 晚上E3 跑在 10-31 早上写这篇是 11-01。下面所有数字都出自这个组合换版本、换模型我不保证。我原来的两个预期都错了。第一个错在工具是模型唯一的手脚第二个错在压缩是加法。这两条错得挺典型值得从头拆。2、先把预算摆上桌三道闸只有两道改历史三个实验分工先交代E1 在算法层用脚本摘要模型E2 用真实 DeepSeek 跑记忆四步E3 用真实HarnessAgent跑压缩。2.1 一次请求的预算怎么分0003 那次常规轮input 6137 token0009 的默认装配23 个工具。把这两笔和系统提示、输出预留摆到一起一次请求的输入大概长这样系统提示和指令固定23 个工具 schema 也固定输出预留 2.0.3 默认 20000剩下那段工作历史是可伸缩区。固定不等于免费。23 个工具的 schema 每次模型请求都要发一次 call 里多轮推理就多份AGENTS.md 每次 call 开头读一遍再随系统提示发出去。这两块是你为“能力”付的固定税它们不随对话变但实打实占 token。固定材料不能动输出预留也不能动——请求还没发就得先给回复扣出位置跟 HTTP 响应体的大小预算一个道理。唯一能动的是工作历史。还有一段随 call 变的注入材料MEMORY.md上限 8000 token它既不算固定材料也不属于工作历史。所以上下文管理不是仓库满了再租一间是这趟车只能装这么多先扔哪个箱子。图 10-1 把三道闸画在一起三道闸都从可伸缩区里取东西取法完全不同。2.2 三道闸各挂在哪看最后一列只有前两道改历史第三道连碰都不碰。表里第三道跨了两个钩子注入在onSystemPromptcall 开头flush 和维护在onAgentcall 结束后、后台。你在一次请求里看到的 MEMORY.md是上一次 call 结束后留下的版本。onReasoning是每一次模型请求前不是每一次 call 前——一次 call 里工具轮多第二、第三轮推理之间就可能压一次你会在一次运行里看到历史突然变短。你要是写过HandlerInterceptor这个位置不用解释就是每个请求进 Controller 前都过一遍只是这里的请求是模型调用。onAgent在 call 成功结束之后像 Spring 的afterCompletion主流程走完了才轮到它它的开销不在主调用里是另一笔模型请求。2.3 为什么把卸货单列装不下有两种形状。一种是整段历史太长另一种是单条工具结果太大——一条舱单查询返回三十万字符摘要救不了它摘要会把它变成一句查过舱单细节全丢。卸货的处理是搬走不是删掉。单条 tool_result 文本超过 80K 字符头尾各留 2K 预览中间换成large_tool_results/hash.txt的路径read_file、memory_search这类工具本身不参与免得把查文件的结果再搬一次排除名单一共七个。为什么阈值是字符不是 token字符在本地就能数不用分词器阈值粗一点没关系因为搬走是保守动作搬错了还能read_file回来。删之前先搬走。后面 E2 第四步模型能靠read_file把事实从 daily 捞回来用的是同一个思路——磁盘上还有原件。本课没构造大工具结果样本80K/2K 是读字节码与速查表的口径。3、压缩把工作历史整体换掉3.1 触发50 条或一条 token 线2.0.3 的默认值javap 出来的不是文档抄的两个 0 的意思不一样triggerTokens0是用动态值triggerMessages0才是关掉条数触发。我第一遍看混了以为两个 0 都是关。两个条件是先到先触发不是每轮都压。50 触发、20 保留默认一次压掉三十条上下这是给长会话留的余量不是给短问答准备的。我们这台机器上有一条具体的链deepseek-flash不在 2.0.3 的ModelContextWindows表里getContextWindowSize()返回 0动态 token 触发落到 160000 兜底keepTokens的动态值也算不出来退回按条数保留 20 条。只背50 条、20 条不够得顺着模型窗口 → 减 reserved → 读不到就兜底 → keep 退化这条链解释排障时才知道阈值为什么落在那儿。3.2 七步最后两步才是关键一次压缩不是加一条摘要是七个动作// ConversationCompactor 的动作序2.0.3伪代码truncateArgs?;// 可选默认关只截旧 ToolUseBlock 的参数字符串pruneToolResults();// 默认开保护最近 40K token至少 20K 可压预览留 2K 字符if(msgstriggerMessagestokenstriggerTokens)return;// 先到先触发intcutofffindSafeCutoffPoint(msgs,keepMessages,keepTokens);flushPrefix(msgs.subList(0,cutoff));// 压前抽事实best-effort失败不阻断Stringsummarymodel.summarize(prefix);// 四段SESSION INTENT / SUMMARY / ARTIFACTS / NEXT STEPSListMsgcompactedsummaryMsg(summary)msgs.subList(cutoff,msgs.size());state.contextMutable().clear();state.contextMutable().addAll(compacted);前五步都在准备第六步花一笔模型调用第七步才是切换。第一步和第二步都不改消息条数真正决定压多少的是第三步和第四步。pruneToolResults和后面的摘要不是一回事它只把旧工具结果的正文压成头尾加省略号消息条数不变也不调模型真正让历史变短的是第七步的替换。注意最后两行不是 appendclear()之后addAll原来的中间轮次从账本里消失了。压前 flush 默认开会把将被压掉的前缀先抽到 dailyoffloadBeforeCompact默认也开会把前缀写进 session transcript。一个是记忆一个是证据——E1 为了隔离变量两个都关了。做过 LSM 的同学会眼熟合并重写之后旧段不再单独存在了。区别是这里合并的是自然语言丢掉的措辞没法从新段里反推。所以压缩一下、原文还在这个理解在 2.0.3 上不成立。原文只可能在 session log 或压之前的账本快照里工作历史里只剩摘要和尾部。3.3 切点保护7 为什么变成 6E1 的输入 9 条keepMessages2朴素切点是 9 − 2 7。索引 7 是一条 TOOL 消息。keepTokens0时切点是从尾部往前累加 token 算的E1 的keepTokens0所以按条数。照切会留下一个没有来源的 tool_result——就像数据库里留了一条没有主表的外键。第 1 课焊的ToolUse ↔ ToolResult 必须配对在这里变成压缩器的硬约束收集这段 TOOL 的 result id向前找到含对应 tool_use 的 ASSISTANT 消息切点移到 6。结果是尾部 3 条不是 2 条。日志里cutoff6, keeping3就是这件事。宁可多留一条也不拆散一对。这个规则写在cutoff.reason里E1 的 JSON 直接给了原话切在索引 7 会让 tool_result 失去配对的 tool_use所以前移到 6。3.4 摘要的身份压完的第 0 条不是 system是一条roleUSER、name__compaction_summary__的消息正文以Here is a summary of the conversation to date:开头后面四段SESSION INTENT、SUMMARY、ARTIFACTS、NEXT STEPS。四段各有分工。按我的理解INTENT 和 SUMMARY 保结论ARTIFACTS 保文件NEXT STEPS 保没做完的动作压完最怕丢的是最后一段——模型下一轮不知道自己该干什么。为什么是 USER它得作为对话内容继续参与推理。塞进 system 会抬高优先级、污染规则层。起名是为了下次压缩能认出旧摘要把它合并进新摘要不至于层层套娃。3.5 两种坏天气摘要调用失败2.0.3 退化成(Summary unavailable)带错误信息仍然照压它没有摘要不比原会话小就保留的 size 检查。模型真溢出HarnessAgent捕获context_length_exceededforceCompactAndRetry在同一次执行里重试一次压不动就抛给调用方。这两条我没构造失败样本是读字节码得出的结论跟实测分开摆。3.6 E19 条变 4 条的现场E1 是算法层不走真实模型摘要模型是脚本罐头只回一段固定文本为的是把变量关掉。配置triggerMessages6 / keepMessages2 / keepTokens0。页面点一下9 条变 4 条。日志一行Compaction triggered: total9 msgs / 305 tokens, cutoff6, keeping3 msgs305 token 是估算不是账单9 条货运对话都短所以这个数小。我第一眼还以为是哪条没算进去。读法先看日志再看 after 数组。日志给切点after 给顺序——第 0 条摘要后面依次是 tool_use、tool_result、assistant正好是被前移留下的那一对加最后一句。被压掉的是前 6 条包括查船期那次往返。10-31 我用当前构建复跑了一次JSON 跟 10-30 那份一样。E2 和 E3 没再跑第三遍。4、记忆三笔模型调用两层文件4.1 三笔额外调用记忆两笔压缩一笔官方原文就是three independent LLM calls不是这节课编的。第三笔是压缩流程的账列在这里只因为都是额外模型请求它不写盘也不该算进记忆的成本。三笔都是额外模型请求默认共用主模型MemoryConfig和CompactionConfig都能单独换便宜模型但频率是另一回事。三笔里只有第三笔改当前上下文前两笔都落磁盘。排障时先分清是哪一笔再去看对应的文件。E2 的三次主对话额外四笔flush 3、consolidation 1。同一日志窗口里 E1 另记一笔压缩摘要total9那是压缩实验的账不算进 E2。记忆不是纯文件 IO它要花钱。4.2 两层文件与一个水位2.0.3 本地跑出来的目录大致长这样archive/是 90 天规则本次没触发workspace/ └─ lab-user/ ← 本地模式按 userId 开命名空间文档画在根目录 ├─ MEMORY.md ← L2整篇重写、≤4000 token、每 call 注入 └─ memory/ ├─ 2026-10-30.md ← L1只追加Flush 段 / Memory Save 段 ├─ archive/ ← 超过 90 天的日记账 └─ .consolidation_state ← 水位ISO Instant30 字节L1 便宜写得全但越来越长、重复越来越多。L2 要短、要可读、要去重所以必须有一个昂贵的整篇重写步骤。L2 写入上限 4000 tokenconsolidationMaxTokens它被注入时另有读取上限 8000 tokenmaxContextTokens——两个数不是同一个参数。水位是两层之间的消费位点consolidation 只读水位之后被改过的日记账没有新条目就直接跳过连模型都不调——日志里那句No fresh daily entries since 1970-01-01T00:00:00Z — skipping consolidation就是它。写完 MEMORY.md 才推进水位写失败水位不动下一轮重跑同一批——不漏条目但要多付一笔合并调用。水位存 ISO Instant 而不是行号因为台账按天分文件时间戳跨文件可比行号不行。这套结构和 WAL 加定期压实很像L1 只追加保证不丢L2 定期重写保证可读水位决定下一轮从哪继续。差别是这里的日志是自然语言压实要靠模型。daily 超过 90 天移进 archivesessionRetentionDays180这个字段还在我没验它实际管什么先不算进结论。路径这里有个漂移文档示意图画在工作区根目录2.0.3 本地模式实际在workspace/userId/实验里就是lab-user/。按文档去根目录找MEMORY.md会找不到。4.3 读路径注入是垫底检索才是主力每次 call 开头WorkspaceContextMiddleware读一遍MEMORY.md按maxContextTokens默认 8000截断作为HARNESS_CONTEXT的 USER 侧参考材料注入。system 侧只有 Memory Recall / Persistence 的使用指导。我这边看到的是明明注入了它还是先搜一遍。Recall 指导让它回答过去工作的问题前先memory_search注入只是垫底。截断不是摘要后面的条目这一轮就是看不见。注入只覆盖 L2且可能落后一次合并要问今天刚发生的事只剩检索这条路。E2 第三步新会话问同一事实两次窗口分别 3 次和 0 次搜索Source 都指向MEMORY.md完整读数放 §4.5。Source 带行号说明它是被读进来的材料不是指令。指令不会给你行号。4.4 写路径自动 flush 与主动 save自动 flush 是中间件每次成功 call 结束后台把这段对话交给模型抽出值得记的事实追加到当日台账没东西可记就回NO_REPLY。它不碰 MEMORY.md。NO_REPLY是个约定没东西可记就不写不然每天的台账会被无事发生撑满。主动 save 是模型的手脚调用memory_save同时写 MEMORY.md追加和当日台账。disableMemoryTools关掉的是这只手不影响 flush。E2 第一步就是证据0 次工具调用daily 照样多出## Memory Flush。两条路径一条都不需要模型决定。一次普通问答 主调用 一笔 flush如果赶上首次后台维护再加一笔合并。这笔账 §7.3 再算。4.5 E2 四步不让调工具也能写盘E2 跑了两次18:26 与 20:32。下面以 20:32 为主18:26 只作对照两个窗口的读数不同不能混成同一次。第一步输入那句不要调用任何工具只用一句话回答并确认我们公司出口固定走上海港客户代号 ALPHA。0 次工具调用daily 140 B出现## Memory Flush — 2026-10-30T12:33:04ZMEMORY.md 不存在。日志同时有一行No fresh daily entries since 1970-01-01T00:00:00Z — skipping consolidation首次后台维护抢在 flush 落盘之前跑完读到空台账就跳过了。这不算失败两层之间还欠一次合并。flush 和首次维护都是 call 结束后排队的后台任务谁先跑没有保证这也解释了 ① 之后 MEMORY.md 为什么还没生成。反向样本flush 先落盘、维护顺手合并出一份我只在逻辑上推过没抓到。18:26 那次它的回答是尚未写入长期记忆20:32 那次改口成对话结束时记忆会自动提取保存。两次磁盘上都多了一段 Flush。模型说的不算中间件写的算。页面能看到这些是因为/chat在 call 返回后等了MemoryBackgroundTasks.awaitQuiescence(60s)不等的话你可能读到半成品。第二步手动合并。MEMORY.md 从无到 158 B整篇重写daily 140 B 原样水位 30 B耗时 1148 ms。正文是## 业务与物流加两条事实出口港口、客户代号。合并读的是旧 MEMORY.md 加水位之后的 daily输出整篇重写它不是把 daily 的内容 cat 到文件末尾。注意 562 B 那个数是 18:26 窗口的不是这一次。两个窗口的合并产物不同不能混成同一次实验。第三步新会话追问。3 次搜索、Source 指向 MEMORY.md答对。18:26 那次 0 次工具也答对。同一条事实两条读路径都走得通。第四步删掉 MEMORY.md 再问。9331 ms、10 次工具memory_search两次read_file两次list_files三次session_search两次最后memory_save。MEMORY.md 被重建到 127 Bdaily 涨到 317 B新增一段## Memory Save水位不变。它能重建是因为 daily 里有 Flush 段L1 只追加的价值就在这儿——L2 可以丢L1 不能。18:26 那次是 5 次工具、4909 msSource 指向memory/2026-10-30.md#3-4没有重建 L2。同一张卡跑两次次数不一样。判读看证据链Source 指向哪个文件、用了哪几个工具、磁盘终态是什么。次数不是结论。4.6 记忆不是账本删掉 L2 不是永久失忆L1 还在检索能找回模型还可能顺手把 L2 写回去。删只是删了一个视图。另一头flush 会脑补。18:26 那次它写出这样一句2026-02-13 之前这些信息仅在对话中确认尚未写入长期记忆……这个日期在对话里从未出现。consolidation 把它原样并进了 562 B 版的 MEMORY.md还多了一节备注记录来源。这不算 bug。记忆本来就是模型对对话的抽取不是账本的复制。它适合提效不适合当审计事实源。要审计回 AgentState、session 日志、原始单证。顺便把另一个错位点掉把长期记忆当成把聊天记录存起来存聊天记录的是 AgentState 账本但账本也不是一整份原文压缩会把它整体换掉完整原文在 session log。MEMORY.md 是模型抽出来的几条事实写入者都不是同一个。5、真机压缩trigger 写 5第 3 轮就压了5.1 配置5 条 / 留 2 条先回到压缩线。E3 跑的是真HarnessAgent不是算法层labAgentHarnessAgent.builder().name(compaction-lab).model(agentConfig.resolveModel()).workspace(WORKSPACE).stateStore(newJsonFileAgentStateStore(STATE)).compaction(CompactionConfig.builder().triggerMessages(5).triggerTokens(0)// 0 动态这里靠条数.keepTokens(0)// 0 按条数保留.keepMessages(2).flushBeforeCompact(false).offloadBeforeCompact(false).build()).disableMemoryHooks()// 隔离变量只看压缩.disableMemoryTools().sysPrompt(你是压缩实验的对话助手。回答保持简洁不要调用任何工具。).build();关键不是这几行是三个隔离关 memory hooks、关 memory tools、flushBeforeCompactfalse。不关的话压之前还会多一笔 flush变量就混了。E2 的 chat 端点反着来.disableCompaction()把压缩关掉只看记忆两个实验各关一头才能把两条流水线分开看。脚本 4 轮必测记暗号夜莺只回复收到问暗号是什么把暗号倒过来念问第一轮原话还在不在。第 5 轮补一次再答一次暗号。5.2 时间线我押第 4 轮实测第 3 轮我押第 4 轮。理由很蠢trigger5我数的是第 5 条消息差不多第 5 轮又想着 keep2 要留两条就押了第 4 轮。实测第 3 轮。原因是本轮的用户消息在onReasoning之前就已经入账第 2 轮结束账本 4 条第 3 轮 user 进来变 5 条正好命中。压缩瞬间 context 是摘要加 2 条尾部3 条模型回复再加 1 条接口看到 4 条。那 3 条是摘要、A2、U3U3 是本轮刚进来的 user不是上一轮的回复。阈值数的是消息条数不是轮数。普通问答一轮两条5 条自然落在第 3 轮如果一轮带三个工具往返条数涨得快按挂载点推同一轮里压两次也有可能这个样本我没造。第 3、4、5 轮各压一次。三次日志都是total5 msgs / cutoff3 / keeping2Compacted to 3 messages before reasoning。页面上调用前 4、调用后 4我盯着看了半分钟以为没压。4 是调用前账本压发生在 user 入账之后、模型请求之前两次读数之间内容已经换过一轮所以条数对上了。5.3 记忆保真记得夜莺丢了原话第 4 轮问第一轮定的暗号是什么第一轮原话还在吗它答第一轮定的暗号是夜莺。但第一轮的原话已经不在上下文里了我现在能看到的只是这份会话摘要……所以结论可靠措辞无法还原。第 3 轮它把“夜莺”倒过来念成“莺夜”第 5 轮再问暗号它仍答“夜莺”还补了一句按第一轮的规矩倒过来是“莺夜”。结论活得好好的。从回答看摘要保住了“夜莺”和“倒过来念”这条规矩没保住第一轮的原句短结论能活措辞活不下来。摘要长度 698 → 874 → 168 字符第三次反而短了。我猜是压完工作集变小摘要跟着收这条没单独验。终态 4 条、624 token 估算624 也是估算真值看那一轮的 usage我没截。压的是工作历史不是完整历史。session log 里第一轮的原话还在只是模型这一轮看不见了。5.4 节奏为什么第 3 轮之后每轮都压压完 keep13 条回复 14下一轮 user 15又命中。所以trigger5 / keep2的稳态是从第 3 轮起每轮都压不是每 5 轮一次。普通问答的间隔ceil((trigger − keep − 1) / 2)。想要 5 轮一次得trigger13 / keep2第一次在第 7 轮命中——这条是算的我没跑。拿trigger6 / keep2代进去间隔 2 轮trigger5 / keep2代进去是 1 轮也就是每轮。带工具的一轮是 4–6 条消息节奏完全不同。生产上按 token 预算设别按轮设。6、能看见才敢动手仪表与手动压缩6.1 仪表估算加上一轮真值主面板顶部加了一条只读仪表端点完整路径是GET /workbench/sessions/{threadId}/contextGetMapping(/{threadId}/context)publicResponseEntityContextMetercontext(PathVariableStringthreadId){// 空会话分支与遍历略关键两行inttokensTokenCounterUtil.calculateToken(context);// 与 Harness 压缩同一个估算器returnResponseEntity.ok(newContextMeter(threadId,context.size(),visible,tokens,hasSummary,none,主链路 ReActAgent 未启用压缩));}前端接CUSTOM token_usage显示上次请求 input / cached / 本轮累计。实测读数10 条、458 token 估算、上次 input 1.2K、cached 1.0K、累计 2.3K。发这一轮之前是 6 条、253 token。458 是估算1.2K 才是上一轮的真值。估算器是启发式的字符加消息开销不是 provider 的分词器我自己排障时先看这个数账单看 usage。主链路要兼容多个模型估算器只能统一误差靠上一轮真值兜底所以两个数一起显示。估算值的用处是趋势同一会话里从 253 涨到 458说明这一轮多出来的主要是工具往返绝对值不准但涨跌能看。主链路是ReActAgent没开压缩所以仪表不显示阈值真正的阈值读数在 E3 卡片里。仪表只读不会触发任何模型调用。cached 1.0K 不是上下文被压了这笔账 §8.4 算。6.2 手动压缩的 Rails与 2.0.3 的现实手动压缩是有损操作按钮不是 UI 问题是状态机问题。我把要加的东西归成三道状态安全只在空闲时压且没有未决 interrupt。压缩改的是同一个 context 列表推理正在读它并发改会写出半截之前那个没回的中断恢复时要接着原来的上下文先把历史压了恢复点就对不上了。可撤销确认框加前置快照。有损操作得让人知道原文会不在工作历史里压完出问题能回去。可追溯审计日志。谁、什么时候、切点在哪、摘要多长出事故要能查。三道里最容易被跳过的是第二道。快照看起来浪费等真压丢一条关键结论你就知道那一份 JSON 值钱。2.0.3 没有公开的compactNow。HarnessAgent只暴露getCompactionHookCompactionMiddleware只有onReasoning和构造器。手动压缩和自动压缩用的是同一个 compactor区别是谁触发、什么时候触发、有没有 Rails。要用只能应用层自己拼ConversationCompactor加AgentState或者等新版本。最小实现见HarnessMemoryLabController.compactionDemo()E1 端点。主链路是ReActAgent暂时只能在 lab 里做——这也是课程实验和生产按钮的边界。想自己跑页面http://127.0.0.1:8080/lab.html#exp-0010-e1实验跑在我本地 workbenchJDK21工程不随文发布。E1 不需要 keyE2/E3 需要 DeepSeek key。E1点执行一次压缩预期 9 → 4、切点 6。E2先点重置再按 ①预期 0 次工具、daily 多出## Memory FlushMEMORY.md 可能不存在只要 0 工具 daily 有 Flush 就算通过。E3先点重置或刷新换新会话4 轮必测第 5 轮补测预期第 3 轮出现__compaction_summary__第 4 轮答夜莺并承认原话不在。失败分支服务没起先看 8080 和日志401 看 keydaily 没 Flush 先看NO_REPLYE3 答偏也是结果先看摘要里有没有夜莺。单次读数上面的字节/字符/毫秒是单次运行模型换一次可能不同结构判据不变。PowerShell 的curl是别名用curl.exe或Invoke-RestMethod。7、三个容易搞错的点契约、注入与节流7.1 中间件改不改历史契约 vs 能力第 7、9 课我写过三句不准确的话这里逐条修正。0007 说中间件不能改写历史。那句话是契约钩子给你输入和事件流没有把历史改成这样的入参。但中间件拿得到 Agent 和 RuntimeContext能力上是能改的AgentStatestateruntimeContext.resolveAgentState(ctx);ListMsghistorystate.contextMutable();history.clear();history.addAll(compacted);eviction 和 compaction 就是这么干的。契约不给你 API不等于能力不存在。0007 的说法也不算错它描述的是给普通中间件的契约框架自己的中间件是内部人走的是另一条门。排障含义我自己写中间件时踩过的坑是乱动账本框架自己动的时候我得知道它动了。看到历史突然变短先想压缩别先怀疑模型。7.2 MEMORY.md 注入哪参考材料不是 system0009 写记忆每轮注入 system写粗了。官方原文是… loaded once per Agent call and supplied as HARNESS_CONTEXT reference material, not System.实际是HARNESS_CONTEXT的 USER 侧参考材料system 里只有 Recall / Persistence 的使用指导AgentScope memory 文档。注入了还先搜可变事实不能升格成指令。规则和材料分开AGENTS.md 是规则MEMORY.md 是材料。还有一个工程推断MEMORY.md 内容每次合并都变那一段前缀就要重建放 USER 侧也一样不是放进 system 才有这个问题。7.3 flush 是不是每轮ALWAYS 的代价0009 说压缩、记忆提炼、后台维护都被节流闸门管着。三件事的节奏不一样flush默认ALWAYS每次成功 call 都跑。consolidation首次立即之后 30 分钟有新台账才跑。compaction过阈值才跑。所以都被节流管着这句话只对 consolidation 成立flush 是每 call 一笔压缩是过阈值才来。18:26 那次的日志callMs2627、flushWaitMs1962。回答本身 2.6 秒flush 又等了 2.0 秒——这是端点等了后台静默生产里你不一定等但钱照花。省法三条flushTrigger(throttled(10min))限频never()只留压前那笔disableMemoryHooks()全停连维护一起。只关每次 call 都跑的那笔改flushTrigger别动disableMemoryHooks。同理disableCompaction关掉的不只是阈值压缩还有溢出兜底那一次重试。8、别家也有账也要算对整机、零件与两笔账先看别家怎么做再算两笔最容易读错的账DeepSeek 的 160K和缓存。8.1 产品层压缩加文件记忆已成套先纠一个容易写错的判断这套组合不是 AgentScope 独有。Claude Code 的 auto memory 是默认开的目录里一个MEMORY.md索引加每个主题一个文件压缩之后 CLAUDE.md 和 auto memory 都从磁盘重新注入memory 文档。PreCompact 钩子还能拿到 trigger 和 custom_instructions手动/compact时可以带指令自动压缩时是 null。OpenAI Agents SDK 把压缩做成会话层动作OpenAIResponsesCompactionSession可以每轮压压缩会清空并重写会话历史sessions 文档。这页只讲会话历史Sessions 本身不管跨会话事实抽取别据此推断 OpenAI 没有别的长期记忆产品。SessionSettings(limitN)还能只取最近 N 条相当于会话层的滑窗。这几家我没跑只读官方文档AgentScope 的数字才是本机实测。三家有跨会话存法Claude Code / LangGraph Store / Deep AgentsOpenAI 这条只到会话层。四家都把压缩和记忆分开处理差别在注入位置和检索工具Claude Code 压缩后重注入Deep Agents 可进 system promptAgentScope 放 USER 侧参考材料。写成独家能力会翻车。8.2 Java 库层给的是零件Spring AI 的MessageWindowChatMemory默认窗口 20 条超了淘汰旧的但永远保留SystemMessage它按条计数、按轮对齐不会切半轮但没有摘要。它自己的文档还补了一句ChatMemory 不是存完整聊天历史的最佳选择chat-memory 文档。这两点决定了它只能当 L1——它不沉淀事实。LangChain4j 只有MessageWindowChatMemory和TokenWindowChatMemory两种滑窗官方自陈currently offers only ‘memory’, not ‘history’要完整历史自己存chat-memory 文档。这条流水线里它只给了两个滑窗实现要摘要、要沉淀、要检索都得自己接。两边都没有摘要写回 事实沉淀 检索这条流水线。差别在默认装多厚、落在 Java/Spring 哪一层。8.3 DeepSeek 的 160K框架兜底不是厂商限制§3.1 那条链裸名→窗口 0→160K在厂商口径里还有一层官方把deepseek-flash标到 1M 上下文、384K 最大输出定价页。2.0.3 登记的却是两个已经标成 legacy 的deepseek-v4-flash/v4-pro新裸名反而没进表——表既不全也过期。所以这是框架保守不是厂商限制我排障时先问框架登记了这个模型名吗不急着说DeepSeek 只有 160K。文档也跑在制品前面2.0.3 输出预留固定 20000当前文档改成窗口的 1/8、封顶 4096未知窗口兜底2.0.3 是 160000文档写 64000摘要验收门2.0.3 没有文档说完整且确实更小才替换。排障以 2.0.3 为准升级复验另开一课。按普通问答的体量推先撞上的是 50 条这条线——每条几十到几百 token攒到 160K 要很久真正让 token 线提前的是大工具结果。E3 用 5 条就能压也是条数先到。8.4 缓存不是压缩两条正交的账DeepSeek 的上下文缓存是前缀级、按完整前缀单元命中、best-effort命中价约为未命中的 1/50prompt_tokens等于命中加未命中。它复用计算不减少你发出去的 token 条数。压缩减少的是 token 条数还改变内容。两条账正交。仪表上 cached 1.0K 说明上一轮前缀基本命中省的是单价它不代表上下文被压过。反过来压缩之后前缀变了缓存那一段大概率要重建——省了 token 条数可能多付单价。这笔取舍要按会话长度算我只在文档层面推过没有实测账单。9、货代落点三类信息三种归宿9.1 三类信息只有一条判据这条信息在下一个会话里还成立吗9.2 判据下一个会话还成立吗我实际分的时候先看影响期。E2 那两条事实只走上海港、客户代号 ALPHA是跨会话口径落在第一档某航次跳港这种如果只影响今天装船就进 daily如果这条航线接下来两周都绕行它就已经跨到长期规则。判据看影响期不是信息本身。这票货的临时备注是最容易进错档的一类它看起来像客户偏好但只对当前这票货成立下一票就不成立了。它留在对话里让压缩带走别写进 MEMORY.md。别把所有聊天都当记忆。那只是把上下文爆炸换成了记忆库爆炸。daily 需要合并也是同一个道理今天的运营事实过几天就不成立留在 L1 让它自然衰减不用人去删。9.3 审计边界记忆不是事实源记忆是模型抽取会省略、改写、脑补18:26 那个假日期就是样本。订舱号、箱号、金额这些以原始单据为准要对账回 AgentState、session 日志、原始单据。记忆里的版本只能当线索。这条我不是从文档抄的是自己跑出来的。10、收口带走三句临走三问回到开头那两个结果写盘的是 flush丢原话的是压缩。两个问题各归各的机制。压缩改这一次的工作历史请求前把AgentState.context换成摘要加尾部有损原文不在里面E3 第 4 轮原话已不在。记忆搬跨会话的事实call 结束写 daily合并进 MEMORY.md不改历史下次注入或被检索E2 ①0 工具调用仍写盘。先算这笔钱再决定开不开flush 默认每次成功 call 都跑consolidation 首次立即、之后 30 分钟一趟compaction summary 过阈值才来。临走三问你的场景里哪条信息该进 MEMORY.md哪条只该进 daily剩下哪些应该什么都不进你的模型在 2.0.3 的窗口表里被读成多少压缩阈值会落到哪一条线上如果明天就加手动压缩按钮三道 Rails 你先加哪一道为什么三道都答对了这一课才算真的带走。第 10 课结课学习进度 9/570006 暂挂。下一篇 0011 Workspace这些记忆文件住的工作区到底长什么样AGENTS.md 与它什么关系。如果这篇文章对你有帮助欢迎转发给需要的同事和朋友。
企业数字化 ERP 产品动态
相关推荐
全球第一个 800 伏直流数据中心跑起来了,在乌兰察布,不在硅谷 英伟达把 800 伏直流当成 2027 年以后百万瓦机柜的唯一解。它自己的时间表是先上 800V 的 sidecar 电源模块,原生 800V 机柜要等到 Feynman 那一代,也就是 2028 年。
11 月 2 日,一家做风电起家的中国公司说,它已经在内蒙古乌兰察… · 2026/11/6 8:55:14
11.3【大模型】 config到模型架构字段含义在config当中,各字段都是什么含义,怎么就能反映出整体结构的从配置到结构的推导注意力层和 qkvoMLP 与其他配置Anacondawsl与windows互联那原来windows当中的OLLAMA_HOST是怎么填值的,为什么WSL在此时无法看到window… · 2026/11/6 8:55:14
数据库认识 一、基础认识数据库是结构化数据的集合,它以系统化的方式存储、组织和管理数据,便于计算机 程序快速访问、操作和管理。简单来说:数据库就是存放数据的“仓库”,但这个仓库有着精心设计的结构和高效的存取机制。数据库进行数据管理… · 2026/11/6 8:54:14
大模型实操指南:从本地部署到PPT级可控生成 1. 这不是“学大模型”,而是重建你和信息世界的关系“大模型相关内容的研究学习”——看到这个标题,我第一反应是笑。不是嘲笑,是那种在实验室熬了三个通宵、刚调通一个LoRA微调任务后,盯着终端里跳出来的loss曲线突然失语的笑。因… · 2026/11/6 15:59:18
高效查找第K大元素:排序、堆与快速选择算法对比 1. 问题描述与核心挑战 给定整数数组 nums 和整数 k,我们需要找到数组中第 k 个最大的元素。请注意,这里要求的是排序后的第 k 个最大元素,而不是第 k 个不同的元素。 这个问题看似简单,但隐藏着几个关键挑战: 当数组… · 2026/11/6 15:05:13
企业设备数字化管理:易点易动系统实践指南 1. 设备管理在企业数字化转型中的核心价值 设备管理作为企业资产管理的重要组成部分,正在经历从传统人工记录向数字化、智能化管理的转变。在制造业、医疗、教育等行业,设备资产往往占据企业总资产的60%以上,其管理效率直接影响企业运营成本和… · 2026/11/6 15:05:13
企业元宇宙治理框架:技术实现与合规路径 1. 企业元宇宙治理框架的核心逻辑 企业元宇宙作为数字化转型的新阶段,其治理框架需要兼顾技术创新与合规要求。从技术架构角度看,企业元宇宙本质上是一个由数字孪生、区块链、人工智能等技术构成的复杂系统。这个系统需要解决三个核心问题:如… · 2026/11/6 14:59:51
基于CDC的MySQL实时数据同步方案实践 1. 项目背景与核心价值 在数据驱动的业务场景中,数据库表间数据同步是个高频需求。我最近在电商订单系统中就遇到了这个问题:订单主表数据变更后,需要实时同步到统计分析表和风控表。传统的手动同步或定时任务方式存在延迟高、易出错的问题&a… · 2026/11/6 14:00:34
JSP农贸交易系统开发与智能撮合算法实践 ## 1. 项目概述与核心价值农贸产品交易系统是连接农产品生产端与消费端的重要数字化桥梁。这个基于JSP技术的交易平台(项目编号g3608)完整包含了程序源码、数据库设计、部署指南和开发环境配置,是一套开箱即用的农产品B2B解决方案。我在参与某… · 2026/11/6 14:00:34
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23
三菱PLC数据采集到数据库的时序设计:Python+MC协议实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11
ASIC主模式RTL设计:状态机与三态驱动的流片级实现 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11
STM32嵌入式C++开发:GDB调试与Renode仿真实战指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23