Vault

把智能体变成分布式状态机:Palantir Agent Engine 与 Agent SDK 发布

cover

摘要

DevCon 6 上,Palantir 发布了智能体栈(agent stack)的下两层:Agent Engine 与 Agent SDK。演讲者从现场与客户身上学到的教训出发:智能体不是一种形状——任务智能体、副驾驶(copilot)、自主智能体、交互式智能体、AI FDE、AIP 分析师,以及完全不交互的智能体,任何框架都必须能构建这全部形态。

更深层的教训是:真实世界是异步且并发的。智能体可能等待一位护士、一份化验结果、一个构建系统——每个都可能要一周以上才返回;用户同时处理智能体与两封邮件,竞态条件(race condition)随之而来。真实世界更像一个分布式系统:许多智能体、许多人类,每个参与者都需要不同的视图——「不把智能体正确地渲染给每个参与者,就无法建立信任」。这解释了为什么「while 循环包住工具调用」的简单模型会失效:智能体必须多玩家、能处理竞态与外来信号、且可渲染给所有参与者。

Agent Engine 用三大原语——上下文项(context items)、事件(events)与效应(effects)——把智能体循环变成底层为分布式状态机的架构。演示中,出院审批智能体把「待决」状态持久化,护士批准后才执行出院;新化验结果(新冠阳性)一到,事件流自动使旧决定失效并重新评估。SDK 之外,低代码构建器与 Agent Manager 治理应用也即将到来。

正文

一、智能体不止一种形状:真实世界的异步与并发

演讲者先总结了「智能体设计层」学到的教训(此前 John 讲了基础设施层的教训)。第一课:智能体不是一种形状——他们构建过任务智能体、副驾驶、简单智能体、自主智能体、交互式智能体、AI FDE、AIP 分析师,甚至完全不交互的智能体,以及介于其间的一切。任何框架都必须为开发者提供构建所有这些智能体的能力。

第二课:智能体与世界互相作用,而真实世界是异步的——在现实里,「回复」不只是你打开笔记本电脑那一刻的事:一个智能体可能在等一位护士、一份化验结果、一个构建系统,而每一个都可能要等一周甚至更久。世界还是并发运作的:用户一边与智能体协作,一边进来一封邮件,甚至同时两封——竞态条件(race condition)出现了。真实世界开始看起来非常像一个分布式系统:许多智能体、许多人类,而系统中的每个参与者都需要不同的视图——回应患者出院的护士、确认当天出院流程无误的医院管理员、为智能体响应链提供反馈回路的另一个模型。「不把智能体正确地渲染给每个参与者,就无法建立信任。」

以 AI FDE 里的构建功能为例:用户可以启动长时间运行的构建任务,它们有状态——已启动、运行中、已取消、失败——可能耗时数分钟到数小时。用户想跳过结果让会话继续,结果到了要收到通知、智能体要正确响应;如果另一个用户在别的界面取消了构建,智能体也要反映这个更新。这本质上是一个状态机——状态之间转换,带丰富的人机协同(human-in-the-loop)交互。把这些需求放到真实世界去压力测试,就会发现「一个 while 循环包住简单工具调用」根本解不了题:智能体必须支持多玩家、处理竞态与外来信号、拥有最大灵活性、可渲染给所有参与者——这不是一份容易的需求清单。

演讲者提醒:你们其实见过这个问题——在 Claude Code 里,如果终端在智能体工作时死掉,所有子智能体的工作全部丢失;这在 Claude Code 里只是有点烦人或费钱,换一个场景就可能攸关生死:「在战场上,你必须知道你做的是对的。」在 Palantir 所处的环境与赌注之下,必须把这些需求交付给智能体——这就是智能体栈存在的原因。

二、三大原语:上下文项、事件与效应——分布式状态机

演示沿用 John 的出院场景:智能体可以办理患者出院。Agent SDK 让定义复杂智能体「极其简单」:定义模型、系统提示词,再挂三个工具——查患者、拿化验结果、办理出院。出院工具也很简单:名称、描述、输入模式,外加一个异步执行函数,调用出院辅助函数后告知模型「患者已出院」。底层,患者是本体对象,这只是在跑一个动作:把患者对象上的布尔字段 is_discharged 从 false 改为 true(为演示做了简化)。

运行第一个智能体处理患者 Ayesha Patel:看到一串系统提示词、用户消息、助手消息——它们都被类型化为「上下文项」(context items)。患者成功出院、工具被调用。但缺了很多东西:UI 太难看,需要更好的界面;需要护士批准智能体的结果——「不能让智能体直接放人出院,没人签字同意」;要把智能体渲染成对护士有价值的形式;还要确保智能体响应任何外来的决策或数据——新化验结果一到,智能体必须反思并更新决定。

这就引出了 Agent Engine 的原语。层级是这样的:Orchestrator 提供持久化(durability),其上 Agent Engine 处理智能体原语,再往上 Agent SDK 让定义智能体极其容易——但随时可以「逃生舱」降级到直接在 Agent Engine API 层上构建。三大原语是:上下文项、事件与效应。一个智能体会话由上下文项组成——由智能体的开发者定义的强类型数据;上下文项通过事件(events)变更,并持有自己的强类型状态;效应(effects)可以异步运行并派发新事件——这是智能体连接外部世界的方式。

把三者缝合起来就是智能体循环:新事件进入事件队列,由你定义的事件处理器处理;处理器返回变更(mutations)与效应;变更更新状态(上下文项状态与会话状态);效应异步触达真实世界(比如模型供应商 API),回来时变成新派发的事件。这个循环的底层,是一台分布式状态机(distributed state machine)。

三、让智能体可被批准:护士审批与持久化的待决状态

修复版是第二个智能体——患者出院审批智能体:模型加系统提示词,外加自定义上下文项、对应的事件处理器,以及同样的三个工具。出院工具被更新为需要护士批准:不再直接返回字符串字面量并当场执行出院,而是返回一个「待决出院」上下文项。这个上下文项持有强类型状态:患者 ID 与审批状态——待决(pending)、已批准、已拒绝、已失效(invalidated);创建时即处于待决状态。

状态通过代码中写的事件自我变更:提交出院审批事件(带审批状态),通过返回变更把上下文项状态更新为批准或拒绝;如果护士批准了出院决定,就返回一个「执行出院」效应,由处理器调用同一个出院辅助函数、执行本体里的动作。关键的一步是:把出院效应从工具调用挪进了上下文项状态——这让「待决」状态能在智能体里持久地持有。

运行新版本(这次处理 David Park):化验结果良好、没有值得担心的,智能体建议出院。刷新页面——出院审批状态还在:它是持久的。原始结果以「待决出院上下文项」的形式保存在智能体会话里。上下文项的威力在于前端渲染:化验结果现在是强类型状态,可以给护士渲染成友好的界面,而不是像第一个演示里那样前端靠正则解析一大块文本(Ayesha 的化验结果就是一坨 blob)。

最后一个需求:智能体要能处理外来数据。在化验控制台上传一份 David 的新化验结果——一份新冠阳性检测报告(演讲者故意把 PDF 做得很长来 OCR,「制造悬念」)。注意智能体状态:化验结果到了,智能体重新评估:「这份化验结果令人担忧。这位患者得了新冠,我们不应该让他出院。」机制是:化验控制台向智能体发送「新化验结果」事件,事件处理器派发「使出院失效」事件,在上下文项状态里把状态设为已失效,再渲染给 LLM:「出院决定已过期,需要重新评估」——智能体循环重跑,LLM 拿到更多结果后决定不出院。就这几层原语,把一个真正办理患者出院的智能体所需的复杂度全部表达了出来。

四、智能体栈全景:SDK、低代码构建器与 Agent Manager

总结:今天展示的是智能体栈的下层。Agent SDK 让定义复杂智能体极其容易;Agent Engine 用低层原语支持构建任意形状的智能体;所有基于 SDK 构建的智能体都跑在 Orchestrator 之上——John 提到的全部持久化收益直接到手。Agent SDK 的测试版在 DevCon 现场可用,还有一场 canary 上手会话。

而这一切只是开始:驱动 ProCode Agent SDK 的原语将进入新的低代码智能体构建器(low-code agent builder)——组织里的任何人都能轻松定义复杂智能体;其上还有一款新应用 Agent Manager,用于监控与治理智能体——任何在本栈中发布的智能体(无论 ProCode 还是低代码)都会出现在 Agent Manager 里,成为你企业内所有智能体的统一「玻璃面板」。演讲者随后把话筒交回 Ankit,讲解如何把可观测性加进这个栈的每一层。

觉得有用?分享给一个需要的朋友 🙏