最近我一直在思考一个问题我们今天构建 AI Agent 的方式是不是过度围绕“完成一次任务”设计了现在大部分 Agent 产品的基本单位都是一次 Run你给它一个任务它理解需求、制定计划、调用工具、执行、验证然后交付结果。即使引入了 multi-agent、workflow、subagent本质上仍然是在优化同一件事如何把一次任务做完。但现实世界里很多真正重要的工作并不是一次任务。它们没有一开始就确定的执行路径也不会在一次 Run 结束时得到最终答案。它们需要持续观察外部世界在不同时间采取行动等待反馈再根据结果调整策略。它们更像一个长期运行的 loop。Cold email 不是一个任务比如 cold email。如果把它写成任务可能是找到 100 个潜在客户写邮件并发送。Agent 确实可以一次完成这些动作。但真正的目标通常不是“发出 100 封邮件”而是找到一套能够稳定产生有效客户对话的 outbound 方法。这个 Goal 可能持续几周甚至几个月。每天只能发送有限数量的邮件。发完之后继续运行 Agent 没有意义。它必须等待第二天额度恢复。有些收件人会在当天回复有些会在三天后回复有些标题打开率高但回复率低有些文案能获得回复却吸引了错误类型的客户。于是真正的工作过程更像观察昨天的数据 → 检查新回复、退信和额度 → 判断当前最大的差距 → 选择今天要测试的人群或文案 → 发送有限的一批邮件 → 记录结果 → 等待新的外部反馈 → 第二天重新判断这里每天是一个小周期。但整个 Goal 是由许多个日周期组成的。更重要的是第二天的行动不能只是重复第一天的 prompt。它应该基于昨天留下的证据重新决定下一步。“等待”也是 Goal 的一部分今天的 Agent 系统通常不太擅长处理等待。在一个 Run 内如果 Agent 没有继续执行它看起来就像停了、失败了或者被阻塞了。但在长期 Goal 中等待经常是正确状态等待邮件额度恢复等待对方回复等待 CI 完成等待代码评审等待应用商店审核等待一周的数据积累等待用户真正使用新功能等待人工决策这不是 blocked。这是当前没有值得执行的动作但 Goal 仍然在继续。所以我越来越觉得Heartbeat 不应该简单理解为“定时唤醒 Agent 干活”。Heartbeat 更应该是定时或由事件触发让 Agent 重新观察世界并判断现在是否值得行动。一次成功的 Heartbeat完全可能只输出没有出现新反馈 当前策略无需调整 继续等待 下次检查明天上午 9 点 如果收到客户回复则提前唤醒没有调用工具没有生成新的任务也没有消耗大量 token。但这个 loop 是健康的。我们最近的发版工作也是一个真实案例我们最近一直在优化 Rudder 的发版流程。表面上看“发布 v0.6.5”是一个任务。它有明确的版本号有发布脚本也有相对明确的完成条件。但我们真正想解决的 Goal 不是把某一个版本发布出去。而是让每一次发版都能够在一个可预测的时间窗口内完成。这是两个完全不同的问题。一次发版偶然很快并不代表发版系统已经变好了。我们真正关心的是从锁定发布代码到所有公开渠道验证完成需要多久npm、GitHub Release、Desktop、文档站分别花了多久时间花在机器执行上还是花在等待和返工上为什么有时很快有时会拖很久哪个阶段决定了 p90而不只是平均值这次修复的瓶颈在下一次发版中真的消失了吗最近我们做了很多具体工作让发布流程绑定经过验证的准确 source commit尽量复用已经通过的 CI 结果减少重复运行的系统验证把能够快速失败的检查提前避免 canary 和 stable release 相互争抢发布资源缩短 Desktop 构建和验证的等待让发布完成后的下一版本交接更加确定每一项看起来都像一个独立的 feature 或 fix。但如果只把它们当作任务任务合并后就结束了。只有把它们放回“收敛发版时间”这个长期 Goal我们才会继续追问这个改变有没有让下一次真实发版变得更快、更稳定如果没有那么代码虽然完成了Goal 却没有前进。真正的 loop 应该是执行一次真实发版 → 保存每个阶段的时间与失败证据 → 找到最长尾的瓶颈 → 提出一个改进假设 → 完成一个最小改动 → 在下一次真实发版中验证 → 保留、调整或回滚 → 继续寻找新的最大差距这个 Goal 不属于任何一次发布。它横跨许多次发布并通过每一次发布获得新的反馈。Feature 开发也不是一次直线执行即使是看起来周期较短的 feature 开发也存在同样的问题。我们最近在处理 Messenger 长对话下的滚动性能。“修复滚动空白”可以是一张 issue。但真正想得到的结果是Messenger 在真实的高压力对话中仍然保持稳定、流畅和可理解。一次代码修改不能证明这个结果已经实现。Agent 需要经历多个更小的 loop复现问题 → 提出原因假设 → 修改最小范围 → 运行压力测试 → 在真实界面中观察 → 检查是否引入新的交互问题 → 根据结果继续调整自动化测试通过只能提供一部分证据。真实 UI 没有空白却出现滚动跳动是新的差距。单一对话正常但大量实时更新时再次退化也是新的差距。所以对一个 feature 来说单次 loop 的边界不应该是“写完了多少代码”而应该是是否完成了一次能够产生新证据的验证。例如让 1,000 条消息下的快速滚动不再出现空白并在真实界面和压力测试中验证。这是一个可观察、可证伪的小周期。而“让 Messenger 在真实工作负载下持续流畅”则是一个更长的 Goal。大 Goal 不是更大的 Task这也是我目前最重要的判断我们不应该通过不断扩大 Task 来表达长期 Goal。一个持续三个月的 Goal不应该变成一个持续三个月、永不结束的 Agent session。长期性不应该依赖一个无限增长的上下文窗口。它应该存在于持久化的状态、证据和决策里。每次 Run 结束时都应该给下一次 Run 留下一个足够小、足够明确的 checkpoint当前状态是什么 这次发生了什么变化 我们获得了什么证据 距离目标还差什么 当前最大的差距是什么 下一步准备验证什么 现在应该继续执行还是等待 由什么时间或事件再次唤醒下一次可以是一个全新的 Agent session。只要它能读取这些状态就应该知道为什么这个 Goal 存在、上一次做了什么以及现在最值得做的下一步是什么。也许我们需要三层 Loop我目前倾向于把 Agent 工作拆成三层。第一层Run Loop持续几分钟到几小时。理解局部目标 → 提出下一步 → 执行 → 观察结果 → 判断差距 → 调整或结束它追求的是一次可验证的进展。第二层Heartbeat Loop持续几天到几周。读取上一次 checkpoint → 检查时间、事件和外界反馈 → 判断是否需要行动 → 创建或执行下一项工作 → 更新状态 → 设置下一次唤醒条件它负责跨 Run 保持连续性。第三层Goal Loop持续几周到几个月。检查核心指标是否收敛 → 判断当前策略是否仍然有效 → 找到新的主要瓶颈 → 调整任务、流程、skill 或资源 → 从真实结果中学习它关心的不是“做完了多少任务”而是外部世界是否真的接近目标状态。这会带来一组新的产品问题一旦把 Goal 当成长期 loop而不是任务分类标签会出现很多有意思的问题Agent 怎么区分“合理等待”和“已经停滞”Heartbeat 应该由固定时间触发还是由事件、指标变化和超时共同触发每一次 Run 最少需要保存哪些状态才能让另一个 Agent 无损接手下一步应该由 Goal owner 自己决定还是由预先定义的 workflow 决定如何避免 Agent 为了显得有进展不断制造无意义的任务如何限制长期 Goal 的 token、预算和外部操作Goal 的完成应该由 Agent 判断、指标判断还是必须经过人类 review如果局部任务全部完成但核心指标没有变化系统应该如何暴露这种“伪进展”一个 Goal 是否应该能够修改自己的策略却不能偷偷修改自己的成功标准我觉得这些问题可能比“Agent 能不能再多调用几个工具”更接近下一阶段 Agent 产品需要解决的东西。Rudder 把 Goal、Task、Chat、Issue、Agent Run、Review 和 Feedback 连接成 Agent 团队的工作 loop。它为人类和 Agent 提供一套共享的工作结构用来推进工作、运行 Agent、审查产出、控制成本并保留能让下一次 Run 做得更好的经验。但我们现在更想进一步回答Goal 能不能不只是一个长期的 why而是成为一个跨越许多 Run、持续观察和缩小差距的工作 loop这意味着 Heartbeat 不只是定时执行。等待必须成为一等状态。每次 Run 必须留下可以继续的 checkpoint。Goal 必须能看到真实指标、外部反馈、成本和证据。系统也必须知道什么时候应该执行什么时候应该停下来什么时候应该换策略以及什么时候真的可以宣布 Goal achieved。我还没有觉得这个问题已经有了完整答案。甚至“Goal controller”是不是正确的抽象我也不确定。但我越来越相信Agent 真正重要的下一步可能不是在一次 Run 里变得更强。而是它能不能在明天、下周甚至下个月重新回到同一个 Goal读懂世界发生了什么变化然后做出一个比今天更好的下一步决定。如果一个 Agent 能完成任务却不能长期追踪结果、等待反馈、修正策略它究竟是在工作还是只是在执行命令很好奇大家会怎么设计这种长期 Goal。