编码智能体上云:用Azure KARS在AKS上构建多运行时AI基础设施 上周有朋友问我你们的编码智能体现在到底是在IDE里聊天还是真的能自己干活我愣了一下因为这个问题问到了点子上。过去一年我关注的重点已经从这个智能体能不能写代码慢慢转移到了这个智能体跑起来之后我拿什么接住它。所谓接住就是基础设施问题。最近我一直在折腾Azure KARS目标很明确把编码智能体从代码仓库旁边那个聊天框里解放出来放到一个真正的多运行时AI智能体基础设施上运行。如果你也在做AI智能体落地有三个问题绕不开它跑在哪它怎么接入业务流程它出问题时你怎么复盘这篇文章就想把这套思路讲透。我会从编码智能体为什么会离开代码库这个现象出发拆解多运行时场景对基础设施的需求再详细讲我在AKS上使用Azure KARS搭建、调试、故障演练的全过程最后分享一些只有实际动手才会踩到的坑。适合正在做智能体平台化、或者想把LLM从聊天工具变成执行者的工程师参考。1. 编码智能体怎么就从IDE里跑到了集群上1.1 从生成代码到执行任务大多数人对编码智能体的印象还停留在在IDE里帮你补全代码或者在聊天窗口里生成一段函数。但2026年这个时间点上编码智能体的形态已经变了。基于ReAct模式构建的智能体不再是简单的问题-答案循环而是推理、行动、观察交替进行它读代码、发现bug、运行测试、修改文件、再验证结果甚至在失败后自己调整策略重试。与此同时多模态大模型的进展让智能体的感知范围也大幅扩大。它不再只吃文本输入还能看界面截图、分析崩溃堆栈、读监控图表。这意味着编码智能体真正开始接触真实世界——而真实世界不在IDE里在环境里。当智能体具备了行动能力之后它就不再是坐在开发者身边出主意的辅助工具而是分布在运行时环境中的执行者。它会进容器、跑流水线、调用云资源、操作Kubernetes集群。我见过不少团队已经在让编码智能体自动修复CI失败、自动升级依赖、自动处理安全告警。这个趋势非常明显编码智能体正在离开代码库。1.2 离开代码库之后智能体要面对的三个新问题一旦智能体离开代码库很多原来不存在的麻烦就冒出来了。我归纳下来有三个问题最核心。第一是身份问题。智能体到底以什么身份在环境里活动是模拟某个开发者的个人账号还是用一个独立的服务账号它推送代码、创建PR、关闭Issue时审计记录里留下的是谁的痕迹这个不搞清楚后面所有运维动作都没法开展。第二是范围问题。一个能执行代码的智能体它能够影响的范围到底有多大它跑一条命令最坏情况下会造成什么后果是删掉一个临时缓存文件还是把整个生产集群搞挂我在自己项目里看到过智能体因为指令理解偏差差点把某个namespace下的资源全部清掉。权限边界如果不提前划定智能体的能力越强风险越大。第三是生命周期与可观测性。这个智能体现在在哪个容器里运行它的状态是健康的还是已经卡死了它执行的每一个步骤有没有日志可以回放任务失败了我是能完整重放它的思路轨迹还是只能看到一个莫名其妙的ERROR这三个问题本质上都是基础设施问题。它们决定了智能体能不能从演示走到规模化生产。网络上有大量讨论AI智能体应用案例的文章但很少有人把案例背后那层运行时讲清楚。这也是我写这篇文章的原因。2. 多运行时场景下基础设施到底要解决什么问题2.1 多运行时到底包含哪几类环境多运行时这个词听着玄实际上就是一个智能体逻辑要在多个不同的物理执行环境里跑。我整理了一下至少包含这几类本地开发机开发者在自己的环境里调试智能体行为CI/CD流水线比如GitHub Actions、Jenkins里自动执行修复任务Kubernetes集群比如AKS上长期运行的智能体服务Serverless函数和SaaS API作为轻量事件处理入口边缘节点或嵌入式设备离数据源更近的位置同一个编码智能体在不同运行时里扮演的角色可以完全不同。在CI里它是自动修构建的小工在集群里它是长驻的审查员在事件处理入口它又是分类和路由的前哨。多运行时的本质是同一套智能体逻辑需要适配不同场景的部署形态最好还能被同一个控制面管起来。2.2 基础设施要回答的六个问题我在设计这套基础设施时往后退了一步先不聊具体工具而是列了六个必须回答的问题声明我如何用一段配置描述这个智能体想干什么需要什么镜像起几个副本调度任务来了之后谁决定把它分发到哪个运行时触发外部世界怎么把一个工作任务递给智能体Webhook消息队列定时任务生命周期我怎么判断一个LLM进程是活着、卡住了、还是已经凉了可观测智能体每一步动作都能审计吗任务失败能不能重放治理它能不能访问不该访问的东西权限怎么隔离出了问题怎么快速回滚这六个问题列完你会发现它们和传统的后端服务治理高度重合。过去十年我们在微服务领域踩过的坑在智能体时代一个都不会少只是换了一层皮。2.3 为什么Kubernetes是绕不开的底座有人会问为什么不用自己写的任务系统或者直接用Serverless我的答案很简单因为Kubernetes已经解决了我最不想重复造轮子的那部分问题。容器封装带来了可复现的运行时环境智能体的依赖、模型、工具链都能打成镜像Deployment天然支持多副本管理Service解决了流量路由Probe机制提供了健康检查RBAC和NetworkPolicy提供了权限边界HPA和KEDA这类生态组件解决了弹性伸缩。这些是智能体基础设施的核心原语。如果从零开始搭一套自研系统等于把这些年Kubernetes生态沉淀的可靠性工程能力全部放弃。Azure KARS之所以打动我恰恰是因为它没有尝试替代Kubernetes而是把Agent当作一种新的CRD放进这个体系里用声明式的方式管理智能体。3. 认识Azure KARS一个长在Kubernetes上的智能体编排Operator3.1 KARS是什么又不是什么Azure KARS全称Kubernetes Automatic Reasoning Service。说白了它是一个运行在AKS上的Operator通过CRD把Agent变成Kubernetes里的一等公民。它不是什么新运行时也不是一个把PaaS平台搬到集群里的东西更不是模型托管服务。KARS做的事情是你定义一个Agent资源它负责把Pod、Service、健康检查、触发器这些底层细节编排起来让智能体像普通工作负载一样被调度和管理。用Kubernetes的行话来说KARS就是把智能体语义翻译成Kubernetes原语的一层适配器。它站在Kubernetes的肩膀上把LLM智能体这匹野马套上了平时我们熟悉的缰绳。3.2 Agent资源的骨架拆解KARS的核心API是一个叫Agent的资源。下面这份YAML是我实际用过的结构经过脱敏和简化apiVersion: agents.azure.com/v1alpha2 kind: Agent metadata: name: codefix-agent namespace: agents spec: pod: containers: - name: codefix image: registry.example.com/agents/codefix:2026.02 args: [--mode, multi-runtime] env: - name: GITHUB_TOKEN valueFrom: secretKeyRef: name: repo-token key: token resources: requests: cpu: 1 memory: 2Gi limits: cpu: 2 memory: 4Gi replicas: 2 sociable: true triggers: - type: http path: /messages - type: queue queueRef: codefix-queue先强调一句KARS的API在预览阶段迭代非常快我在写这篇文章时使用的是v1alpha2你部署的时候一定要用kubectl explain agent查看当前集群里实际支持的字段不要照抄。这个骨架里最关键的是三块。spec.pod定义智能体跑在什么环境下本质是PodSpec的扩展容器镜像就是智能体的全部依赖做到了环境完全可复现。replicas控制实例数意味着同一个智能体可以水平扩展这在多运行时场景下特别重要——同一个Agent逻辑既可以在集群里干活也可以在其他运行时被调用。sociable是个很有意思的开关它决定这个Agent愿不愿意接收外部消息相当于定义了智能体是主动干活还是被动响应。3.3 消息、触发器与sociable行为编码智能体不可能靠人工kubectl exec进去敲命令来驱动。它得能接活儿。KARS里任务驱动主要靠两种方式HTTP入口和消息队列。HTTP触发比较简单外部系统可以通过Webhook直接POST一个任务过来Agent收到消息后开始处理。这种方式适合交互式的短任务比如GitHub上有人提了一个IssueWebhook把Issue内容推过来Agent分析后回一条评论。队列触发则更适合异步长任务。把消息丢进队列之后Agent从队列里消费任务处理完再把结果写到某个存储里。这种方式的好处是削峰填谷任务积压也不会打爆Agent本身。sociable这个属性控制的就是这一切的外部输入是否被接受。如果设为falseAgent就是一个纯粹的无状态计算单元只在被显式调用时工作如果设为true它就主动接收外部世界的消息并做出响应。这个开关实际上决定了一个智能体在基础设施层的社交能力。3.4 Kubernetes心智模型的自然延伸对于熟悉Kubernetes的同学KARS的学习成本极低。它没有发明一套全新的概念体系而是把像管理Deployment一样管理Agent这个心智模型贯彻到底。你在Deployment里定义Pod模板、副本数、探针在KARS里定义Agent的容器镜像、副本数和健康检查你在Service里定义流量怎么进在KARS里定义trigger怎么绑定。唯一多出来的部分是智能体语义——比如sociable这个属性、任务消息的格式、LLM特有的健康判断。这种设计最直接的好处是团队里已有的Kubernetes经验和工具链可以直接复用。监控、日志、命名空间隔离、资源配额全都是熟悉的那一套。这比引入一个完全独立的智能体平台运维成本低太多。4. 在AKS上跑通第一个编码智能体从零到能干活4.1 准备一个能跑的AKS集群实操部分从AKS集群开始。如果你手头还没有集群下面这套命令可以直接用az group create --name kars-rg --location eastasia az aks create \ --resource-group kars-rg \ --name kars-cluster \ --node-count 3 \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 8 az aks get-credentials --resource-group kars-rg --name kars-cluster --overwrite-existing kubectl get nodes我强烈建议你开启cluster autoscaler。智能体的任务往往是突发型的——一个仓库突然出现了10个并发Issue消息瞬间涌进来Pod数开始增长如果集群没有弹性任务就只能排队等着。另外节点数不用多3个起步就够了后面按实际情况调整。如果你已经有集群在跑那就省掉创建这一步直接检查Kubernetes版本是否满足KARS的要求然后进入下一步安装。4.2 安装KARS并验证CRDKARS的安装方式在持续变化中我装的时候是通过Azure的扩展机制做的。装完之后第一件事就是看CRD有没有注册成功kubectl get crd | grep agents.azure.com如果能看到一个叫agents.azure.com的CRD存在说明Operator已经就绪。这时候再用kubectl explain agent看一眼字段结构确认API版本和字段名和你手上的文档一致。这一步非常关键。预览阶段的项目经常出现文档还没更新、集群里已经换了新版API的情况。我后来就吃过这个亏——照着旧版本文档写的YAMLapply之后发现字段名已经变了。4.3 一份Agent清单的详细写法现在我创建一个最小编码智能体的Agent资源。假设这个Agent的职责是收到GitHub任务后克隆代码库、跑测试、如果发现失败就自动生成修复补丁并提起PR。apiVersion: agents.azure.com/v1alpha2 kind: Agent metadata: name: codefix-agent namespace: agents spec: pod: containers: - name: codefix image: registry.example.com/agents/codefix:2026.02 env: - name: GITHUB_TOKEN valueFrom: secretKeyRef: name: repo-token key: token - name: MODEL_ENDPOINT value: https://api.example.com/v1 resources: requests: cpu: 1 memory: 2Gi limits: cpu: 2 memory: 4Gi replicas: 1 sociable: true triggers: - type: queue queueRef: codefix-job-queue创建它kubectl create namespace agents kubectl create secret generic repo-token --from-literaltokenghp_xxxx -n agents kubectl apply -f codefix-agent.yaml然后是重点查看Agent状态。kubectl get agent codefix-agent -n agents -o yaml kubectl get pods -n agents -l agents.azure.com/namecodefix-agent我强调一下resources字段的重要性。LLM推理进程如果不设置内存上限在Kubernetes里很容易出现间歇性的OOMKilled。这种问题极其隐蔽——进程不是一上来就死而是在处理某个特别长的上下文时内存突增啪一下被杀了排查起来非常让人抓狂。所以从一开始就设置好requests和limits能省掉后面一大半痛苦。4.4 从代码仓库到智能体的工作流Agent跑起来了现在要让它真正接活。工作流是这样的GitHub或GitLab产生事件通过Webhook发给一个中转服务中转服务把任务封装成消息丢进队列Agent从队列里消费并执行。我用的是Azure Service Bus。创建完队列之后在Agent的触发配置里指定队列引用即可。如果你更习惯HTTP直达也可以在trigger里加一个HTTP入口外部直接POST任务消息。接着给Agent暴露访问入口。这一步就是标准的Kubernetes玩法kubectl expose agent codefix-agent \ --name codefix-svc \ --port 80 \ --target-port 8080 \ -n agents如果你需要域名访问再配一个Ingress。建议用nginx ingress controller或者AGICTLS证书直接挂在Ingress上后面所有外部系统的Webhook统一打到这个域名。全部配置完成后最简单的一次验证是手动往队列里丢一条测试消息然后观察Pod日志kubectl logs -f -n agents -l agents.azure.com/namecodefix-agent如果日志里出现了智能体开始处理任务的痕迹说明从事件源到智能体的完整链路已经打通。这一步完成后你的编码智能体才算是真正离开代码库了。5. 从演示到生产多运行时环境里的可靠性、权限与容错设计5.1 存活与就绪检查别用TCP探活LLMdemo跑通只是开始生产环境才是分水岭。第一个要解决的是健康检查问题。传统服务做健康检查TCP连得上就认为活着。但对LLM智能体来说这个判断完全不够模型推理进程通常不会崩它是卡住——长时间没有输出、上下文越积越长、单次推理耗时飙升到分钟级。这些情况TCP检查根本测不出来因为进程其实是活着的。正确做法是用自定义的HTTP探针。在Agent容器里暴露一个/healthz端点让它返回三件事最近一次LLM调用是否成功、当前任务队列深度、是否需要重启。然后把这个探针接到KARS的readiness和liveness配置里。在智能体场景里我更看重readiness而不是liveness。liveness判断的是要不要杀掉重启readiness判断的是要不要继续把流量发给你。LLM推理慢的时候应该先把实例从负载均衡里摘掉让它把当前任务处理完而不是马上杀掉。假设一个实例正在生成一个复杂补丁你把它kill了这个补丁就丢了任务还得从头来。5.2 让LLM智能体具备自主容错能力这个部分我想聊深一点因为这可能是LLM智能体自主容错控制的真正价值所在。LLM和传统程序最大的区别是它的输出天然具有不确定性。同一个任务跑三次可能第一次成功后两次失败。如果你用传统程序的一次成功标准去要求它整个系统会极不稳定。我的做法是三个原则。第一任务可重入。Agent处理任务时的中间状态不能只存在本地内存里必须外置到Redis、SQL或者云数据库。这样即使Pod重启新实例能接着未完成的状态继续处理。第二操作幂等。Agent产生的每个动作执行两次的结果应该和执行一次相同。比如更新依赖这个操作跑两次不会造成双重修改创建PR这个动作如果PR已经存在第二次应该跳过而不是新建一个重复的PR。没有幂等性一次失败重试就可能造成数据混乱。第三有上限的重试策略。一个任务最多允许失败几次、每次重试之间隔多久、什么时候放弃这个任务改走人工通道。LLM智能体偶尔会陷入同一个错误策略反复尝试的循环如果没有上限它会在那里空转到天荒地老。在KARS环境下我把这些能力都放进了Agent的启动脚本里启动时先检查有没有未完成任务有则优先恢复完成后再去消费新任务。K8s保证的是进程级容错——Pod挂了自动拉起Agent自己保证的是任务级容错——任务断了能恢复。两层缺一不可。5.3 权限收口给智能体单独一个服务账号编码智能体能执行代码这个能力本身就是一颗核弹。权限必须严格收口这是我从头到尾最坚持的原则。首先给智能体建独立服务账号绝不允许用集群管理员凭据跑Agent。在Kubernetes里给这个SA配置RBAC只允许它访问自己namespace下的资源和必要的ConfigMap、Secret。我只给过我的Agent访问指定Secret的权限连其他namespace只读权限都没开。然后是云资源层面的权限。如果你的Agent需要操作Azure资源别把AKS的kubelet身份或者管理员身份塞给它用Workload Identity把Agent绑定到一个专门的Azure AD应用上给这个应用分配最小权限。我的Agent只需要往队列发消息和读对象存储我就只给了这两项。最后是网络层的隔离。NetworkPolicy只放行Agent到模型API、GitHub API和对象存储的出口流量其他出站一律默认拒绝。Agent有可能会被提示注入攻击或者某些时候模型被诱导着访问错误的目标网络策略就成了最后一道防火墙。5.4 流量路由与服务发现多副本智能体如何平衡压力如果发布到生产你的Agent可能不止一个副本。KARS通过replicas字段管理多个实例而Kubernetes Service天然提供轮询式的负载均衡。两个实例同时消费队列里的任务处理能力直接翻倍。但有一个问题要注意LLM推理是长耗时操作单个请求可能占住一个连接几十秒甚至几分钟。如果后端的Service负载均衡不做任何处理超时设置可能太短导致把还在处理中的请求判为失败。我的建议是接入层直接走异步队列模式而非同步HTTP。外部系统只需要把任务丢进队列Agent处理完把结果写到存储里外部系统通过回调或轮询拿到结果。这样整个链路对超时、重试、突刺都有天然免疫力。同步HTTP模式适合交互式短任务异步队列模式适合大多数真实业务。6. 我踩过的坑与排查心得KARS实战调试笔记6.1 冷启动与队列积压集群没节点时发生了什么第一次正式压测我遇到的情况是深夜时段集群自动缩容到了1个节点Agent也缩到了1个副本。早上上班时间CI系统一下子涌进来几十个任务消息瞬间堆满队列。Agent的HPA开始扩容但集群没有空闲节点cluster autoscaler要先把新节点拉起来这通常要2到4分钟。新节点起来后开始调度PodPod又要拉镜像这个过程中几十条消息全部堆积在队列里。这个问题的根源不是KARS而是所有云端弹性伸缩都面临的冷启动延迟。我做了三件事来缓解第一在集群里预留一个2节点的保底池不参与自动缩容保证核心任务随时能跑第二把Agent镜像推送到集群所在区域的ACR并且开启镜像预热新节点一启动就能立刻拉到镜像第三给Agent配置了基于队列深度的HPA条件队列长度的增速一旦超过阈值提前扩容而不是等任务堆积了才动。6.2 故障注入Agent挂了但你别让工作也挂了我还做过几次混沌演练主动杀掉Agent的Pod观察系统反应。第一次演练让我发现了一个隐患没有配置readiness探针的时候Pod已经被kill了但Service的Endpoints里还留着那个故障实例新任务依然会被路由到死掉的副本上。任务虽然会从队列里被重新消费但消费延迟增加了不少。第二次演练暴露了更严重的问题任务缺少幂等保护。Agent在处理一个建PR的任务时被杀掉重启后再消费同一条消息因为幂等判断没写好结果生成了两个几乎一模一样PR。从那次以后所有会对外产生影响的动作必须先查重成了我写Agent代码的硬性要求。我建议你也做一次类似的故障注入演练。故意kill几个Pod、把节点断掉观察任务会不会丢、会不会重复、恢复量有多少。在这里发现问题的成本远低于在生产事故后去排查。6.3 调试三件套Events、日志与CRD状态KARS调试时最常碰到的困惑是Agent的YAML已经apply了但Pod没有起来或者起来之后一直没反应。这时候我一般按下面这个顺序排查。第一步看Events。kubectl describe agent codefix-agent -n agentsEvents里会记录KARS Operator对这个Agent做了什么操作如果配置有问题比如镜像不存在、资源request超过节点容量、Secret缺失都会在这里留下记录。大部分配置错误的根因都能在Events里找到。第二步看Pod日志。kubectl logs -f -n agents -l agents.azure.com/namecodefix-agent注意Agent的日志除了模型调用的日志外还要打自己的决策日志。我会让Agent每做一个动作就输出一条结构化日志包含动作类型、目标对象、执行结果。这样在排查为什么它跑偏了的时候能还原整个决策轨迹。第三步看CRD的Status。kubectl get agent codefix-agent -n agents -o yamlKARS会把Agent的当前状态写进status里包括活了几副本、健康检查结果、最近一次消息处理状态。很多时候只凭status就能判断出是Agent卡在了模型调用上还是卡在了工具执行上用不着进Pod里瞎猜。6.4 成本控制让智能体与资源一起伸缩最后必须聊钱。LLM智能体的成本构成里容器资源只是小头模型API调用才是大头。但容器资源也不能完全不管因为长期挂着不干活的Agent一样在吃节点费用。我的做法是用KEDA给Agent配置基于队列深度的自动伸缩让它真正实现空闲归零有活重构。队列里没有消息时Agent缩到0副本Service没有可用后端也不怕因为工作任务在队列里躺着队列里来了消息KEDA检测到队列深度大于0开始扩容副本Prometheus指标一路跟着Agent的负载走。但要注意缩到0回弹会带来冷启动延迟。如果业务需要秒级响应还是得保留1个保底副本。我一般是看业务容忍度来定编码智能体这种本身要跑几十秒到几分钟的缩到0完全没压力。另外模型调用费用也得做预算。在Agent启动脚本里设置单任务的token上限超过阈值强制重启上下文或者直接放弃任务走人工。这个机制帮我防住过几次因为模型输出异常导致的大量token消耗。7. 下一步把编码智能体当成通用智能体基础设施的一块基石7.1 从编码智能体到通用Agent基础设施编码智能体只是第一个切入点。已经验证过这套模式之后你会发现其他类型的LLM智能体——运维助手、客服助手、数据分析助手——它们的底层需求几乎是同一个模子印出来的需要容器运行时、需要消息触发、需要健康检查、需要权限控制、需要审计日志。KARS的高明之处在于它没有为每一种智能体发明一套独特的管理方式而是把所有智能体的共性收敛成了Agent这一种资源抽象。业务逻辑可以千差万别但部署一个Agent这个动作是统一的。这一点对平台工程团队来说特别有价值因为你可以把Agent的标准发布流程、监控对接、权限申请全部标准化上层业务方只需要写自己的Agent镜像和业务逻辑。7.2 基础设施层的统一约束我现在的目标是把从编码智能体身上沉淀下来的经验固化成一套Agent基础设施的默认约束。不管上层跑的是哪种智能体基础设施层必须保证每个Agent都有可观测链路它的决策过程必须是可回放的每个Agent默认不允许直接写生产数据只能通过受控的API或队列通道操作每个Agent的动作都以任务为粒度做审计出了问题能追溯到某一次具体决策。这三个约束如果只在业务代码层面靠自觉执行迟早会出漏洞。但把它们固化到基础设施层每个Agent从出生那天起就带着这些规则就没有办法绕开。这也是我在KARS平台上看到的最大价值——它让我不再把智能体当成一个会写代码的脚本进程而是一个受良好约束的、平台化的执行者。从我个人实际操作中得到的体会是别急着在第一天就搭建一个完美的大平台。先在AKS上把一个Agent容器跑起来给它接上真实的消息队列再主动把它打挂一次你很快就会发现自己最缺的是什么。缺什么补什么远比一开始就追求架构完备要靠谱得多。