Google AX 深度解析:声明式编排数十亿 Agent 的运行时 1. 这个 AX 到底是个什么东西Google 开源 AX 这件事在技术社区里炸开锅的那天我正好在刷动态第一反应是又一个 agent 框架但仔细看完仓库结构和几篇讨论之后我意识到这东西跟市面上那些帮你写 prompt 的 SDK完全不是一个物种。AX 的核心定位是声明式编排数十亿 agent 的运行时注意这几个词——声明式、数十亿、运行时。它不是在解决怎么让一个 agent 跑起来而是在解决怎么让海量 agent 在集群里有序、可观测、可调度地活着。说白了如果你用过 Kubernetes 编排容器那 AX 想做的事情就是把 agent 当成容器来编排。你写一份 YAML描述你想要的 agent 拓扑、依赖关系、资源约束剩下的调度、生命周期管理、故障恢复交给运行时。这个思路在容器领域已经被验证了十几年现在被搬到 agent 编排上难怪有人兴奋有人质疑。适合谁来研究这个东西我认为有三类人值得花时间一是已经在做多 agent 系统、被调度和状态管理折磨过的后端工程师二是想理解agent 基础设施这个方向会往哪走的架构师三是单纯好奇声明式这套哲学能不能套到 AI 工作流上的技术爱好者。如果你只是想让一个 agent 帮你查天气那 AX 属于杀鸡用牛刀不用碰。我先把结论放前面AX 的价值不在于它现在有多好用而在于它把agent 编排这个问题从写代码调 API提升到了声明式描述期望状态的抽象层级。这个抽象层级的变化才是它值得被认真对待的原因。2. 为什么声明式这三个字是整件事的核心2.1 命令式编排的痛做过的人都懂在 AX 出现之前绝大多数 agent 框架都是命令式的。什么叫命令式就是你得一步步告诉程序该干什么先初始化这个 agent再调用那个工具然后判断返回值如果失败就重试重试三次还失败就降级……这套逻辑写起来直观但一旦 agent 数量上去、依赖关系变复杂代码就会变成一团意大利面。我踩过最典型的坑是状态管理。一个 agent 执行到一半挂了它之前产生的中间状态怎么办重试的时候是从头来还是从断点续如果这个 agent 依赖上游三个 agent 的输出而上游其中一个失败了整条链路怎么处理命令式代码里这些逻辑全得你自己写写到最后你会发现你其实在重新实现一个蹩脚的调度器。声明式的思路完全反过来。你不描述怎么做你描述我要什么。你写一份 YAML 说我要一个由 A、B、C 三个 agent 组成的流水线A 的输出喂给 BB 和 C 并行最后汇总。运行时拿到这份描述自己去算怎么调度、怎么重试、怎么恢复。这就像你告诉 Kubernetes我要三个副本的 nginx而不是自己写脚本去docker run三次再写个监控脚本盯着。2.2 声明式带来的三个实际好处第一个好处是幂等性。声明式描述的是期望状态运行时的工作就是不断把实际状态往期望状态上靠。这意味着你重复提交同一份 YAML结果是一样的不会因为重复执行产生副作用。这在 agent 场景里特别重要因为 agent 经常需要重试幂等性能保证重试是安全的。第二个好处是可观测性天然内建。因为运行时知道你的期望状态是什么它就能告诉你现在实际状态和期望状态差在哪。哪个 agent 没起来、哪个依赖没满足、哪个资源超了一目了然。命令式代码里这些信息散落在各个日志里排查起来要命。第三个好处是关注点分离。写 agent 逻辑的人只管写 agent 逻辑调度、扩缩容、故障恢复这些脏活交给运行时。团队里不同角色可以各司其职不用每个人都懂全套调度逻辑。提示声明式不是银弹。它的代价是抽象层变厚出问题时排查链路变长。你得接受我看不到运行时内部在干什么这件事除非它提供了足够的可观测性接口。2.3 为什么是 YAML 而不是别的热词里yaml文件yaml格式yolov10 yaml文件怎么创建这些搜索词扎堆出现说明很多人对 YAML 本身就有困惑。AX 选 YAML 作为描述语言我觉得是深思熟虑的。YAML 的可读性好非程序员也能看懂大概它天然支持嵌套结构适合描述 agent 之间的层级和依赖而且 Kubernetes 生态已经把 YAML 这套玩得很熟了大家有认知基础。但 YAML 的坑也不少。缩进敏感、类型推断诡异yes会被解析成布尔值这种经典坑、大文件难维护。AX 用 YAML 描述 agent 拓扑意味着你得接受这些坑。我的经验是写复杂 YAML 一定要配 schema 校验不然一个缩进错误能让你 debug 半天。3. AX 的核心概念拆解3.1 Agent 作为一等公民在 AX 的世界观里agent 是一个被运行时管理的实体就像 Pod 之于 Kubernetes。每个 agent 有自己的生命周期创建、运行、完成、失败、销毁。运行时负责在这些状态之间做转换并在异常时采取行动。这里有个关键设计agent 是无状态的至少运行时假设它是无状态的。agent 的状态存在外部运行时只负责调度。这个设计让水平扩展变得容易——想加 agent 就加不用考虑状态迁移。但代价是如果你的 agent 逻辑本身需要维护复杂状态你得自己想办法外置。3.2 编排图与依赖关系AX 用图来描述 agent 之间的关系。节点是 agent边是依赖。这个图可以是有向无环图DAG也可以有循环用于迭代场景。运行时根据这个图来决定执行顺序没有依赖的 agent 可以并行跑有依赖的必须等上游完成。我实测下来DAG 这种模型对大多数批处理式的 agent 流水线是够用的。但如果你要做那种agent 之间互相协商、动态决定下一步的场景DAG 就有点僵。AX 据说支持动态图但动态图的调度复杂度会指数级上升这块我还没深入验证。3.3 运行时与调度器运行时是 AX 的心脏。它要做的事情包括解析 YAML、构建执行图、分配资源、调度 agent、监控状态、处理失败、收集指标。这一套下来复杂度不比一个轻量级容器编排器低。调度策略是运行时最核心的部分。AX 默认的调度策略我理解是类似就绪即调度——只要一个 agent 的依赖都满足了就把它扔到可用的执行槽里。但实际生产环境里你可能需要更复杂的策略优先级调度、资源感知调度、亲和性调度等等。这些 AX 是否都支持得看具体版本。4. 从零理解 AX 的执行模型4.1 一次完整的执行流程假设你写了一份 YAML描述了一个三步流水线抓取数据、处理数据、生成报告。AX 拿到这份描述后大致会经历这么几个阶段。第一阶段是解析与校验。运行时读 YAML检查语法、校验 schema、确认引用的资源都存在。这一步失败的话直接报错不会进入执行。第二阶段是构建执行图。运行时把 YAML 里的声明转换成内部的图结构计算出哪些节点可以并行、哪些必须串行、关键路径是哪条。第三阶段是调度与执行。运行时按图调度 agent每个 agent 被分配到一个执行单元可能是线程、进程、容器取决于配置。执行过程中运行时持续监控状态。第四阶段是状态收敛。如果有 agent 失败运行时根据重试策略决定是重试、跳过还是终止整条流水线。如果一切顺利所有 agent 完成后运行时汇总结果。第五阶段是清理。释放资源收集指标把执行记录归档。4.2 状态是怎么被管理的这是我觉得 AX 最值得研究的部分。声明式系统的核心是状态收敛循环——运行时不断对比期望状态和实际状态然后采取行动消除差异。具体到 agent 场景期望状态可能是这三个 agent 都成功完成实际状态可能是agent A 完成agent B 运行中agent C 等待中。运行时看到这个差异就知道该去推进 B 和 C。如果 B 失败了实际状态变成B 失败运行时根据策略决定是重试 B 还是标记整条流水线失败。这个循环的难点在于并发控制。多个 agent 同时改变状态时怎么保证不冲突AX 应该用了类似乐观锁或者事件队列的机制但具体实现我没看到源码不好下结论。4.3 失败处理的设计哲学命令式代码里失败处理是显式写的 try-catch。声明式系统里失败处理是策略驱动的。你可以在 YAML 里声明这个 agent 失败了重试三次重试间隔指数退避如果三次都失败标记为致命错误终止整条流水线。这种策略驱动的失败处理好处是统一、可配置、不用每个 agent 都写一遍。坏处是灵活性受限遇到策略覆盖不到的特殊情况你还是得想办法绕。注意重试策略一定要配超时。我见过太多因为重试没有超时导致任务卡死、资源耗尽的案例。指数退避 最大重试次数 全局超时这三件套缺一不可。5. 手把手一份 AX YAML 该怎么写5.1 最小可用示例的结构虽然我没法给你一份官方文档级别的完整示例但基于声明式编排的通用模式一份 AX YAML 大概长这样顶层是版本和元信息然后是 agent 定义区每个 agent 有名字、镜像或执行入口、资源需求、依赖列表最后是编排策略区定义重试、超时、并发度这些。写这份 YAML 的时候我建议你从最小可用开始。先定义两个 agent一个依赖另一个跑通了再加复杂度。一上来就写几十个 agent 的拓扑出错了你根本不知道从哪查。5.2 关键字段的含义与取值agent 的name字段是唯一标识命名要有意义别用agent1agent2这种后期维护会疯。dependsOn字段声明依赖值是一个列表列出所有上游 agent 的名字。resources字段声明资源需求包括 CPU、内存可能还有 GPU。retryPolicy字段控制重试行为通常包含maxAttempts、backoff、timeout三个子字段。backoff可以是固定间隔也可以是指数退避。timeout是单次执行的超时不是总超时这点容易搞混。5.3 参数计算资源怎么估资源估算是个经验活。我的做法是先给一个宽松的值跑一遍用监控数据看实际峰值然后按峰值的 1.5 倍设限。CPU 密集型 agent 给 1-2 核内存密集型看数据量GPU 密集型按显存需求给。并发度这个参数要特别小心。并发度设太高资源争抢导致整体变慢设太低资源闲置。我的经验值是并发度设为可用执行槽的 70%-80%留点余量给系统本身和突发流量。参数建议取值说明CPU 请求峰值的 1.2 倍留 20% 余量内存请求峰值的 1.5 倍内存超了会 OOM余量给足并发度执行槽的 75%避免资源争抢单次超时正常耗时的 3 倍容忍偶发慢最大重试3 次再多说明是系统性问题5.4 一个容易忽略的细节命名空间如果你的 AX 集群是多租户的命名空间隔离一定要做。不同团队的 agent 放在不同命名空间避免互相干扰。命名空间还能用来做资源配额防止一个团队把整个集群吃满。这个设计是从 Kubernetes 抄来的实践证明有效。6. 跟 Kubernetes 到底像在哪、不像在哪6.1 像的地方控制循环与期望状态AX 和 Kubernetes 最像的地方是控制循环control loop这个模式。Kubernetes 的控制器不断对比期望状态和实际状态AX 的运行时也是。这个模式的好处是自愈能力强——不管中间出什么岔子只要期望状态不变系统最终会收敛过去。另一个像的地方是资源抽象。Kubernetes 抽象了计算、存储、网络AX 抽象了 agent 的执行单元、状态存储、消息传递。这种抽象让上层不用关心底层细节但也意味着底层出问题时上层很难直接干预。6.2 不像的地方agent 是有智能的容器是无状态的、确定性的——同样的输入同样的输出。agent 不是。agent 内部可能调用大模型同样的输入可能得到不同的输出。这给编排带来了新问题你怎么定义成功怎么判断一个 agent 的输出是对的Kubernetes 里容器退出码非零就是失败。AX 里agent 跑完了但输出质量差算成功还是失败这个问题没有标准答案得靠你在 agent 逻辑里自己定义成功标准然后通过某种方式反馈给运行时。6.3 借鉴与超越AX 明显借鉴了 Kubernetes 的很多设计但它也针对 agent 场景做了调整。比如对长时运行 agent 的支持、对动态拓扑的支持、对 agent 间通信的支持这些都是容器编排器不需要考虑的。我觉得 AX 能不能成关键看它能不能在借鉴 Kubernetes和针对 agent 特化之间找到平衡。太像 Kubernetes会水土不服太特化会失去通用性。7. 实际部署时会遇到的那些坑7.1 冷启动延迟agent 的冷启动比容器慢得多因为可能要加载模型、初始化上下文。如果你的流水线里有很多短时 agent冷启动延迟会累积成很大的开销。我的做法是保持一个 warm pool让常用 agent 常驻减少冷启动。7.2 状态存储的选择AX 需要外部状态存储来记录 agent 的执行状态。选什么存储很关键。Redis 快但持久性弱PostgreSQL 持久但慢etcd 适合小状态但不适合大吞吐。我的经验是执行状态用 Redis最终结果用对象存储审计日志用 PostgreSQL各司其职。7.3 可观测性的搭建声明式系统的可观测性比命令式更重要因为你不能靠读代码理解系统在干什么。指标、日志、追踪三件套都得配齐。指标看整体健康度日志查具体事件追踪看单次执行的完整链路。缺一个排查问题时都会抓瞎。7.4 版本兼容性AX 还在快速迭代版本之间的兼容性可能有问题。我的建议是锁定版本升级前先在测试环境跑一遍完整流水线确认没问题再上生产。别追新稳定压倒一切。8. 常见问题速查与排查思路8.1 agent 一直处于 Pending 状态这是最常见的问题。原因通常有三个依赖没满足、资源不够、调度器卡住。排查顺序是先看依赖的 agent 状态再看集群资源余量最后看调度器日志。如果是依赖问题等上游完成就行如果是资源问题要么加资源要么降需求如果是调度器问题重启调度器组件。8.2 agent 反复重启反复重启通常意味着 agent 逻辑本身有问题或者健康检查配置太严。先看 agent 日志确认是崩溃还是被健康检查杀掉。如果是崩溃修逻辑如果是健康检查放宽阈值。还有一种可能是资源限制太紧agent 被 OOM Killer 干掉这种情况要加内存。8.3 流水线整体卡住不动整条流水线卡住通常是某个关键 agent 卡住了导致下游全部等待。排查方法是找到那个运行中但长时间没进展的 agent看它的日志和资源使用。可能是死锁可能是外部依赖超时也可能是 agent 内部逻辑有 bug。现象可能原因排查动作Pending 不调度依赖未满足/资源不足查依赖状态、查资源余量反复重启逻辑崩溃/健康检查过严查日志、放宽阈值流水线卡住关键 agent 阻塞定位阻塞 agent、查其日志输出质量差agent 逻辑问题检查 prompt、检查模型资源耗尽并发度过高/内存泄漏降并发、查内存曲线8.4 输出不符合预期但没报错这是 agent 场景特有的问题。agent 跑完了退出码是 0但输出是垃圾。这种情况运行时帮不了你得在 agent 逻辑里加输出校验。我的做法是关键 agent 的输出必须过一遍校验器校验不过就当失败处理触发重试或告警。提示给 agent 定义明确的成功标准比什么都重要。没有成功标准声明式编排就失去了收敛的目标。9. 我对 AX 这类方案的一些个人判断折腾了这段时间我最大的体会是声明式编排 agent 这个方向是对的但 AX 现在还在很早期。它的概念模型清晰但工程实现上还有很多粗糙的地方。如果你现在就想上生产我建议再等等或者只在小范围非关键业务上试水。另一个体会是agent 编排的难点不在编排本身而在 agent 的不确定性。容器编排之所以成功是因为容器的行为是确定的。agent 的行为不确定这让所有基于期望状态的假设都变得脆弱。AX 能不能解决这个问题或者至少缓解这个问题是它能否走远的关键。最后分享一个我自己的用法我把 AX 当成一个agent 流水线的描述语言来用而不是一个完整的运行时。我用它来描述拓扑但执行还是走我自己的调度器。这样我既能享受声明式描述的好处又不用完全依赖 AX 的运行时。这个折中方案目前跑得还不错供你参考。