[控场AI]
· 17 分钟阅读· 8,928 字

提示即平台:AI Agent如何深度参与系统设计与规范

提示即平台:AI Agent如何深度参与系统设计与规范

一个大胆的预言:软件平台的终结

编码AI Agent将悄然让第一批软件平台退役——不是因为它们不够好,而是因为它们变得不再必要。这是Resonate创始人兼CEO Dominic Torno在AI Engineer大会上抛出的核心观点。

Resonate是一个以极简主义(minimalism)和简洁性(simplicity)为核心技术价值观的**持久化执行(durable execution)**平台。持久化执行是一种编程范式,确保长时间运行的工作流在进程崩溃、网络中断或机器重启后能够自动恢复并继续执行,而非从头重来。其核心思想是将程序的执行状态持久化到外部存储,使计算具备"检查点"能力。

持久化执行范式的兴起与分布式系统的普及密切相关。早期的单机程序崩溃后重启即可,但在微服务和云原生架构下,一个业务流程可能横跨数十个服务、持续数小时乃至数天,任何节点故障都可能导致整个工作流丢失状态。这一痛点直接催生了两类解决方案:一类是以AWS Step Functions、Azure Durable Functions为代表的托管服务,将可靠性保障下沉至云平台层;另一类是以Temporal(前身为Cadence,由Uber工程团队开发并开源)为代表的开源框架,其工程哲学是让开发者用普通函数编写工作流逻辑,由框架自动处理所有可靠性保障——开发者无需关心幂等性实现、重试退避策略或状态持久化机制,这些横切关注点全部由运行时托管。值得注意的是,持久化执行本质上是对"分布式事务"问题的一种实用主义解法:它放弃了两阶段提交(2PC)的强一致性保证,转而通过事件溯源和幂等重试构建"最终正确"的语义。

Temporal作为该领域最具影响力的开源框架,通过事件溯源(Event Sourcing)机制记录工作流的完整执行历史,Worker节点在重启后可通过"重放"历史事件还原到故障前的精确状态,在金融交易、订单履约等对可靠性要求极高的场景中被广泛采用。Resonate在此赛道上的差异化在于其极简主义哲学:Temporal涉及Workflow、Activity、Signal、Query等多个原语,而Resonate试图仅用两个核心对象(承诺与任务)覆盖相同场景。这种极简主义在AI Agent生成代码时尤为有价值——原语越少,规范越易表达,生成的实现越可能正确。

Torno团队正在验证这样一个理论:软件工程的方向正在发生根本转变——通用实现(general purpose implementations)将越来越多地被按需生成的定制实现(bespoke implementations)所取代。

关键在于,这些定制实现不再是新的库、框架或平台,而只是对现有基础设施的最小化扩展。如果这个理论成立,"复用"(reuse)将向上游转移:我们不再复用通用实现,而是复用规范(specification),并从中派生出针对特定基础设施定制的实现。此时,提示即平台(The Prompt is the Platform)。

价值从实现转向规范

当实现变得可生成时,工程师的价值究竟在哪里?Torno给出的答案清晰而深刻:我们的价值从实现转向了规范。

规范与实现的分离是软件工程的经典议题,可追溯至Dijkstra、Hoare等人的形式方法研究。形式化方法(Formal Methods)在工业界长期被视为学术工具,但随着系统复杂度飙升,其实用价值得到重新认可。除TLA+外,Alloy(MIT开发的轻量级形式化建模语言)、Coq/Lean等定理证明器也在安全关键系统中被采用。形式规范的本质是用数学语言消除自然语言描述中的歧义——一份英文设计文档可能被十位工程师理解为十种不同的行为,而一份TLA+规范只有唯一的语义解释。这种精确性不仅服务于人类工程师之间的沟通,在AI时代更成为将意图无损传递给Agent的关键媒介。值得关注的是,形式规范语言本身也在演化:传统的TLA+要求工程师掌握时序逻辑的数学符号体系,学习曲线陡峭;而新兴的规范语言如Quint(TLA+的现代语法变体)和P语言(微软研究院开发,专为协议验证设计)正试图降低形式化方法的准入门槛,使更广泛的工程团队能够受益于形式规范的严谨性。

Leslie Lamport开发的TLA+(Temporal Logic of Actions)是目前工业界最成熟的形式规范工具,允许工程师用数学语言精确描述系统的状态机行为,并通过模型检测器(Model Checker)自动穷举所有可能的状态转换路径以发现违反不变量的场景。Amazon AWS工程师使用TLA+对DynamoDB的复制协议进行验证,发现了仅凭代码审查和测试无法发现的深层并发缺陷。微软Azure Cosmos DB、Intel TigerBeetle等工业级系统也先后引入形式化方法作为设计阶段的必要工序,标志着形式规范从"学术奢侈品"向"工程标准件"的转变。

在AI时代,规范的价值被进一步放大:一份精确的规范可以被用来生成面向PostgreSQL的Rust实现,也可以生成面向NATS的Go实现,还可以在未来生成面向SQLite或Cassandra的实现。规范因此从"开发前的设计文档"演变为"可反复提取价值的知识资产",其生命周期远超任何单一具体实现。Resonate的实践可视为这一形式化传统在AI时代的延伸——当实现可以由Agent生成时,规范的价值被进一步放大,规范本身成为可复用的核心产品。

这彻底改变了Resonate对自身产品的定义。产品不再是具体的实现,而是规范和协议本身。基于这个协议,团队希望派生出多个服务端实现:

  • 一个通用的Resonate服务器作为参考实现
  • 多个与基础设施合作伙伴共建的实现,让持久化执行能力直接运行在客户已有的技术栈之上,且几乎不引入额外依赖

真正的问题因此不再是"如何实现产品",而是"能否用同一份规范反复合成出可信赖的服务器,以及如何做到"。

The agent helped us build

有意思的是,当业界讨论Agent工程时,注意力几乎全部集中在**验证(verification)**上——如何确认结果是正确的。Torno却选择把焦点放在规范本身,以及一个更根本的问题:Agent如何参与系统的设计(specifying),而不只是构建或验证。

从抽象规范到具体实现的鸿沟

为了探索这套Agent工程实践,Resonate与NATS.io背后的公司Synadia展开合作。NATS.io是专为现代分布式系统设计的开源消息系统,由Synadia开发,以极低延迟、极高吞吐量和轻量级部署著称。

消息系统是分布式架构的神经中枢,其设计哲学的差异深刻影响着上层应用的架构选择。Kafka以"不可变日志"为核心抽象,强调持久性与可重放性,代价是相对较高的运维复杂度;RabbitMQ以AMQP协议为基础,提供丰富的路由语义,适合企业级消息队列场景;NATS则走向了另一个极端——以极度简洁的核心换取极致性能,其Go语言实现的服务器二进制文件不足20MB,可在边缘设备上运行,这在IoT和边缘计算场景中极具竞争力。NATS的这种极简哲学并非偶然:其创始人Derek Collison曾主导开发TIBCO的消息中间件,深知企业级消息系统的"功能膨胀"陷阱——每一个新增的路由语义、确认机制和持久化选项都在降低系统的可预测性和可运维性。NATS的设计选择是"宁可在协议层做减法,在客户端库层做加法",这使得协议核心保持了极高的稳定性和可验证性。

NATS最初由Derek Collison于2010年创建,其设计目标是为云原生应用提供极低延迟的消息通信基础设施。与Apache Kafka"以日志为中心"的持久化优先哲学不同,NATS的核心是一个极其轻量的发布/订阅路由器,单节点可处理每秒数千万条消息。JetStream是NATS于2021年引入的持久化层,为其添加了at-least-once和exactly-once语义支持,以及键值存储和对象存储能力。然而,JetStream的键值存储在集群模式下基于Raft共识协议进行领导者选举,读取操作默认可能从非领导者节点返回,这就产生了合法的陈旧读取窗口。这一设计并非缺陷,而是在高可用与强一致性之间的有意权衡——这正是CAP定理在工程实践中的具体体现,也是Resonate团队需要处理陈旧读取问题的根本原因。CAP定理(由Eric Brewer于2000年提出,Gilbert和Lynch于2002年正式证明)指出,分布式系统在网络分区发生时无法同时保证一致性(Consistency)与可用性(Availability),工程团队必须在两者之间做出明确的取舍,而这一取舍将深刻影响所有上层算法的设计边界。

常见的Agent编码心智模型很简单:一个Agent、一份规范、一个实现。对许多应用来说这已足够。但Resonate的目标不是从规范生成"一个"实现,而是生成多个针对不同目标平台的实现。

这就要求规范必须足够抽象——它不能假设任何具体的数据库schema或索引,不能假设使用关系型数据库,不能假设键值存储,不能假设弱一致性或强一致性。规范必须是抽象的,只有实现才是具体的。

第一次尝试时,团队直接要求Agent"在Postgres上用Rust构建一个Resonate服务器"。结果失败了。抽象规范与具体实现之间的鸿沟太大——生成的系统只在"happy path"上工作,能通过基础测试,但并不正确:它在并发下崩溃,在进程失败下崩溃,在网络失败下崩溃。这更像是一个原型,而非生产系统。

引入中间产物:具体规范

团队随即修正了流程,在抽象规范和具体实现之间插入了一个中间产物——具体规范(concrete specification)。

对于Postgres而言,这意味着将所有针对目标平台的决策明确记录下来:数据schema、索引、SQL查询、事务边界。一旦这些决策被固化,Agent确实能够实现一个生产级系统。

但这也暴露了局限性:Agent帮我们构建了系统,却没有帮我们设计系统。 那份具体规范仍然是人类主导交互产出的。如果规范是可复用的产品,这还远远不够。

让Agent走向上游:确定性模拟

下一步显而易见——Agent必须向上游移动,参与设计。但如何实现?

在NATS.io上构建Resonate时,团队改变了提问方式。他们不再问"Agent能否构建生产系统",而是问:"Agent需要什么,才能先设计系统、再构建系统?"

答案是给Agent一个确定性模拟环境(deterministic simulation environment),并交给它一个不同的任务:不要构建生产系统,而是构建一个模拟实现。

确定性模拟测试(Deterministic Simulation Testing,DST)由FoundationDB团队系统化提出并推广,后被TigerBeetle、Antithesis等新一代存储系统广泛采用。其核心思想是用一个完全受伪随机数生成器(PRNG)控制的虚假基础设施替代真实的非确定性环境:网络延迟、磁盘故障、消息乱序、时钟漂移都在同一个PRNG种子的控制下按确定顺序发生。给定相同种子,系统行为百分之百可重复,这意味着任何一次测试失败都可以被无限精确地复现和分析。DST的哲学与函数式编程中"纯函数"的思想一脉相承:通过消除所有外部副作用和非确定性来源,将系统行为降格为一个纯粹的输入-输出映射,从而使整个状态空间变得可枚举和可推理。这一思想的工程实现难点在于如何构建足够逼真的虚假基础设施——模拟的网络延迟分布、磁盘故障模式必须覆盖真实环境中所有合法行为的超集,才能确保"在模拟中正确"等价于"在生产中正确"。

传统分布式系统测试面临一个根本性困境:测试环境的非确定性使得偶发性故障(Heisenbug)极难复现和调试。混沌工程(Chaos Engineering)虽然能发现问题,但每次注入的故障序列不同,难以精确归因。DST通过将所有非确定性来源替换为受控的虚假实现,从根本上解决了可重复性问题。TigerBeetle将DST推进到了极致:其模拟框架Vopr可在单台笔记本上每秒模拟数千个集群年的运行历史,这在传统集成测试框架下完全不可想象。FoundationDB的工程师曾公开表示,他们在产品发布前通过DST运行了相当于数十万年的分布式系统模拟时间。对AI Agent而言,DST的价值在于将"随机试错"变为"精确归因"——Agent不再需要猜测故障来源,而是可以逐帧回放导致不变量违反的确切事件序列,从根本上加速了算法设计的收敛过程。

模拟实现不是产品,而是可执行的设计(executable design)。它的目的是在偏序(partial order)和部分失败(partial failure)条件下发现正确的算法。一旦算法在模拟中被发现、测试和验证,才让Agent编写具体规范,最后才编写生产实现。

于是整个流程变为:抽象规范 → 模拟实现 → 具体规范 → 具体实现。这正是Agent走向上游、成为设计驱动者的关键节点。人类仍然参与设计,但这一次,Agent是驾驶员。

simple primitives

极简与简洁是终点而非起点

让这一切成为可能的两个要素是极简主义与简洁性。但Torno强调,它们不是起点,而是终点。团队花了数年时间把协议做得更小、更简单——每遇到一个问题就追问:能拿掉什么?能抹去哪个抽象?能移除哪个属性?能打破哪个关系?

最终得到的是一个极小的协议,围绕两个对象展开:持久化承诺(durable promise)和持久化任务(durable task)。简洁之所以重要,是因为即便是简单的并发分布式协议,其状态和行为空间也极其复杂。这种极度精简的抽象设计在计算机科学史上有著名先例:Unix"一切皆文件"的哲学将文件、套接字、管道、设备统一为单一抽象,使整个操作系统的接口面极度收窄;Lisp将程序与数据统一为S表达式,使元编程成为自然而非例外。Resonate的两原语设计遵循同样的哲学:接口的简洁性不是功能的缺失,而是对核心不变量的深刻提炼——简洁的规范不仅更易于形式化验证,更易于在不同基础设施上无歧义地实现,也更易于AI Agent在有限上下文窗口内完整理解和正确操作。

陈旧读取:真实世界的复杂性

以NATS为例,它提供了一组可构建的原语:队列、键值存储、延迟/定时消息。设计问题变成:如何仅用这些原语表达Resonate协议?

以键值存储为例,它是带版本的。你创建键值foo(版本0),更新为bar(版本1),再更新为bus(版本2)。大多数时候读取会得到最新值bus。但有时读取会返回陈旧值(stale read)——最新值明明是bus版本2,读取却返回foo版本0。

这不是数据损坏,也不是键值存储的bug,而是目标平台一致性模型下的合法读取。这一点至关重要:实现不能只在目标平台"表现良好"时正确,而必须在目标平台"合法行事"时也正确。

更麻烦的是,你无法通过读取本身知道读到的是陈旧值。只有在稍后尝试写入时才会发现——这正是**乐观并发控制(Optimistic Concurrency Control,OCC)**机制发挥作用之处。

OCC由H.T. Kung和John T. Robinson于1981年在其经典论文中正式提出,是对悲观锁策略的重要补充。并发控制策略的选择本质上是对"冲突概率"与"锁开销"之间的权衡判断:悲观锁假设冲突频繁发生,在读取时即加锁,保证写入成功但牺牲了并发吞吐;OCC假设冲突稀少,允许并行读写,仅在提交时验证,适合读多写少的工作负载。在分布式键值存储中,这一权衡被CAP定理进一步复杂化:强一致性系统(如etcd、ZooKeeper)要求所有读取都经过领导者,确保新鲜性但增加延迟;最终一致性系统(如Cassandra、DynamoDB默认配置)允许从任意副本读取,提升可用性但引入陈旧读取窗口。值得注意的是,OCC并非银弹:在写入竞争激烈的场景下,大量事务会在提交阶段失败并触发重试,导致系统吞吐量急剧下降,甚至出现"活锁"——所有事务都在不断重试却没有一个能成功提交。这一现象在数据库理论中被称为"高冲突工作负载下OCC的退化",也是工程师在选择并发控制策略时必须预先评估的边界条件。

OCC的核心假设是冲突在大多数工作负载下属于罕见事件,因此允许多个事务并行读取和修改数据,仅在提交阶段通过版本比对检测冲突。在键值存储中,这通常通过条件写入(Conditional Write)或Compare-And-Swap(CAS)原语实现:客户端读取键值时同时获取其版本号,提交更新时将读取时的版本号附带给存储层,存储层仅在当前版本与附带版本一致时才接受写入,否则返回冲突错误并要求调用方重新读取最新版本后重试。etcd、DynamoDB条件写入、Redis的WATCH/MULTI/EXEC机制都是OCC的工业级实现。

当你基于版本0去更新,而键已经移动到版本2时,写入会失败。这正是目标平台告诉你"你看到的世界不是当前的世界"的时刻。当陈旧读取与OCC结合时,算法必须在"可能看到过期世界"的前提下设计正确的重试逻辑,同时保证在任何合法的陈旧读取序列下,系统级不变量(如承诺的幂等性、任务的恰好一次执行语义)始终得到维护——无论对人类还是对Agent都绝非易事。

to ace this task

禁果:让Agent看见因果

Agent依赖反馈而蓬勃发展——即时、无歧义的反馈。不仅是"这里出错了",而是"为什么以及如何出错":返回了什么陈旧值?触发了什么逻辑?哪个写入失败了?哪条不变量因此被打破?

为此,团队用Python构建了确定性模拟测试环境,模拟了他们所依赖的NATS.io部分。模拟的键值存储保留每个键的完整版本历史:GET时有时返回最新版本,有时在确定性随机生成器控制下返回旧版本;UPDATE时强制乐观并发控制,只有读到的版本仍是最新时写入才成功。

这让Agent面对一个在"正确性关键行为"上与真实存储一致的环境——但与真实目标不同的是,模拟是确定性的、可重复的、可检查的。当Agent写出错误算法时,团队可以复现导致失败的确切执行过程。

记录被隐藏的真相

确定性模拟还做了更多——它能暴露真实平台刻意隐藏的事实,团队称之为**"禁果"(forbidden fruit)**。

在生产环境中,从键值存储读取时你只能得到所观察版本的值,无法知道这次读取是新鲜还是陈旧,也看不到你错过的最新值——真实代码本就不应依赖这些信息。但在模拟中,这些都可以被完整记录下来。

and this is what the latest value was.

每次GET都会发出一个trace事件:如果读取是新鲜的,trace标注"fresh";如果是陈旧的,trace标注"stale",同时记录"你得到了什么"和"被隐藏的最新值是什么"。这些信息对算法是禁止依赖的,但对Agent调试却极其有用。

它让Agent不只是知道"不变量失败了",而是知道"不变量失败是因为算法基于一个陈旧的世界视图做出了决策"。因果关系变得可见——Agent不只学到系统错了,更学到系统为什么错。

这一设计与强化学习中奖励信号的塑造(Reward Shaping)有深刻的结构性相似:稀疏奖励(仅告知最终成败)使Agent难以收敛,而密集的中间奖励信号(标注每一步决策的局部后果)能显著加速学习。从信息论的视角来看,"禁果"trace实际上是在不改变系统外部接口契约的前提下,向调试者(无论是人类还是AI Agent)传递了额外的互信息(mutual information)——这些信息本存在于系统内部,只是被生产契约刻意封装隐藏。将其在调试层面暴露,相当于为Agent提供了一个"上帝视角"的观察通道,使其能够在不干预系统行为的前提下获取因果推断所必需的完整证据链。"禁果"trace本质上是一种专为调试Agent设计的密集因果信号——它不改变系统的外部行为契约,却将内部的信息隐藏层完全透明化,使Agent能够在不违反生产约束的前提下获得超越生产环境的调试视角。

结语:规范即产品

凭借这套方法,Agent成功弥合了抽象与具体之间的鸿沟。流程首先在确定性模拟器中构建概念验证,用测试套件验证正确性;从已知正确的概念验证中派生出具体规范;再从具体规范派生出生产实现。

确定性模拟让Agent得以参与设计,而不仅仅是实现。从一份抽象规范出发,Agent经由"模拟→具体规范→具体实现"的路径,设计并构建了整个平台。人类依然深度参与设计过程,但这一次Agent是驾驶员。

正如Torno所总结的:提示与规范,就是产品本身。 这一实践为AI Agent深度参与分布式系统工程提供了极具启发性的范式——把价值从易被生成的实现,转移到难以替代的规范与设计之上。

核心要点

核心要点

分享:

相关推荐