当时钟成为工具:Agent、时区以及那个只在午夜发生的 Bug
询问大型语言模型现在几点,你得到的回答虽然语气自信,但几乎肯定是不准确的。这并非因为模型坏了,而是因为它的内部没有时钟。Transformer 是一种无状态的文本补全引擎:它将 token 映射到 token。在整个流水线中,没有任何地方会接收到“现在是 14:32 UTC”这样的信号。模型感知不到当前时刻 —— 这是你必须在每一轮对话中主动提供给它的东西,否则它就会从陈旧的训练数据中臆造一个时间。
这种无声的失败往往在最糟糕的时刻浮出面。你的智能体认为现在是星期一,因为会话是在星期一开启的,于是它在星期二、星期三依然坚信这一点,直到它为一个已经过去的日子设定了“明天早上”的提醒。它利用数小时前就已冻结的 now 来分析“过去 24 小时”的日志。它在转换跨时区的会议时间时,因为误判了夏令时的边界而导致一小时的偏差。这些在传统意义上都不像是“幻觉”。其输出流畅、合理且逻辑自洽,只是它锚定在了一个不再存在的时刻。
我喜欢将此类问题归为 上下文漂移(context drift):即智能体对世界的认知与实际情况之间的无声偏离。这并不是模型凭空捏造,而是它基于曾经正确的事实进行操作,并保持着与对待正确事实时一样的完美自信。时间是这种漂移最纯粹的表现形式,因为根据定义,时间始终在流逝 —— 当你还在握着旧答案时,正确答案已经变了。
为什么工具救不了你
显而易见的修复方案是给智能体一个 get_current_time 工具。这是一个很好的直觉,你也确实应该配备这个工具。但它本身并不能解决问题,因为工具是被动的。智能体必须 决定 去调用它。而只有当智能体有理由怀疑它所认知的当前时间时,它才会决定去检查时间。
而这种怀疑几乎从未产生过。如果系统提示词说现在是星期一,模型为什么要质疑它?它没有感知时间流逝的能力。在上下文窗口内部,“星期一”就像“水是湿的”一样是不争的事实。一个智能体从未想过要调用的工具不是安全网,而是一个折叠在衣柜里的安全网。
这是大多数智能体架构中的感知偏差。我们在 记忆(检索、长期存储、对话历史)上投入了大量精力,而这些都是回顾性的。我们在 行动(工具调用、函数执行)上投入了大量精力,而这些是向外推进的。几乎没有人构建的是 现在时 频道:即智能体对其操作时刻的、环境化的、始终当前的感知。记忆告诉智能体发生了什么,工具让它能执行操作,但除非你刻意且持续地进行同步,否则两者都无法告诉它 现在是什么时间。
因此,真正的设计问题不在于“智能体是否应该有一个时钟工具”,而在于“如何让正确的时间在每一轮对话中呈现在模型面前,而无需模型主动询问”。这个问题的答案直接引出了第二个问题,而大多数团队只有在推理账单翻了三倍之后才会发现它。
Prompt 缓存陷阱
保持智能体感知最新状态的最简单方法是将精确时间戳直接写入系统提示词:Current time: 2026-07-01T14:32:07Z。每次请求都保证新鲜。问题解决了 —— 除非你无意中禁用了整个系统提示词的 Prompt 缓存(Prompt caching)。
Prompt 缓存通过匹配前缀起作用。供应商会缓存提示词中领先的、不变的部分,并跳过对该部分的重复计算,这是实现大幅降低延迟和成本节省的关键。然而,提示词前端的任何微小变化都会使随后的整个缓存链失效。精确到秒的时间戳在每次调用时都是不同的。因此,即使系统提示词中剩余的一万个 token 逐字节一致,也永远无法命中缓存。你每一轮都要支付全额费用来重新计算前缀,而且通常还要承受额外的延迟。很多团队上线后看到成本激增,花了好几天寻找性能倒退的原因,最后才意识到那一行动态代码才是罪魁祸首。
有两种简洁的解决方案,且它们并不互斥:
- https://dev.to/terrapin88/why-your-agent-doesnt-know-what-time-it-is-15j4
- https://docs.openclaw.ai/concepts/timezone
- https://platform.claude.com/docs/en/build-with-claude/prompt-caching
- https://arxiv.org/pdf/2504.16155
- https://arxiv.org/pdf/2511.09993
- https://github.com/earendil-works/pi/issues/1873
- https://sureprompts.com/blog/prompt-caching-guide-2026
