Skip to content

数据过期后,Agent 应该怎样刷新,而不是反复重试? ​

资料过期以后,真正重要的不是让 Agent 继续调用工具,而是避免把旧事实重新包装成“最新结论”。 反复请求同一个失效来源不会创造新证据;刷新只有在有明确来源、读取资格和安全候选发布路径时才有意义。

我们曾在 ETF Agent 的受控联调中遇到内部便签标签被当作可引用来源的情况。它看起来像一个正常标签,却没有证明自己是获准的金融证据。系统拒绝后保留“不可用”,比为了让答案完整而放行一个无法核实的数字更可靠。

这是 2026 年 9 月 4 日的历史工程实践。 其后现行规范保留的是根层只读刷新与候选报告的受控发布;原 Agent 自动刷新、设置入口和后台续写链已退役。下文的历史触发与小时窗口属于当时方案,不是当前所有研究请求仍会自动刷新的说明。文章保留那个设计转折,重点讨论架构师下一次该如何判断“旧数据、不可用与新证据”的边界。

一、来源被拒后,普通重试不会造出新证据 ​

来源拒绝后,问题不在于怎样把不可用文案说得更委婉,而在于怎样取得一份新的、经过批准的证据。对同一个未批准来源重复调用,不会改变来源身份;沿用旧快照,也不能把旧事实变成当前事实。

这次机制补上的正是安全刷新路径:使用固定操作、限制数据 scope、按 scope/fingerprint/时间窗去重,并且只有验证通过后才原子发布。来源仍被拒绝或刷新失败时,系统继续保留不可用状态。

受控验证覆盖了证据从生成到回读的交接,以及不可信来源的拒绝与降级。它说明这些路径能够按既定规则处理,不能代替真实网关与生产环境的长期观察。

二、两个核心概念 ​

2.1 来源可信度:答案从哪里来 ​

来源可信度回答的是:这个数字或结论,到底来自哪条可信通道。不是“模型觉得合理”,而是“哪份受信数据、在什么时间、以什么口径给出”。

可信通道通常同时满足三点。第一,职责明确,只读的行情与持仓通道不混入推测。第二,时效明确,新鲜或过期都有标记,过期数据不冒充现状。第三,可回查,每条关键断言能关联到具体证据,而不是孤立文本。

在这个模型里,模型文本默认是建议性的、不可信的。只有经过 allowlist 的受信工具输出,才能为数值与状态背书。文本再流畅,也不能替代这条链路。

这意味着评审重点不在措辞,而在链路。先问来源是否在名单,再问口径是否一致,最后才看表达是否清晰。顺序一反,质量观就歪了。

口径一致同样关键。同一指标可能有不同统计口径,不注明口径的数字即使来源受信,也无法直接用于决策。来源、时间、口径三者缺一不可。

2.2 不可用:刷新流程的起点 ​

不可用表示当前证据不能支撑目标结论。它应保留目标和缺口,但不自动触发任意检索;只有通过明确授权的刷新入口,才可能生成新证据。

三、主流程:拒绝、不可用、受控刷新 ​

下面是简化后的主流程。它有三条关键分支:来源拒绝、状态降级为不可用、受控刷新后恢复。另有一条显式未采集分支,见图例说明。

3.1 先定义五个机制词:它们在图中何处生效 ​

机制词定义在主流程中的挂载点
候选限定仅接受根层候选,不接受旁路写入受控刷新入口:非候选直接拒绝
固定操作变更动作类型固定且受限,不支持任意写入刷新执行中:动作越界即失败
规范原子发布要么整体可见,要么整体不可见,不存在半可见刷新收尾:发布失败则整体回退
去重按范围、指纹、小时窗口去重发布前检查:命中即复用,不重复做
同会话精确一次同一会话内连续处理精确一次,不多做不少做去重通过后:保证会话内单次生效
Agent architecture diagram
Agent architecture diagram

主图中的受控刷新节点,即展开为上面这条子链。任何一环不满足,刷新即按失败处理,回到不可用并记审计。

主图中的受控刷新节点,即展开为上面这条子链。任何一环不满足,刷新即按失败处理,回到不可用并记审计。
Agent architecture diagram

关系或判断条件:

  • CheckSourceAllowlist → RejectUntrustedSource:否:未命中。
  • CheckSourceAllowlist → CheckEvidenceFreshness:是:命中。
  • CheckEvidenceFreshness → ReportUnavailable:过期或缺失。
  • CheckEvidenceFreshness → PublishCitedAnswer:新鲜且完整。
  • CheckRefreshAllowed → RemainUnavailable:否:普通问答不隐式触发。
  • CheckRefreshAllowed → ControlledRefresh:是:显式重试或定时采集且小时窗未超限。
  • CheckRefreshResult → PublishCitedAnswer:成功。
  • CheckRefreshResult → RemainUnavailable:失败。
  • ControlledRefresh → MarkNotCollected:需真实环境或超出受控窗。

这个流程的关键在于分叉点都很显式。拒绝发生在证据进入之前,不可用发生在回答生成之前,刷新发生在独立受控通道中。

任何一条分支都不会悄悄绕过。不可信标签进不来,过期数据顶不上去,刷新动作也不可混入普通问答路径。

图例补充:虚线分支为显式未采集出口。当刷新需要真实库、多进程或外部网关质量等受控窗外条件时,不硬判成功或失败,而是标记未采集并保持不可用。

触发规则只有两类合法来源:用户显式重试,以及定时采集任务。两者共享同一小时窗口限频。普通问答永不隐式触发刷新。

四、一次来源拒绝教会我们什么? ​

早期联调时,内部注释标签一度被当作可引用来源。虽然字段形式正确,但它并不在获准来源范围内。系统根据真实来源资格把这次命中判为不可信,没有让该标签支持当前组合状态。

这里不应修成“内部来源也许有用,先放行再说”。来源资格不是由字段名、看起来合理的文字或模型自信度决定的。 拒绝的代价是当次回答保留缺口,好处是不会让调试备注冒充金融事实。

更值得复用的工程方法,是先定位哪一步真正产生了来源事实,再验证材料如何成为可引用依据;不要在模型输出端为某个个案补一个放行条件。

五、从输入到结构化输出 ​

为了让不可用可被机器处理,输入与输出都做了结构化约束。下面是教学级示意,不含任何真实数据。

json
{
  "input": {
    "question": "当前组合状态如何?",
    "need_numbers": true,
    "need_advice": false
  },
  "evidence": {
    "source_label": "internal-note",
    "allowlisted": false,
    "trusted_hit": false,
    "freshness": "unknown",
    "source_id": null
  },
  "output": {
    "status": "unavailable",
    "numbers": [],
    "disclosure": "当前无可用受信证据,未做状态断言。",
    "next": "可触发一次受控刷新后重试",
    "audit": {
      "action_tendency": "none",
      "execution_allowed": false
    }
  }
}

其中 trusted_hit 的定义是:当且仅当 source_label 非空且 allowlisted 为真,trusted_hit 才为真。它是派生字段,不可手填。need_numbers 和 need_advice 是这份历史示意中的类型化输入,不表示 Runtime 可以用规则识别自由文本意图。

伪代码只有四步,优先级固定不变:

text
trusted_hit = allowlisted and source_label in allowlist
if not trusted_hit: return unavailable
if 证据缺失或过期: return unavailable
if 数值无受信根:数字留空 + 固定披露
else: 生成带引用回答 + 审计落盘

上例中 source_label 为内部便签类标签,allowlisted 为假,故 trusted_hit 为假,直接走来源拒绝分支。

输入侧只关心问题是否需要数值与操作倾向。输出侧永远带状态、披露、下一步与审计。动作倾向在不可用路径下恒为无,不产生任何执行暗示。

这种约束让前端很好处理:有数字就展示数字与引用,无数字就展示披露与刷新入口,不存在半吊子文本需要猜测。

对排查同样友好。线上问题只需看结构化字段:来源是否命中、新鲜度为何值、动作为何清零。几秒即可定位是证据问题还是生成问题。

对审计更有价值。每次回答都留下相同的字段结构,事后可以批量统计不可用比例、刷新成功率、降级原因分布。质量从感觉变成了数字。

六、运行规则:输入、优先级、失败与安全 ​

以下是历史受控方案的操作顺序,用于说明当时怎样守住不可用和候选发布边界;不是现行 Native Agent 自动刷新的开关说明。

下图是运行期的操作规则摘要。阅读顺序即执行优先级,越靠前越先判断,不可跳步。

维度规则摘要
输入一:问题类型是否涉及数值与状态;涉及则强制走证据门
输入二:证据命中仅名单内通道算命中,其余视为未命中
输入三:新鲜度新鲜可用,过期未知缺失按不可用处理
优先级一:来源门来源拒绝优先于生成逻辑,先拦后答
优先级二:降级门门未过则生成固定披露,不自由发挥
优先级三:刷新门仅显式重试或定时采集可触发,小时窗限频,普通问答永不隐式触发

前六条解决“何时停”。输入决定是否进门,优先级决定停在哪一步。任何一步不满足,后续步骤不再执行,直接走向固定披露。

维度规则摘要
失败一:网关异常依赖失败直接降级,不猜测不顶旧数
失败二:部分证据缺关键字段即整体不可用,不拼接结论
降级一:文案固定不可用文案模板化,避免误解
降级二:动作清零动作倾向为无,可执行标志恒为假
安全一:只读边界问答路径无执行无变更能力
安全二:审计必记记录原因判定与下一步建议

后六条解决“停后怎么办”。失败侧保证不硬撑,降级侧保证表达一致,安全侧保证无副作用且可追溯。两组规则合在一起,才是完整闭环。

补充四条原子性规则。第一,候选证据只接受根层候选,不接受旁路写入。第二,变更操作固定且受限,不支持任意写入。第三,发布采用规范原子发布,要么整体可见,要么整体不可见。第四,去重按范围、指纹、小时窗口执行,同一会话内保证精确一次的连续处理。

受控刷新在受控窗口内观测到:根层示例六比六通过,应用层示例三十一比三十一通过。该计数是示例范围,不做普遍保证。它没有复用执行级的每日作业流,而是走独立受控通道。

触发规则重申一次:只有用户显式重试与定时采集任务能触发刷新,共享小时窗口限频。普通问答无论证据多缺,都永不隐式触发。

隔离设计值得单独强调。问答需要高频、低延迟、可重试,而资金链路需要低频、强校验、重审计。两者混用只会互相拖累,分开反而各自更稳。

去重策略也是为稳服务的。按范围限定影响面,按指纹避免重复劳动,按小时窗口防止频繁刷新。同一会话内的连续处理保证精确一次,不多做也不少做。

七、三个对比:什么时候该说不知道 ​

案例一:过期快照 vs 坦白不可用 ​

假设受信通道短暂不可达,手头只有一份过期快照。一种做法是拿旧数顶上,加一句“仅供参考”。另一种做法是直接返回不可用,说明缺少新鲜证据。

前者看似体贴,实则危险。用户很可能忽略后缀,把旧数当成现状。后者虽然多了一步刷新操作,却守住了时效语义。过期数据只能解释过去,不能断言现在。

过期场景有明确的禁用说法。禁止写“根据最新数据,当前状态为……”,因为此时并无新鲜证据。应写“暂无新鲜受信证据,未做当前状态断言,可显式重试刷新”。

案例二:内部便签 vs 正式拒绝 ​

假设某个内部标签写着看似正确的结论,引用它只需一行代码。一种做法是为了通过率先放行,事后再补 allowlist。另一种做法是当场拒绝,保持不可用直到合法来源就绪。

前者打开了先例:今天放一个便签,明天就会放更多。后者用一次短期的不可用,换来了长期的来源纯洁性。这正是前文拒绝事件的泛化教训。

案例三:猜测补全 vs 等待刷新 ​

假设证据缺了一个关键字段,但其余字段齐全。一种做法是按常识补全缺口,让回答看起来完整。另一种做法是承认缺口,触发受控刷新后再答。

前者把模型推测混入了受信断言,审计也无法区分哪句来自证据、哪句来自猜测。后者保留了可恢复性,刷新成功即可解除,失败则继续保持诚实状态。

八、哪些边界成立,哪些仍需真实环境验证 ​

在受控场景中,不可信来源不会进入引用路径,刷新只接受限定候选;校验失败时保留不可用状态,而不是把旧证据重新包装成最新结果。这是可复用的工程结论。

真正的数据库并发与跨进程行为、外部服务的延迟和长期运行稳定性仍没有足够的现场证据。受控刷新也刻意与日常执行作业流分离;同一会话内的精确一次处理不能扩展为全局的 exactly-once 保证。

九、结论:知道何时不可用,比不断重试更重要 ​

正确的刷新不是“让红灯消失”,而是让一份具备资格的新证据替代旧状态,同时不改变投资账本。 复核此类流程时,优先问三件事:原资料能否支持当前时点的断言?有没有单独获准、只读且可核验的候选生成方式?候选失败后是否保留旧报告的真实版本,而不把旧数字冒充为更新结果?

2026 年 9 月的方案展示了来源拒绝、候选校验和受控发布的价值,但没有据此证明长期真实外部服务的稳定性、全局恰好一次执行或投资研究效果。后继规范明确退役了 Agent 自动刷新入口,只保留符合当前要求的独立显式刷新和只读报告路径。

允许研究说明“不知道”,有时比再增加一次工具调用更接近可靠的金融判断。

与个人博客并行:这里按问题连续阅读,博客保留时间线。 · 联系邮箱:hpoenixf@foxmail.com · 微信:hpoenixf0510