1. 从“ax”这个标题说起:一个被低估的Agent编排切口
第一次看到“ax”这个标题,加上后面跟着的 agent、orchestrator、kubernetes、workspace 这几个词,我脑子里第一反应是:这大概率是一个把 AI Agent 跑在 Kubernetes 上的编排层项目。为什么这么判断?因为“ax”这种极简命名,在基础设施圈子里通常意味着“抽象层”或者“执行器”——它不负责具体的业务逻辑,而是负责把一堆零散的 Agent 能力串起来,让它们在一个可控的运行时里干活。
我接触过不少 Agent 项目,从早期的单文件脚本,到后来动辄几十个 Agent 互相调用的复杂系统,踩过的坑基本都集中在三个地方:状态怎么管、资源怎么隔离、失败怎么恢复。而“ax”这个标题背后,恰好对应了这三个痛点的解法方向——用 orchestrator 做调度,用 kubernetes 做资源底座,用 workspace 做隔离边界。这套组合拳打下来,Agent 就不再是“跑在笔记本上的玩具”,而是能上生产环境的服务。
这篇文章适合谁看?如果你正在做 Agent 开发,尤其是多 Agent 协作、Agent 编排、Agent 部署测试这类场景,那这篇内容应该能帮你省下不少试错时间。如果你刚接触 Kubernetes,想找一个具体的落地场景来练手,那“用 K8s 跑 Agent”也是一个非常好的切入点。我会从整体设计思路讲到具体实操,包括参数怎么选、坑怎么避、问题怎么排查,尽量让不同基础的人都能拿走能用的东西。
提示:本文提到的“ax”是一个泛指的项目代号,核心讨论的是 Agent 编排层在 Kubernetes 上的落地实践,不涉及任何特定商业产品。
2. 整体设计思路:为什么是 Orchestrator + Kubernetes + Workspace
2.1 Agent 编排的核心矛盾:灵活性与可控性
Agent 开发和传统后端开发最大的区别在于,Agent 的行为是非确定性的。你给它一个任务,它可能调用三个工具就结束了,也可能调用三十个工具还在绕圈。这种不确定性在单机环境下还能靠日志和断点调试来对付,一旦放到生产环境,问题就会被放大:一个 Agent 卡住,可能拖垮整个任务队列;一个 Agent 内存泄漏,可能把宿主机搞崩。
所以 Agent 编排层要解决的核心矛盾就是:既要让 Agent 有足够的灵活性去自主决策,又要让整个系统保持可控。Orchestrator 就是在这个矛盾中间找平衡点的角色。它不干涉 Agent 的具体决策逻辑,但它负责决定“谁在什么时候、用多少资源、跑哪个任务”。
我见过一些团队一开始图省事,直接用 Python 的 asyncio 或者 Celery 来做 Agent 调度。小规模跑没问题,但一旦 Agent 数量上去,或者任务依赖变复杂,就会遇到几个典型问题:任务状态散落在各个 worker 的内存里,重启就丢;资源配额没法细粒度控制,一个 Agent 能把 CPU 吃满;失败重试逻辑要自己写,写到最后变成一团乱麻。这些问题,Kubernetes 其实已经给出了成熟的答案。
2.2 为什么选 Kubernetes 做 Agent 的运行时底座
Kubernetes 对 Agent 场景的适配性,主要体现在几个层面。第一是资源隔离,每个 Agent 可以跑在独立的 Pod 里,CPU、内存、GPU 都能设 request 和 limit,一个 Agent 崩了不会影响别的 Agent。第二是状态管理,K8s 的 Controller 模式天然适合做“期望状态 vs 实际状态”的调和,Agent 任务可以抽象成 CRD,Orchestrator 只需要声明“我要跑 10 个 Agent 实例”,剩下的交给 K8s 去保证。第三是失败恢复,Pod 挂了自动重启,节点挂了自动迁移,这些能力直接拿来用,不用自己造轮子。
当然,K8s 也不是银弹。它的学习曲线陡,对于只跑几个 Agent 的小项目来说,可能有点“杀鸡用牛刀”。但如果你预期 Agent 数量会增长,或者需要多租户隔离,那早点上 K8s 比后期迁移要省事得多。我自己的经验是,当 Agent 数量超过 20 个,或者任务并发超过 50 的时候,K8s 带来的收益就开始明显超过它的复杂度成本了。
2.3 Workspace 的角色:不只是“工作目录”
Workspace 在这个架构里经常被误解成“就是给 Agent 一个读写文件的地方”。实际上,Workspace 承担的责任要重得多。它是 Agent 的状态快照、依赖边界和安全沙箱。
先说状态快照。Agent 在执行任务过程中会产生大量中间状态——临时文件、缓存、对话历史、工具调用记录。这些状态如果散落在容器文件系统里,Pod 一重启就全没了。所以 Workspace 需要是一个可持久化的卷,最好能支持快照和恢复。我一般会用 PVC 来挂载 Workspace,并且定期做 VolumeSnapshot,这样即使 Agent 跑飞了,也能回到某个已知状态。
再说依赖边界。不同的 Agent 可能需要不同的 Python 版本、不同的系统库、不同的模型权重。如果全部塞在一个镜像里,镜像会变得巨大且难以维护。Workspace 可以配合 initContainer 来做依赖注入,每个 Agent 的 Workspace 里放自己的虚拟环境和模型缓存,基础镜像保持干净。
最后是安全沙箱。Agent 会执行代码、调用外部 API、读写文件,这些操作如果直接在宿主机上跑,风险很高。Workspace 配合 K8s 的 SecurityContext,可以限制 Agent 的系统调用、网络访问和文件权限。比如设置readOnlyRootFilesystem: true,只让 Workspace 目录可写,这样即使 Agent 被恶意输入诱导,也很难对系统造成持久性破坏。
2.4 方案选型对比:为什么不用 Serverless 或 Docker Compose
有人可能会问,为什么不用 Serverless 函数来跑 Agent?Serverless 的冷启动问题对 Agent 来说很致命,Agent 初始化往往要加载模型、建立连接,冷启动动辄几十秒,用户体验很差。而且 Serverless 的执行时长有限制,复杂 Agent 任务可能跑几十分钟,很容易超时。Docker Compose 倒是简单,但它缺乏 K8s 的调度能力和自愈能力,适合本地开发,不适合生产。
所以这套架构的选型逻辑是:本地开发用 Docker Compose 快速迭代,生产环境用 Kubernetes 保证可靠性和弹性。Orchestrator 层做成可移植的,底层运行时可以切换,这样开发和生产的环境差异不会太大。
3. 核心细节解析:Agent 编排层的关键设计
3.1 Agent 的生命周期管理:从创建到销毁
Agent 在 K8s 上的生命周期,我一般会抽象成五个阶段:Pending、Initializing、Running、Completed、Failed。每个阶段对应不同的 K8s 资源状态和 Orchestrator 的处理逻辑。
Pending 阶段,Orchestrator 接收到任务请求,生成 Agent 的 CRD 对象,K8s 调度器开始找合适的节点。这个阶段的关键是资源预检——如果集群资源不足,任务应该排队而不是直接失败。我通常会用 ResourceQuota 和 LimitRange 来做命名空间级别的资源约束,避免某个团队的 Agent 把整个集群吃满。
Initializing 阶段,Pod 被调度到节点上,开始拉镜像、挂载 Workspace、注入配置。这个阶段最容易出问题的是镜像拉取超时和Workspace 挂载失败。镜像建议用私有 Registry 并配置 ImagePullSecret,Workspace 的 PVC 要确保 StorageClass 支持 ReadWriteMany(如果多个 Agent 需要共享 Workspace)或者 ReadWriteOnce(如果每个 Agent 独立 Workspace)。
Running 阶段,Agent 的主进程启动,开始执行任务。Orchestrator 需要持续监控 Agent 的心跳和进度。我一般会让 Agent 定期向 Orchestrator 上报状态,如果超过一定时间没收到心跳,就判定为僵死,触发重启或迁移。
Completed 和 Failed 阶段,Agent 任务结束,Orchestrator 收集结果和日志,清理资源。这里要注意日志收集,Agent 的日志量可能很大,建议用 sidecar 容器做日志轮转和上报,避免把节点磁盘写满。
3.2 Orchestrator 的调度策略:轮询、优先级与亲和性
Orchestrator 的调度策略直接决定了 Agent 任务的执行效率和资源利用率。我实践下来,比较有效的策略是优先级队列 + 节点亲和性 + 污点容忍的组合。
优先级队列解决的是“重要任务先跑”的问题。比如线上推理任务优先级高于离线训练任务,用户交互任务优先级高于后台批处理任务。K8s 的 PriorityClass 可以配合 Orchestrator 的队列逻辑使用,高优先级的 Pod 可以抢占低优先级的 Pod。
节点亲和性解决的是“任务跑在合适的节点上”的问题。比如 GPU 任务要调度到有 GPU 的节点,内存密集型任务要调度到大内存节点。我一般会给节点打标签,然后在 Agent 的 CRD 里声明 nodeSelector 或 affinity。
污点容忍解决的是“专用节点不被普通任务占用”的问题。比如某些节点专门给高优先级 Agent 用,就可以打上污点,只有配置了对应 toleration 的 Agent 才能调度上去。
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority-agent value: 1000000 globalDefault: false description: "用于线上交互式 Agent 任务"上面这个 PriorityClass 定义了一个高优先级,值越大优先级越高。Orchestrator 在创建 Agent Pod 时引用这个 PriorityClass,就能让重要任务优先获得资源。
3.3 Workspace 的持久化与隔离方案
Workspace 的持久化方案选择,取决于 Agent 的类型。我一般把 Agent 分成三类:无状态 Agent、有状态 Agent、共享状态 Agent。
无状态 Agent 每次执行都是独立的,不需要保留中间状态,Workspace 可以用 emptyDir,Pod 销毁就清理,简单干净。有状态 Agent 需要保留对话历史、文件产出等,Workspace 要用 PVC,并且要配置备份策略。共享状态 Agent 是多个 Agent 需要读写同一份数据,Workspace 要用 ReadWriteMany 的 PVC,或者用对象存储做中间层。
隔离方案上,我强烈建议每个 Agent 独立 Workspace,即使它们属于同一个任务。共享 Workspace 虽然省存储,但会带来严重的并发问题和安全问题。一个 Agent 误删了文件,可能影响其他 Agent。如果确实需要共享,建议用只读挂载 + 独立可写层的方式,类似容器镜像的分层文件系统。
注意:PVC 的 StorageClass 选择很关键。如果用的是动态供给,要确认 StorageClass 支持你需要的访问模式。很多云厂商的默认 StorageClass 只支持 ReadWriteOnce,多 Agent 共享场景下会挂载失败。
3.4 Agent 与 Orchestrator 的通信协议设计
Agent 和 Orchestrator 之间的通信,我试过几种方案:REST API、gRPC、消息队列、K8s 原生 Watch。每种都有适用场景。
REST API 最简单,Agent 通过 HTTP 上报状态和拉取任务。缺点是实时性差,需要轮询。gRPC 性能好,支持双向流,适合高频通信场景,但需要维护 proto 定义。消息队列(如 NATS、RabbitMQ)解耦彻底,Agent 和 Orchestrator 不需要知道对方地址,适合大规模动态扩缩容场景。K8s 原生 Watch 最“云原生”,Orchestrator 直接 Watch Agent CRD 的状态变化,不需要额外通信通道,但只适合状态同步,不适合传输大量数据。
我现在的做法是混合使用:状态同步用 K8s Watch,任务下发用消息队列,大文件传输用对象存储。这样各取所长,系统整体比较均衡。
4. 实操过程:从零搭建一个 Agent 编排环境
4.1 环境准备与基础组件安装
假设你有一个至少三节点的 K8s 集群(可以用 kubeadm 搭,也可以用托管集群),版本建议 1.24 以上,因为很多新的 CRD 特性需要较新版本。基础组件我一般会装这几个:Ingress Controller(用于暴露 Orchestrator API)、Cert-Manager(用于证书管理)、Metrics Server(用于 HPA 和资源监控)、Prometheus + Grafana(用于可观测性)。
# 安装 Metrics Server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # 验证 Metrics Server 是否正常 kubectl top nodes如果kubectl top nodes能输出节点资源使用情况,说明 Metrics Server 工作正常。这一步很关键,因为后面 Agent 的 HPA 和资源调度都依赖它。
4.2 定义 Agent 的 CRD 与 Controller
Agent 的 CRD 是整个编排层的核心抽象。我设计的 Agent CRD 大概长这样:
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: agents.ax.example.com spec: group: ax.example.com versions: - name: v1alpha1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: image: type: string command: type: array items: type: string workspaceSize: type: string priority: type: string timeoutSeconds: type: integer status: type: object properties: phase: type: string message: type: string startTime: type: string scope: Namespaced names: plural: agents singular: agent kind: Agent shortNames: - ag这个 CRD 定义了 Agent 的镜像、启动命令、Workspace 大小、优先级和超时时间。Controller 监听 Agent 对象的变化,当有新的 Agent 被创建时,Controller 负责生成对应的 Deployment 或 Job,并挂载 Workspace。
Controller 的实现可以用 Kubebuilder 或者 Operator SDK,我一般用 Kubebuilder,因为它的脚手架比较成熟,生成的代码结构清晰。核心的 Reconcile 逻辑就是:读取 Agent Spec,检查当前状态,如果 Pod 不存在就创建,如果 Pod 状态和期望不符就更新,如果 Agent 被删除就清理资源。
4.3 部署第一个 Agent 并验证
CRD 和 Controller 就绪后,就可以部署第一个 Agent 了。我一般会先跑一个最简单的 Agent 来验证链路:一个 Python 脚本,打印环境变量和 Workspace 内容,然后退出。
apiVersion: ax.example.com/v1alpha1 kind: Agent metadata: name: hello-agent namespace: default spec: image: python:3.11-slim command: - python - -c - | import os print("Agent started") print("Workspace:", os.listdir("/workspace")) with open("/workspace/output.txt", "w") as f: f.write("Hello from Agent") print("Done") workspaceSize: 1Gi priority: normal timeoutSeconds: 300应用这个 YAML 后,用kubectl get agents查看状态,用kubectl logs查看 Agent 输出。如果一切正常,你应该能看到 Agent 打印出 Workspace 内容,并且在 Workspace 里生成了 output.txt。
4.4 多 Agent 协作的编排示例
单 Agent 跑通后,下一步是多 Agent 协作。我设计了一个简单的场景:一个“规划 Agent”负责拆解任务,两个“执行 Agent”负责并行处理子任务,一个“汇总 Agent”负责合并结果。
Orchestrator 的逻辑是:先创建规划 Agent,等它输出子任务列表;然后根据子任务数量创建对应数量的执行 Agent,每个执行 Agent 的 Workspace 里注入对应的子任务;等所有执行 Agent 完成后,创建汇总 Agent,把所有执行 Agent 的 Workspace 挂载到汇总 Agent 的 Workspace 下(只读),汇总 Agent 读取结果并生成最终报告。
这个过程中,Orchestrator 需要维护一个任务依赖图,确保 Agent 按正确的顺序启动。我一般用 Argo Workflows 或者 Tekton 来做这种 DAG 编排,它们对 K8s 的原生支持很好,而且有现成的 UI 可以看任务进度。
# 简化的 Argo Workflow 示例 apiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: generateName: multi-agent- spec: entrypoint: agent-pipeline templates: - name: agent-pipeline dag: tasks: - name: planner template: run-agent arguments: parameters: - name: role value: planner - name: executor-1 dependencies: [planner] template: run-agent arguments: parameters: - name: role value: executor - name: task-id value: "1" - name: executor-2 dependencies: [planner] template: run-agent arguments: parameters: - name: role value: executor - name: task-id value: "2" - name: summarizer dependencies: [executor-1, executor-2] template: run-agent arguments: parameters: - name: role value: summarizer - name: run-agent inputs: parameters: - name: role - name: task-id default: "" container: image: my-agent-image:latest command: ["python", "run_agent.py"] args: ["--role", "{{inputs.parameters.role}}", "--task-id", "{{inputs.parameters.task-id}}"] volumeMounts: - name: workspace mountPath: /workspace volumes: - name: workspace persistentVolumeClaim: claimName: agent-workspace这个 Workflow 定义了一个 DAG,planner 先跑,然后两个 executor 并行跑,最后 summarizer 汇总。每个 Agent 共享同一个 PVC,但通过 task-id 区分各自的子目录,避免冲突。
5. 常见问题与排查技巧实录
5.1 Agent Pod 一直 Pending 的排查思路
Pod 一直 Pending 是最常见的问题,原因通常有三类:资源不足、调度约束不满足、PVC 挂载失败。
排查步骤我一般是这样:先kubectl describe pod <pod-name>看 Events,里面会明确写原因。如果是Insufficient cpu或Insufficient memory,说明集群资源不够,需要扩容节点或者降低 Agent 的资源请求。如果是node(s) didn't match node selector,说明 nodeSelector 配置有问题,检查节点标签是否正确。如果是pod has unbound immediate PersistentVolumeClaims,说明 PVC 没有绑定成功,检查 StorageClass 是否存在、容量是否足够。
实操心得:我习惯在 Orchestrator 里加一个“资源预检”逻辑,在创建 Agent 之前先检查集群剩余资源,如果不够就直接返回错误,而不是让 Pod 卡在 Pending。这样用户体验更好,也避免了资源被无效占用。
5.2 Workspace 挂载失败与权限问题
Workspace 挂载失败通常表现为 Pod 启动时报mount failed或permission denied。原因可能是 PVC 的访问模式和多个 Pod 的挂载需求不匹配,比如 ReadWriteOnce 的 PVC 被多个 Pod 同时挂载就会失败。也可能是 SecurityContext 的 fsGroup 没有设置,导致容器内用户没有 Workspace 的写权限。
解决方法:如果是多 Pod 共享,PVC 必须用 ReadWriteMany;如果是权限问题,在 Pod 的 SecurityContext 里设置fsGroup: 1000(或者你的容器用户组 ID),K8s 会自动把 Workspace 的组权限改成这个组。
securityContext: fsGroup: 1000 runAsUser: 1000 runAsGroup: 10005.3 Agent 执行超时与僵死检测
Agent 执行超时有两种情况:一种是任务本身确实需要很长时间,另一种是 Agent 卡死了。区分方法是看 Agent 有没有心跳上报。如果 Agent 定期上报进度,即使任务时间长也没关系;如果心跳停了,那就是僵死。
我一般会在 Agent 的入口脚本里加一个心跳线程,每隔 10 秒向 Orchestrator 发一个心跳。Orchestrator 维护一个心跳表,如果某个 Agent 超过 30 秒没心跳,就标记为僵死,触发重启或告警。
import threading import time import requests def heartbeat_loop(agent_id, orchestrator_url): while True: try: requests.post(f"{orchestrator_url}/heartbeat", json={"agent_id": agent_id}) except Exception as e: print(f"Heartbeat failed: {e}") time.sleep(10) # 在 Agent 主逻辑启动前开启心跳线程 threading.Thread(target=heartbeat_loop, args=(agent_id, orch_url), daemon=True).start()5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
| Pod Pending | 资源不足 | kubectl describe pod | 扩容节点或降低资源请求 |
| Pod Pending | 调度约束不满足 | kubectl describe pod | 检查 nodeSelector/affinity |
| Pod Pending | PVC 未绑定 | kubectl get pvc | 检查 StorageClass 和容量 |
| 挂载失败 | 访问模式不匹配 | kubectl describe pvc | 改用 ReadWriteMany |
| 权限拒绝 | fsGroup 未设置 | kubectl exec查看权限 | 设置 SecurityContext |
| Agent 僵死 | 心跳停止 | 查看 Orchestrator 心跳表 | 重启 Agent 或告警 |
| 镜像拉取失败 | 私有仓库认证 | kubectl describe pod | 配置 ImagePullSecret |
| 日志丢失 | 容器日志未收集 | kubectl logs | 加 sidecar 日志收集 |
5.5 几个容易忽略的坑
第一个坑是时区问题。容器默认是 UTC 时间,如果 Agent 逻辑依赖本地时间,会出现时间偏差。解决方法是在容器里设置 TZ 环境变量,或者挂载宿主机的 /etc/localtime。
第二个坑是DNS 解析。Agent 如果需要访问外部服务,K8s 的 DNS 配置可能会影响解析。我遇到过 Agent 访问内部服务时解析到错误 IP 的情况,最后发现是 ndots 配置导致的。可以在 Pod 的 dnsConfig 里调整 ndots 值。
第三个坑是资源限制太紧。Agent 在运行过程中可能会临时占用较多内存,如果 limit 设得太低,会被 OOM Kill。建议 limit 至少是 request 的 1.5 到 2 倍,给 Agent 留出缓冲空间。
第四个坑是镜像层缓存。如果 Agent 镜像经常更新,节点上的镜像缓存可能会占用大量磁盘。建议配置 K8s 的 imageGC 策略,定期清理未使用的镜像。
6. 工具选型与扩展方向
6.1 Orchestrator 框架选型对比
| 框架 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 自研 Controller | 完全可控,贴合业务 | 开发成本高 | 有特殊调度需求 |
| Argo Workflows | DAG 编排成熟,UI 好用 | 偏批处理,交互式弱 | 离线任务、流水线 |
| Tekton | 云原生,可扩展 | 学习曲线陡 | CI/CD 场景 |
| KubeFlow | ML 生态完整 | 较重,依赖多 | 机器学习任务 |
| Temporal | 状态管理强 | 需要额外部署 | 长流程、有状态任务 |
我自己的选择是:简单场景用 Argo Workflows,复杂状态管理用 Temporal,特殊调度需求自研 Controller。没有银弹,关键是匹配业务需求。
6.2 Agent 记忆框架的集成思路
Agent 记忆是最近很热的方向,a-memguard 这类主动防御框架也开始出现。在 K8s 环境下,Agent 记忆的存储层我一般会用 Redis 做短期记忆,用向量数据库(如 Milvus、Qdrant)做长期记忆,用对象存储做冷备份。
集成方式上,记忆服务可以独立部署为一组 Pod,Agent 通过 Service 访问。这样记忆服务可以独立扩缩容,不会因为 Agent 数量增加而成为瓶颈。同时,记忆服务的持久化用 StatefulSet + PVC,保证数据不丢。
6.3 Agent 安全加固的几个方向
Agent 安全是我越来越重视的方向。除了前面提到的 Workspace 隔离和 SecurityContext,还有几个加固点:网络策略限制 Agent 只能访问必要的服务;镜像扫描确保基础镜像没有已知漏洞;运行时安全用 Falco 或类似工具监控异常行为;输入过滤防止提示注入攻击。
提示:Agent 的权限应该遵循最小权限原则。不要给 Agent 挂载 ServiceAccount Token,除非它确实需要访问 K8s API。不要给 Agent 开放不必要的网络出口,避免数据泄露。
6.4 从单集群到多集群的扩展
当 Agent 数量继续增长,单集群可能不够用,这时候要考虑多集群编排。我一般会用 Karmada 或 Cluster API 来做多集群管理,Orchestrator 层增加一个“集群选择器”,根据任务需求和集群负载决定把 Agent 调度到哪个集群。
多集群带来的额外复杂度主要是网络连通性和数据同步。Agent 的 Workspace 如果跨集群访问,延迟会很高,所以最好让 Agent 和它的 Workspace 在同一个集群。跨集群的数据同步可以用对象存储做中转,或者用专门的同步工具。
7. 一些个人体会
这套 Agent 编排方案我在几个项目里跑过,整体稳定性比早期的脚本调度好很多。但也不是没有代价,K8s 的运维成本是实打实的,小团队如果没有专职的运维,可能会觉得吃力。我的建议是,如果 Agent 规模不大,先用 Docker Compose 或者轻量级调度器跑起来,等确实遇到瓶颈了再上 K8s,不要为了“云原生”而云原生。
另外,Agent 的可观测性比传统服务更重要。传统服务的行为是确定的,看日志和指标基本能定位问题。Agent 的行为是非确定的,同样的输入可能产生不同的输出,所以除了日志和指标,还需要记录 Agent 的决策轨迹——它调用了哪些工具、看到了什么中间结果、为什么选择这个分支。这些轨迹数据对调试和优化非常关键。
最后分享一个小技巧:在 Agent 的 Workspace 里放一个manifest.json,记录这次执行的元信息——Agent 版本、模型版本、工具列表、输入摘要。这样排查问题时,只要看这个文件就能快速了解 Agent 的运行环境,不用去翻一堆日志。这个习惯帮我省了很多时间。