Google AX开源:声明式编排数十亿Agent的运行时解析
1. 从 HN 吵翻天的那个帖子说起AX 到底想解决什么问题前几天技术圈最热闹的事莫过于 Google 开源了一个叫 AX 的项目定位是声明式编排数十亿 agent 的运行时。帖子在 Hacker News 上挂了一整天评论区从架构设计吵到工程哲学从 Kubernetes 类比吵到 agent 到底该不该有编排层。我翻完了整栋楼发现吵得最凶的其实不是技术细节而是一个更根本的问题当 agent 的数量从几个变成几十亿个我们到底该怎么管它们这个问题听起来很夸张但如果你最近半年在折腾 agent 开发应该能感受到那种隐隐的焦虑。现在大家写 agent基本还是一个脚本一个 agent的路子——用 Python 起个进程挂个 LLM 调用加几个 tool跑起来就完事。几个、几十个 agent 这么搞没问题可一旦你要做的是每个用户配一个专属 agent每个设备跑一个本地 agent每个数据流触发一个处理 agent数量级瞬间就上去了。这时候你面对的就不是怎么写 agent的问题而是怎么调度、怎么编排、怎么保证它们不互相踩脚的问题。AX 想干的就是把这件事从手工作坊拉到工业化生产。它的核心思路非常 Kubernetes你用 YAML 声明你想要什么运行时负责把它变成现实。你不需要关心 agent 跑在哪台机器上、怎么扩容、挂了怎么重启你只需要描述我要一个能处理用户退款请求的 agent它需要访问订单数据库和支付网关剩下的交给 AX。这个类比一出来HN 上立刻分成两派。一派觉得终于有人把 K8s 那套成熟经验搬到 agent 领域了这是必然趋势另一派则质疑agent 不是无状态容器它有记忆、有上下文、有不确定的行为你拿编排容器的方式编排 agent是不是刻舟求剑这场争论其实非常有价值因为它逼着我们去想清楚agent 编排和传统服务编排到底哪里像、哪里不像我自己的判断是AX 的价值不在于它现在有多完善而在于它把agent 运行时这个概念正式推到了台面上。以前大家聊 agent聊的是 prompt 怎么写、tool 怎么接、memory 怎么存这些都是单个 agent 内部的事。AX 把视角拉高了一层开始聊agent 群体的事——调度、编排、生命周期管理、资源隔离。这个视角的切换才是它真正值得关注的地方。接下来的内容我会从几个角度把 AX 这件事拆开讲它到底怎么工作的、YAML 声明式编排在 agent 场景下意味着什么、和 Kubernetes 的类比哪些成立哪些不成立、实际落地时会踩哪些坑、以及如果你现在就想动手试该怎么起步。不管你是刚接触 agent 开发的新手还是已经在做多 agent 系统的老手应该都能从中找到对自己有用的东西。2. 声明式编排的内核你描述要什么运行时负责怎么做到2.1 命令式 vs 声明式一个生活化的类比要理解 AX 的设计哲学得先搞清楚声明式和命令式的区别。这两个词听起来很学术但其实生活里到处都是例子。命令式就像你给厨师写菜谱先热锅倒油油温七成热下葱姜蒜爆香后放肉丝翻炒三分钟加酱油再炒两分钟出锅。你每一步都要说清楚厨师照着做。如果中间哪个环节出了问题——比如火太大肉糊了——你得自己想办法补救。声明式则像你直接说我要一盘鱼香肉丝微辣不要胡萝卜。你只描述最终状态至于厨师怎么切、怎么炒、用哪个锅那是他的事。如果第一遍做咸了他会自己调整重做直到端出来的菜符合你的描述。AX 走的是后一条路。你写一个 YAML 文件描述我要一个 agent它的职责是处理退款它需要访问订单服务和支付服务它最多同时处理 100 个请求然后 AX 的运行时负责把这个描述变成实际运行的 agent 实例。如果某个实例挂了运行时自动拉起新的如果请求量涨了运行时自动扩容如果依赖的服务地址变了运行时自动重新配置。这种模式最大的好处是解耦。写 YAML 的人不需要知道底层跑在什么机器上、用什么容器运行时、网络怎么配。这些脏活累活全被运行时屏蔽掉了。对于 agent 这种本身就够复杂的东西来说少操一份心就是多一份生产力。2.2 AX 的 YAML 长什么样核心字段拆解虽然 AX 刚开源不久文档还在完善中但从它公开的示例和设计文档来看一个典型的 AX 配置文件大概包含这几个核心部分apiVersion: ax.io/v1 kind: Agent metadata: name: refund-handler namespace: customer-service spec: runtime: python3.11 entrypoint: agent.py replicas: 10 resources: cpu: 500m memory: 512Mi dependencies: - name: order-service type: http endpoint: http://order-svc:8080 - name: payment-gateway type: grpc endpoint: payment-svc:9090 scaling: minReplicas: 2 maxReplicas: 100 targetConcurrency: 50 memory: type: vector-store backend: local ttl: 3600这个文件里每一块都在回答一个问题metadata回答这个 agent 叫什么、属于哪个业务域runtime和entrypoint回答用什么跑、从哪开始跑replicas和scaling回答要几个实例、什么时候扩缩容resources回答给它多少 CPU 和内存dependencies回答它依赖哪些外部服务memory回答它的记忆存哪、存多久你看这里面没有一行是怎么启动进程怎么注册服务发现怎么配负载均衡——这些全是运行时的事。你只负责描述这个 agent 应该是什么样运行时负责让它变成那样。2.3 为什么 agent 特别需要声明式编排有人可能会问传统微服务早就有声明式编排了K8s 就是agent 有什么特别的特别之处在于agent 的行为是不确定的。一个普通的 HTTP 服务你给它同样的输入它大概率给你同样的输出。但 agent 不一样它背后是 LLM同样的输入可能因为温度参数、上下文长度、模型版本的不同而产生完全不同的行为。这种不确定性带来两个后果第一你不能用固定的健康检查来判断 agent 是否正常。一个 HTTP 服务返回 200 就是健康但一个 agent 返回了结果你怎麼知道它返回的是对的它可能一本正经地胡说八道。所以 AX 这类运行时需要更复杂的健康评估机制比如基于输出质量的评分、基于用户反馈的闭环。第二agent 的状态更难管理。传统服务可以设计成无状态的但 agent 天然有记忆——它记得之前跟用户聊过什么、做过什么决策。这些记忆存在哪、怎么同步、怎么在实例之间迁移都是传统编排没遇到过的问题。AX 在 YAML 里专门有个memory字段就是在回应这个需求。所以 AX 不是简单地把 K8s 那套照搬过来它是在 K8s 的基础上针对 agent 的特性做了扩展。这个扩展做得好不好直接决定了它能不能真正支撑数十亿 agent这个量级。3. 和 Kubernetes 的类比哪些成立哪些是刻舟求剑3.1 成立的部分调度、扩缩容、服务发现HN 上吵得最凶的就是这个类比。我的看法是在基础设施层面类比完全成立在行为层面类比会误导人。先说成立的部分。AX 从 K8s 继承的最核心能力有三个调度。数十亿 agent 不可能都跑在一台机器上必然要分散到成千上万台机器。哪个 agent 跑在哪、怎么平衡负载、怎么处理故障转移这些是 K8s 已经解决了十几年的问题。AX 直接复用这套调度逻辑是最务实的选择。你不需要重新发明轮子只需要把容器换成agent 实例。扩缩容。agent 的负载波动可能比传统服务还大。比如一个电商客服 agent平时可能只有几十个并发大促期间瞬间涨到几万。AX 的scaling字段就是干这个的你设一个目标并发数运行时根据实际负载自动调整实例数量。这比手动扩容靠谱得多也比预留大量闲置资源省钱。服务发现。agent 之间需要互相调用——退款 agent 可能要调用风控 agent风控 agent 可能要调用用户画像 agent。这些 agent 的地址是动态的今天在这台机器明天可能就漂到另一台。AX 自动维护服务注册表agent 之间通过名字互相访问不需要硬编码 IP。这三块是 AX 和 K8s 最像的地方也是它最稳的地方。因为这些问题的本质是分布式系统的基础设施问题跟上面跑的是容器还是 agent 没关系。3.2 不成立的部分agent 不是无状态容器但一到行为层面类比就开始出问题了。问题一agent 有记忆容器没有。一个容器重启状态全丢这是特性不是 bug。但一个 agent 重启如果记忆丢了用户会疯掉——我刚才跟你说的地址你怎么又忘了所以 AX 必须解决记忆的持久化和迁移问题。它 YAML 里的memory字段支持vector-store类型说明它至少考虑到了向量记忆的存储。但记忆的同步、版本管理、跨实例共享这些远比存储复杂。问题二agent 的行为不可预测容器的是可预测的。你给一个 Nginx 容器发 100 个请求它处理 100 个请求。你给一个 agent 发 100 个请求它可能处理 80 个就卡住了因为第 81 个请求触发了某个它没见过的场景它在那里反复思考。这种卡住不是崩溃进程还在端口还通但就是不干活了。传统的健康检查发现不了这种问题你需要更智能的监控——比如检测输出延迟、检测 token 消耗速率、检测是否陷入循环。问题三agent 的副本不是完全等价的。在 K8s 里10 个 Nginx 副本是完全一样的请求发给谁都行。但 agent 不一样如果每个 agent 有自己的记忆和上下文那副本 A 和副本 B 就是两个不同的人。你把用户的请求随机发给 A 或 B用户体验会非常割裂——A 记得他昨天说过什么B 不记得。所以 AX 需要更复杂的路由策略比如基于用户 ID 做一致性哈希保证同一个用户总是打到同一个 agent 实例。这三个问题是 AX 这类 agent 运行时必须面对、但 K8s 没有现成答案的。HN 上那些质疑刻舟求剑的人担心的就是这些。我觉得这个担心是合理的但结论下得太早——AX 才刚开源它有没有解决好这些问题得看后续的迭代。3.3 一个关键差异agent 的启动成本高得多还有一个容易被忽略的差异启动一个容器可能只要几百毫秒启动一个 agent 可能要几秒甚至几十秒。为什么因为 agent 启动时通常要做这些事加载模型如果是本地模型、初始化向量数据库连接、拉取最新的 prompt 模板、预热缓存。这些操作加起来冷启动时间轻松超过 5 秒。在数十亿 agent 的场景下如果每次扩缩容都要等这么久系统的响应速度会非常糟糕。所以 AX 必须支持热池机制——预先启动一批待命的 agent 实例需要时直接分配而不是从零启动。这跟 K8s 的预热 Pod思路类似但 agent 的预热更复杂因为你还得考虑每个 agent 的个性化配置比如不同用户可能有不同的 prompt 模板。这个差异也解释了为什么 AX 强调声明式——如果每次都要手动配置 agent 的启动参数热池根本没法管理。只有声明式地描述我要 100 个退款 agent 待命运行时才能自动维护这个池子。4. 数十亿 agent 的调度难题AX 的架构猜想与工程现实4.1 数十亿是什么概念先算一笔账数十亿 agent这个说法听起来很唬人但咱们得算算账看看它到底意味着什么。假设你有 10 亿个 agent每个 agent 平均占用 100MB 内存这已经是很乐观的估计了LLM 相关的 agent 通常远不止这个数。那么总内存需求是 10 亿 × 100MB 100PB。100PB 内存是什么概念目前全球最大的超级计算机之一内存总量也就几十 PB 级别。也就是说你不可能同时运行 10 亿个 agent。那 AX 说的编排数十亿 agent是什么意思我理解它指的是管理数十亿个 agent 的定义和生命周期而不是同时运行数十亿个实例。就像 K8s 可以管理数百万个 Deployment 定义但同一时刻运行的 Pod 数量远小于这个数。大部分 agent 定义是休眠的只有在需要时才被激活。这个理解很重要因为它决定了 AX 的架构重点不是怎么同时跑 10 亿个 agent而是怎么高效地管理 10 亿个 agent 定义并在需要时快速激活其中的一小部分。4.2 冷热分离AX 最可能的架构选择基于上面的分析AX 的架构大概率是冷热分离的冷层存储所有 agent 的定义YAML 文件、配置、记忆快照。这一层可以用对象存储或分布式数据库成本低、容量大。10 亿个 YAML 文件每个平均 10KB总共也就 10TB完全存得下。热层运行当前活跃的 agent 实例。这一层的规模取决于实际并发需求可能只有几万到几百万个实例。热层的资源是昂贵的CPU、内存、GPU所以需要精细的调度和快速的扩缩容。温层是介于两者之间的待命池。这些 agent 已经加载了基本配置但还没绑定具体用户或任务。当请求来时从温层直接分配省去冷启动时间。这个三层架构的关键挑战是状态迁移当一个 agent 从冷层被激活到热层时它的记忆、上下文、配置怎么快速加载当一个 agent 从热层被释放回冷层时它的状态怎么持久化这些迁移操作如果太慢整个系统的响应就会卡顿。AX 的 YAML 里那个memory字段很可能就是为这个设计的。type: vector-store说明记忆是以向量形式存储的backend: local说明可以存在本地ttl: 3600说明有生存时间。这些参数组合起来就是在控制记忆的加载和释放策略。4.3 调度器的核心挑战不只是找台机器放进去传统 K8s 调度器的任务是找一个满足资源需求的节点把 Pod 放上去。AX 的调度器要复杂得多因为它要考虑的维度更多维度一记忆亲和性。如果一个 agent 的记忆存在节点 A 的本地存储上那下次调度这个 agent 时最好还调度到节点 A否则就要跨网络传输记忆慢且贵。这跟 K8s 的本地卷亲和性类似但 agent 的记忆可能更大、更频繁地变化。维度二模型亲和性。如果多个 agent 共用同一个本地模型那把它们调度到同一台机器上可以共享模型的内存占用。这需要调度器知道哪些 agent 用哪个模型并做打包优化。维度三用户亲和性。前面说过同一个用户的请求最好打到同一个 agent 实例。这要求调度器在做路由时考虑用户 ID而不是简单地轮询。维度四成本亲和性。不同节点的成本不一样比如 GPU 节点比 CPU 节点贵得多。调度器需要在满足性能要求的前提下尽量把 agent 放到便宜的节点上。这四个维度叠加起来调度问题就从二维装箱变成了多维装箱复杂度指数级上升。AX 能不能解决好这个问题是它能不能支撑数十亿这个量级的关键。4.4 工程现实先别想数十亿想想一万个怎么管虽然 AX 的愿景是数十亿但我觉得对绝大多数团队来说更现实的问题是怎么管好一万个 agent一万个 agent 已经足够让手工管理崩溃了。你不可能手动记录每个 agent 跑在哪、什么配置、什么状态。你需要一个系统来自动化这些。AX 提供的声明式接口至少让你可以用 Git 来管理 agent 定义——每个 agent 一个 YAML 文件提交到代码仓库CI/CD 流水线自动部署。这个工作流跟管理 K8s 配置是一样的成熟且可靠。所以我的建议是别被数十亿吓到先从一百个开始用 AX 的思路管理你的 agent。当你发现手工管理一百个 agent 已经力不从心时AX 这类工具的价值就体现出来了。至于数十亿那是 Google 该操心的事不是你我该操心的。5. 落地实操从零开始用声明式思路管理你的 agent5.1 环境准备你不需要真的装 AXAX 刚开源文档不全直接上手可能会踩很多坑。但好消息是你可以用 K8s 加一些自定义资源来模拟 AX 的核心思路。这样你既能学到声明式编排的精髓又不用等 AX 成熟。我的建议是如果你已经有 K8s 环境直接用它如果没有用kind或minikube起一个本地集群就行。然后你需要装一个能跑 agent 的容器镜像——最简单的做法是写一个 Python 脚本里面调用 LLM API把它打包成 Docker 镜像。FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY agent.py . CMD [python, agent.py]agent.py里就是一个简单的循环从环境变量读取任务调用 LLM输出结果。这个 agent 本身很简单重点不在于它多智能而在于它怎么被编排。5.2 用 K8s 自定义资源模拟 AX 的 Agent 定义K8s 允许你定义自定义资源CRD。我们可以定义一个Agent资源字段跟 AX 的 YAML 类似apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: agents.example.com spec: group: example.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: replicas: type: integer memoryTTL: type: integer dependencies: type: array items: type: string scope: Namespaced names: plural: agents singular: agent kind: Agent然后你就可以像这样定义一个 agentapiVersion: example.com/v1 kind: Agent metadata: name: refund-handler spec: replicas: 5 memoryTTL: 3600 dependencies: - order-service - payment-gateway这个 YAML 本身不会做任何事你需要写一个控制器Controller来监听Agent资源的创建和更新然后相应地创建 Deployment 和 Service。这个控制器就是运行时的核心。5.3 写一个最简控制器把声明变成现实控制器用 Python 的kopf框架写起来最方便。核心逻辑就是监听到Agent资源变化时创建或更新对应的 Deployment。import kopf import kubernetes kopf.on.create(example.com, v1, agents) def create_agent(spec, name, namespace, **kwargs): apps_v1 kubernetes.client.AppsV1Api() deployment kubernetes.client.V1Deployment( metadatakubernetes.client.V1ObjectMeta(namef{name}-deploy), speckubernetes.client.V1DeploymentSpec( replicasspec.get(replicas, 1), selector{matchLabels: {app: name}}, templatekubernetes.client.V1PodTemplateSpec( metadatakubernetes.client.V1ObjectMeta(labels{app: name}), speckubernetes.client.V1PodSpec( containers[kubernetes.client.V1Container( nameagent, imagemy-agent:latest, env[ kubernetes.client.V1EnvVar(nameMEMORY_TTL, valuestr(spec.get(memoryTTL, 3600))), kubernetes.client.V1EnvVar(nameDEPENDENCIES, value,.join(spec.get(dependencies, []))) ] )] ) ) ) ) apps_v1.create_namespaced_deployment(namespacenamespace, bodydeployment)这段代码虽然简单但它完整地演示了声明式编排的核心循环监听声明 → 对比现状 → 执行变更。AX 内部做的事情本质上跟这个一样只是它处理的问题更复杂、优化的维度更多。5.4 实测中的坑我踩过的三个雷我在用这套思路管理 agent 时踩过几个坑分享出来帮你省时间坑一agent 的启动时间远超预期。我一开始设的initialDelaySeconds是 5 秒结果 agent 因为要加载向量数据库实际启动要 20 秒。K8s 以为它挂了反复重启陷入死循环。后来我把initialDelaySeconds调到 30 秒并加了startupProbe专门处理启动阶段才稳定下来。坑二记忆的持久化没做好重启就丢。我一开始把 agent 的记忆存在容器本地文件系统里结果容器一重启记忆全没了。后来改成挂载 PersistentVolume但又有新问题——多个副本同时读写同一个卷会冲突。最后的方案是每个副本用自己的卷然后用一个后台任务定期把记忆同步到中心存储。坑三扩缩容指标选错了。我一开始用 CPU 使用率作为扩缩容指标结果发现 agent 大部分时间在等 LLM API 返回CPU 使用率很低但实际并发已经很高了。后来改成用正在处理中的请求数作为指标扩缩容才准确。这三个坑的共同点是传统服务的经验不能直接套用到 agent 上。agent 的启动、状态、负载特征都跟普通服务不一样你需要重新思考每一个配置项。6. 争议背后agent 运行时该由谁定义6.1 HN 争论的焦点抽象层级对不对回到 HN 那场争论我觉得最有价值的一条评论是AX 把抽象层级提得太高了高到它假设了太多关于 agent 应该怎么工作的前提。这句话点到了要害。AX 的 YAML 里replicas、scaling、dependencies这些字段都隐含了一个假设agent 是可以被水平扩展的、无状态的、通过标准接口通信的。但现实中的 agent 可能完全不是这样——它可能是有状态的、不能简单复制的、通过自然语言而不是 HTTP 通信的。如果 AX 强行把 agent 塞进 K8s 的抽象模型里那它可能只适合某一类 agent比如工具调用型的、无状态的而不适合另一类比如有长期记忆的、个性化的。这个局限性是 HN 上很多人担心的。但换个角度想任何抽象都有适用范围。K8s 也不是万能的它适合无状态微服务不适合数据库这类有状态服务所以才有 StatefulSet。AX 可能也会演化出不同的agent 类型对应不同的编排策略。现在下结论说它抽象错了或抽象对了都太早。6.2 我的判断AX 的真正价值在定义问题而非解决问题说实话AX 现在这个版本离能编排数十亿 agent还差得远。它的文档不全、生态没起来、实际案例几乎没有。如果你现在就想用它上生产大概率会失望。但我觉得它的价值不在于它现在能做什么而在于它把agent 运行时这个问题正式提出来了。在 AX 之前大家聊 agent 都是在聊单个 agent 怎么写得更好AX 之后大家开始聊一群 agent 怎么管得更好。这个视角的切换会催生一批新的工具、新的模式、新的最佳实践。就像当年 Docker 刚出来时也没人觉得它能改变世界。但它把应用打包这个问题定义清楚了后面的 K8s、Istio、Prometheus 才有机会在此基础上生长。AX 可能也在扮演类似的角色——它不一定笑到最后但它定义的这个赛道会有人跑出来。6.3 给不同阶段团队的建议最后给不同阶段的团队一些实在的建议如果你还在写第一个 agent别碰 AX也别碰 K8s。用一个 Python 脚本把 agent 跑起来把业务逻辑跑通比什么都重要。这个阶段你的核心问题是agent 能不能用不是agent 怎么管。如果你已经有几十个 agent 在跑开始感到管理吃力了可以看看 AX 的设计思路但不一定要用它的代码。你可以先用 Git 管理 agent 配置用 CI/CD 自动部署用简单的脚本做健康检查。这些土办法在几十个 agent 的规模下完全够用。如果你已经有几百上千个 agent那 AX 这类工具就值得认真评估了。但评估的重点不是它能不能跑而是它的抽象模型跟你的 agent 匹不匹配。如果你的 agent 是无状态的、可水平扩展的那 AX 的思路很适合你如果你的 agent 是有状态的、个性化的那你可能需要等它演化出更合适的模式或者自己基于 K8s 做定制。如果你在做 agent 平台那 AX 的源码值得细读。它怎么设计调度器、怎么管理记忆、怎么做扩缩容这些决策背后的权衡对你自己做平台很有参考价值。哪怕你最后不用它的代码它的架构思路也能帮你少走弯路。我在实际折腾 agent 编排的这段时间最大的体会是别被数十亿这种数字迷惑先解决你眼前那一百个 agent 的管理问题。大部分团队一辈子也到不了数十亿的规模但一百个 agent 的管理痛点是实实在在的。AX 提供的声明式思路哪怕你只用它来管理十个 agent也能让你的工作流清晰很多。至于它能不能真的支撑数十亿那是 Google 的工程能力问题不是我们该操心的。我们该操心的是怎么用它的思路把自己手头那摊事管得更明白。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →