很多 Agent 看起来“会思考”,但一旦把它放进真实世界持续运行,问题就会很快暴露出来:它不知道刚刚过去了多久,不知道自己停了多久,不知道一次等待是真正的等待,还是系统卡住了;它也分不清一段对话是刚刚发生,还是三小时前留下的上下文。

我越来越觉得,很多所谓“智能不稳定”,本质上并不是推理能力不够,而是 Agent 缺少对时间流动的感知。它拥有任务、记忆、工具,却没有时间。没有时间感的系统,就很难形成真正的节奏感、优先级感和连续性。

所以我提出一个很朴素、但我认为非常关键的设计:在系统 TICK、聊天对话、行为日志中显式加入时间信息,让 Agent 能够感知“时间正在流动”。

这不是给系统额外塞几个时间戳那么简单。更重要的是,要让时间成为 Agent 理解世界、理解自己状态、决定下一步行动的一部分。

为什么 Agent 会缺少时间感

大多数 Agent 系统默认把上下文看成一个静态窗口。

模型拿到的是一段 system prompt、一段聊天记录、几条记忆、一些工具结果,然后在这个切片里做推理。问题在于,这个切片通常是“无时间”的。即使里面有内容顺序,模型也未必能准确知道:

  • 这件事是 10 秒前发生的,还是 10 小时前发生的
  • 用户是刚刚沉默了一会儿,还是已经离开了很久
  • 某个任务的等待期是否已经结束
  • 上一次行动后没有新进展,是因为外部事件尚未发生,还是因为自己漏掉了继续推进
  • 眼前这段记忆到底应该被视为“当前状态”,还是“历史痕迹”

于是 Agent 很容易出现几类常见问题:

  • 它会把过期信息当成当前事实
  • 它会在不该催促的时候催促
  • 它会忘记等待和轮询之间的区别
  • 它会不断重复刚做过的动作
  • 它会失去长期运行所需要的节奏感

从这个角度看,很多 Agent 的问题不是“不够聪明”,而是“活在一个没有时间的房间里”。

时间感不是功能,而是基础知觉

如果我们把 Agent 当作一个持续运行的认知体,那么时间感不是一个附属 feature,而是一种底层知觉。

人类为什么能形成计划感?因为我们知道“刚刚”“现在”“过会儿”“明天”“已经很久没发生了”之间的差别。我们的感知是连续的,永远或者当下,我们判断一件事是否紧急,并不只靠事情本身,还靠它在时间轴上的位置。

Agent 也一样。

一个真正能持续工作的 Agent,至少要回答下面几个问题:

  • 现在是什么时候
  • 距离上一次关键事件过去了多久
  • 当前任务处在哪个阶段
  • 下一次适合采取行动的时间点是什么时候
  • 哪些信息正在变旧,哪些信息仍然新鲜

这意味着时间不应该只是系统内部偷偷保存的元数据,而应该进入 Agent 可感知、可推理的上下文。

设计核心:把时间注入三个层面

我的设计很简单:把时间显式注入到三个地方。

  • 系统 TICK
  • 聊天对话
  • 行为日志

这三层分别对应三种不同的时间知觉:

  • TICK 提供“现在”与“节拍”
  • 对话提供“关系中的时间”
  • 行为日志提供“行动序列中的时间”

三者叠加之后,Agent 才不只是知道有个时间戳存在,而是真的能理解自己正处于怎样的时间流中。

一、在系统 TICK 中加入时间:给 Agent 一个持续流动的“现在”

TICK 可以理解为系统周期性唤醒 Agent 的机制。很多持续运行系统本来就有类似设计,比如每隔一段时间检查任务、轮询事件、刷新状态。但在很多实现里,TICK 只是一次“被叫醒”,而不是一次“时间被告知”。

这是非常可惜的。

因为 TICK 正是 Agent 感知时间流动最自然的入口。每次 TICK 到来时,系统都应该明确告诉 Agent:

  • 当前绝对时间
  • 距离上次 TICK 过去了多久
  • 距离上次用户消息过去了多久
  • 距离上次自己行动过去了多久
  • 是否有等待中的任务已经接近截止点

例如,一个更有时间感的 TICK 不应该只是:

TICK: check pending tasks

而应该更像:

TICK 2026-04-22 21:30:00 +08:00

这样做的价值在于,Agent 拿到的不再只是“执行检查任务”的命令,而是带着时间背景去理解“为什么现在该做这件事”。

一旦有了这种节拍感,Agent 的行为会发生明显变化:

  • 它更容易做出“现在先不打扰用户”的判断
  • 它能区分“马上跟进”和“再等一会儿”
  • 它能感知某项任务是否拖得太久
  • 它能形成周期性工作的稳定节奏

换句话说,TICK 不只是调度器事件,也应该是 Agent 的“时间感官输入”。

二、在聊天对话中加入时间:让 Agent 理解关系和上下文的衰减

对话是 Agent 与用户建立连续关系的核心场域,但很多对话记录默认只有文本顺序,没有清晰时间语义。模型当然可以从“上一条在前,下一条在后”推断先后,但这远远不够。

因为对话的意义,不只取决于内容,还取决于间隔。

同一句“我明天再看”,出现在一分钟前和出现在三天前,含义完全不同。同一句“稍等一下”,如果已经过了两小时,Agent 就应该重新理解它的状态,而不是把它仍然当作一个即时承诺。

所以,对话记录应该把时间直接暴露给 Agent。最简单的方法,是为每条消息附带:

  • 发送时间
  • 距离当前的相对时间
  • 与上一条消息的间隔

例如:

[2026-04-22 18:02 +08:00]user: 我晚上回来再决定要不要部署

[2026-04-22 21:07 +08:00]user: 可以,开始吧

这样一来,Agent 不只是“看到了第二条消息”,它还能注意到两条消息之间经历了一段真实时间。这会直接改善几个关键能力。

第一,它能更准确地处理承诺与延迟。

用户说“稍后”“明天”“下周看看”这类表达时,本来就带有时间约束。把时间戳显式放进对话,Agent 才能把这些自然语言锚定到真实世界。

第二,它能识别对话热度。

如果用户刚刚连续发送了三条消息,说明当前对话活跃,Agent 应该更实时、更紧凑。如果用户沉默了 18 小时,Agent 的语气、策略和主动程度就该不一样。

第三,它能理解上下文的新鲜度。

一些短期状态只在短时间内有效,比如“我现在在开会”“我马上回来”“这个报错刚刚出现”。如果没有时间信息,这类状态在上下文中会被无限延长,最终变成误导。

所以,对话加时间,并不是为了展示日志更漂亮,而是为了让 Agent 真正理解“关系也在时间中变化”。

三、在行为日志中加入时间:让 Agent 看到自己的行动轨迹

如果说对话时间帮助 Agent 理解用户,那么行为日志里的时间,帮助 Agent 理解自己。

很多 Agent 系统其实已经有 action log,会记录:

  • 调用了什么工具
  • 搜索了什么内容
  • 写了什么文件
  • 做出了什么决策

但如果这些日志只有动作,没有时间,Agent 对“自己做过什么”的理解仍然是扁平的。它知道自己做过,却不知道是在什么时候做的,也不知道几个动作之间隔了多久。

这会带来一个很常见的问题:重复行动。

比如它 20 秒前刚查过一次网页,30 秒前刚跑过一次测试,2 分钟前刚提醒过一次用户。如果日志里没有时间,模型在上下文压缩后很容易只剩下“做过这件事”,却没有“刚刚做过”的感觉。

所以行为日志应该包含:

  • 动作发生时间
  • 与上一个动作的时间间隔
  • 动作耗时
  • 动作后的状态变化

例如:

[21:10:03] action: checked CI status
duration: 4s
result: 1 failing job found

[21:10:18 | 15s later] action: opened failing job logs
duration: 7s
result: test timeout in memory-injector.spec.ts

[21:12:01 | 1m43s later] action: replied to user with diagnosis
duration: 18s
result: waiting for confirmation before patching

这样的日志会带来两个关键变化。

第一,Agent 开始拥有“行为连续性”。

它不再只是看到一串离散动作,而是看到自己如何从检查、诊断、回复,一步步推进任务。连续性一旦出现,策略质量通常会显著上升。

第二,Agent 开始拥有“节奏记忆”。

它知道自己刚刚已经尝试过某种方法,就不容易立刻重复;它知道某个等待已经持续了很久,就更容易决定该升级处理;它知道某次尝试耗时异常,就会意识到系统可能卡住或依赖项出了问题。

行为日志加时间,本质上是在给 Agent 构造一种弱形式的自我时间意识。

三层时间组合后,Agent 会出现什么变化

当 TICK、对话、行为日志都带上时间后,Agent 的变化并不是“回答里多了几个时间词”,而是工作方式会变。

它会开始从事件驱动,转向事件加时间驱动。

这种变化至少体现在五个方面。

1. 能更好地等待

等待不是不做事,而是知道什么时候不该动,什么时候该重新介入。

没有时间感的 Agent 很难真的会等待,它要么过于积极,不停打扰;要么过于被动,一直沉默。加入时间后,它才能形成“等待窗口”“重试间隔”“超时升级”这些真正可执行的策略。

2. 能更好地管理优先级

优先级从来不只是任务的重要程度,也包括时效性。

一个 10 分钟前出现的阻塞,和一个已经拖了 3 天的阻塞,应该有不同处理方式。时间一旦进入推理过程,优先级就不再是静态标签,而是动态判断。

3. 能更好地避免重复

许多 Agent 的低质量行为,本质上是“忘了刚刚干过什么”。时间日志会显著缓解这个问题,因为“刚刚做过”和“以前做过”终于被区分开了。

4. 能更好地处理长期任务

长期任务最怕的不是复杂,而是失去节奏。什么时候回访、什么时候复盘、什么时候重新扫描环境,这些都离不开时间感。一个有时间感的 Agent,才可能真正承担持续运行的任务。

5. 能更像一个真实协作者

协作者最重要的不是立刻回答所有问题,而是知道什么时候该回应、什么时候该推进、什么时候该沉默、什么时候该提醒。时间感会让 Agent 的互动方式明显更像人类协作,而不是一个只会即时响应的接口。

这套设计的关键,不在“记录时间”,而在“让模型看见时间”

这里有一个非常重要的实现原则:时间信息必须进入模型真正能读到、能利用的上下文,而不是只存在数据库里。

很多系统其实已经保存了时间戳,但模型推理时看不到,或者只在需要时临时查一下。这样做当然比完全没有好,但仍然不够。

如果时间只是后端字段,它属于系统;如果时间进入上下文,它才属于 Agent。

因此,这套设计真正的重点不是“数据层补了几个字段”,而是:

  • TICK prompt 里要有时间
  • 对话消息里要有时间
  • 行为摘要里要有时间
  • 在记忆压缩和上下文裁剪时,要尽量保留时间关系

尤其是在做摘要时,不能只保留“发生了什么”,还要保留“是什么时候发生的”“间隔了多久”。否则一压缩,时间感又丢了。

一个可执行的最小实现框架

如果要把这个设计快速落地,我会建议从一个最小版本开始。

第一层:统一时间表示

所有 TICK、消息、行为日志都使用统一格式,例如:

  • 绝对时间:2026-04-22 21:30:00 +08:00
  • 相对时间:3 minutes ago
  • 间隔时间:12 minutes since previous event

统一表示非常重要,因为模型对规律性很敏感,格式越稳定,越容易形成可靠理解。

第二层:在上下文组装阶段注入时间

不要等模型自己问“现在几点”。系统在组装上下文时就主动提供:

  • 当前时间
  • 最近事件时间线
  • 关键等待项的起始时间与剩余窗口

这一步决定了时间感是不是默认存在,而不是偶尔存在。

第三层:在摘要器里保留时间关系

如果你有 memory summarizer 或 action summarizer,要明确要求它保留时间语义,例如:

  • 用户在 2 小时前要求等待部署确认
  • 15 分钟前已经执行过一次状态检查
  • 该任务已连续 3 天没有新进展

比起“用户要求等待部署确认”,这种摘要对 Agent 更有用得多。

第四层:把时间变成决策变量

不仅要展示时间,还要在系统提示词中明确要求 Agent 使用时间做决策,例如:

  • 如果距离上次提醒不足 30 分钟,不要重复提醒
  • 如果等待超过 24 小时且任务阻塞,考虑发起温和跟进
  • 如果某条上下文超过预设有效期,降低其权重

这一步会把时间从“可见信息”变成“行为规则的一部分”。

可能的代价与风险

当然,这个设计不是没有成本。

第一,时间信息会增加上下文长度。

第二,如果格式设计得太啰嗦,可能反而稀释有效信息。

第三,过强的时间驱动可能让 Agent 变得机械,比如固定每隔多久就打扰一次用户。

所以关键不是“把所有时间全塞进去”,而是做有层次的时间表达:

  • 当前时间必须强可见
  • 最近关键事件应高保真保留
  • 较远历史可以摘要成相对时间
  • 无关时间细节可以压缩

也就是说,我们要给 Agent 的不是“时间噪声”,而是“时间结构”。

最后:一个能持续运行的 Agent,必须活在时间里

我越来越相信,Agent 的下一步演化,不只是更长上下文、更强工具调用或更复杂的工作流编排,而是补上那些人类默认拥有、但系统经常忽略的基础知觉。

时间感就是其中一个最关键的知觉。

当 Agent 能在 TICK 里感受到现在,在对话里感受到关系的间隔,在行为日志里感受到自己的行动轨迹,它就不再只是一个被动响应输入的模型,而更像一个正在时间中持续存在的行动者。

这件事听起来很小,只像是在 prompt 和日志里多写几个时间字段。但它改变的,其实是 Agent 对世界的坐标系。

没有时间感的 Agent,只能处理片段。

有时间感的 Agent,才有机会真正进入过程。