Dim 如何让 Agent 正确理解动态状态
Dim 将状态解释规则放入系统提示,将日期、运行环境等动态值放入带来源的消息,并规定同源新状态覆盖旧状态。跨午夜案例展示了如何处理历史日期冲突,同时避免动态值变化频繁改动系统提示前缀。
AI 深度解读
Agent 的上下文里,昨天和今天的日期可能同时存在,后台通知和人的指令也可能都挂着 user 角色。模型怎么分清哪些信息仍然有效、哪些只是历史?Dim 给出的办法,是随请求附上一份 Meta Prompt,专门说明输入应该怎么读。
这篇文章的价值在于,它把 Agent 常见的上下文混乱拆成了可处理的问题:规则与状态分开,消息注明来源,更新保留顺序,压缩后重新确认当前条件。作者用本地会话记录展示了这套机制,但没有给出模型理解准确率的对照实验。
两个日期同时出现,模型该相信哪一个
11 月 3 日 00:00:22,一个本地 Dim 会话追加了当天的日期状态。下一次模型调用里,旧日期仍在历史中,新日期已经到达,于是请求同时包含:
<dim-state source="dim/environment/date">2026-11-02</dim-state>
<dim-state source="dim/environment/date">2026-11-03</dim-state>
要看的是两行相同的 source:它们属于同一个状态来源,后面的值覆盖前面的当前值。旧值仍能解释历史,却不再代表今天。
跨午夜前后的请求 main #1910 和 #1930 使用了相同的 System Prompt。日期更新通过 Messages 进入,没有要求替换 System。
这是 Dim 的关键拆分:System 负责解释输入,Messages 负责承载具体值。Rust 实现会在每次请求中提供 Meta Prompt,其中 System 部分直接叫作 How to read your input,规定同源状态如何更新、不同消息如何理解。
为什么不把日期直接写进 System?因为日期、运行环境和可用技能的变化频率不同。如果把它们与解释规则绑在一起,任何值变化都会迫使前缀变化。
解释规则可以保持稳定,环境状态则沿消息流持续更新。
这里的「稳定」有边界。日期变化不用改指南,但新增一种消息类型,或者插件改变了输入含义,指南仍然需要更新。原文没有测量这种拆分对缓存命中、费用或响应速度的影响,不能顺手把这些收益也算进去。
同样是 user 消息,来源为什么还要单独标记
API 的角色字段不足以描述 Agent 运行中的全部输入。
作者记录了一次后台命令完成的过程:#413 出现 exec/ended,#414 写入包含 <dim-notification> 的通知,通知被消费后,在 #421 的模型请求中以 user 角色出现。人的输入也使用 user,只看角色,模型无法区分二者。
Dim 的做法是把通知作为独立消息发送,加上运行时标记,再由指南解释:这是一项先前工作的完成结果,模型需要联系当前任务,判断是否读取完整输出。通知本身不等于用户刚刚提出了新要求。
分支身份也存在类似问题。另一段记录中,子 Timeline 继承了主 Timeline 截至 #97 的历史,首次请求同时带上继承消息和新写入的分支身份块。这个身份块同样放在 user 消息里,由指南说明它描述的是当前 Timeline。一个 Agent 可以拥有多条 Timeline,继承历史不代表仍处于原来的分支。
原文还区分了状态、具有作用域的规则,以及文件、网页、命令输出等待分析材料。它们都进入模型上下文,但用途不同。
标记也有明确边界:它说明来源,不授予权限。实际权限检查仍由运行时完成。不能因为一段文字带着某种标签,就把它当成执行操作的授权。
这些解释由谁维护?Dim 使用 rutis 组装能力,让产生消息的组件同时注册该消息的标记、含义和解释。Core 维护共用阅读规则,插件维护自己引入的内容。
插件加载后,Prompt 合并共享说明与适用于当前分支的插件条目;配置在 context/configured 被采用后,后续请求才使用更新后的 System。插件卸载则撤回解释并重新组合指南。此前的请求保持原样,Timeline 仍可追溯当时采用的指南版本。
这样,消息格式和阅读说明由同一组件维护,减少了两者各改各的机会。
历史可以保留,失效规则不能重新生效
Dim 对运行中变更的处理,遵循同一个原则:追加记录,不回头修改历史。
不过,状态更新和规则更新不能完全用同一套覆盖逻辑。状态主要看来源,规则还要看作用域和操作类型。
<dim-rule> 的 op 表达规则如何变化:
set或replace让块中的规则生效,其中replace标明当前采用的版本。revoke或expired让规则在对应作用域内失效,其他作用域里的同名规则不受影响。
状态则采用同源后值覆盖前值的方式;带有 cleared="true" 的状态块表示该状态不再适用。
模型不能看到历史上出现过某条规则,就继续执行它。它需要结合来源、作用域和后续操作判断当前条件。撤销也是一条需要保留语义的记录。
上下文压缩(compaction)让这个问题更突出。如果摘要记住「以前有这条规则」,却丢掉「后来撤销了」,旧约束就可能重新影响任务。
Dim 将压缩后的输入分成两部分:摘要负责过去发生的事,随后重申的规则与状态负责当前仍然成立的条件。

图中的三次调用都使用 System 中的 Guide A。第一次 Messages 带有项目规则 <dim-rule> 和日期 <dim-state>;第二次依序加入日期更新、分支消息 <dim-branch-message>、后台通知 <dim-notification>;第三次压缩后,由 <dim-summary> 和 <dim-digest> 承接历史摘要及工具信息,并重申仍然有效的规则与状态。
重申使用最近一次交付的形式,例如当前采用版本的 replace 块。已经撤销的规则不会作为有效规则重新列出。指南还明确说明,重申是在确认现状,不是新的变更,也不产生权限。
开头跨午夜的会话后来在 #2025 成功压缩上下文。下一次请求 #2026 先携带摘要,再重申五项仍然有效的规则与状态,其中日期只剩 2026-11-03。
这个记录证明了输入投影保留了预期的当前值;它还不能单独证明模型在所有任务中都能正确理解这些值。
我的判断
我认可 Dim 把「如何解释输入」和「输入当前是什么」拆开。对于有后台执行、分支协作、动态插件和上下文压缩的 Agent,这套结构能让问题更容易定位:出错时可以回看具体请求,检查指南、状态和保留历史,而不必只盯着最终回答猜原因。
但它的有效性依赖前面的工程环节都做对。来源需要稳定,顺序需要可靠,作用域不能混淆,压缩后也必须准确筛出有效状态。给普通文本加几个 XML 风格标签,并不会自动获得这些性质。
作者提供的是机制说明和具体会话记录,没有比较「只用角色字段」「每次重建当前状态快照」等方案,也没有给出错误率或任务成功率数据。因此,模型能否稳定遵循指南,仍应视为需要验证的设计判断。
对于短会话、没有分支和后台任务的 AI 工具,每次提供一份清楚的当前状态快照,可能更容易实现。Dim 选择保留追加历史,并借助指南解释变化,更适合需要追溯过程的复杂运行时。代价是插件协议、规则生命周期和压缩投影都要有人维护。
可追溯的输入能帮助查错,但不等于模型已经理解正确。
能拿来做什么
- 在 Node Agent 中接入后台命令时,可以把完成通知作为独立消息,标明来源并解释其用途,让模型联系原任务决定是否读取输出。
- 给 AI 编程工具传入日期、项目路径或运行环境时,可以将值放进带来源的状态消息,同时明确同源更新和清除规则,避免历史值一直充当当前值。
- 如果工具支持项目规则动态变更,应一起设计作用域、替换、撤销和过期语义,并检查压缩后是否只重申仍有效的内容。
- 调试长会话偏航时,可以保留每次请求实际采用的指南、状态和历史片段,先确认模型收到了什么,再判断该改提示词还是消息组装逻辑。