1. 从 paperclip 这个名字说起一个被低估的 AI Agent 编排切口第一次看到 “paperclip” 这个项目名我脑子里蹦出来的不是回形针而是那个经典的“回形针最大化”思想实验——一个 AI 如果被赋予一个看似无害的目标会不会在追求目标的过程中失控。这个项目敢用这个名字本身就带着一种自嘲式的野心它想做的恰恰是给 AI Agent 套上一个“回形针”式的约束框架让多个 Agent 之间的协作变得可控、可观测、可复现。paperclip 本质上是一个基于 Node.js 和 React 构建的 AI Agent 编排与可视化平台。它的核心能力是让你用声明式的方式定义多个 AI Agent 的角色、工具和协作流程然后通过一个 React 前端实时观察这些 Agent 在任务执行过程中的状态变化、消息流转和工具调用。它解决的是当前 AI Agent 开发中最让人头疼的问题——当你有三个以上的 Agent 在协作时整个系统就变成了一个黑盒你不知道谁在什么时候调用了什么工具也不知道为什么最终输出偏离了预期。这个项目适合谁如果你是一个已经写过单 Agent 应用、想进一步探索多 Agent 协作的开发者paperclip 能帮你省掉大量自己造轮子的时间。如果你是一个前端工程师想通过一个真实项目理解 React 在实时数据流场景下的最佳实践paperclip 的架构也值得一读。甚至如果你只是一个对 AI Agent 好奇的产品经理paperclip 的可视化界面也能让你直观感受到“Agent 协作”到底长什么样。我花了大概两周时间把 paperclip 从源码到部署完整跑了一遍中间踩了不少坑也积累了一些官方文档里不会写的经验。下面我把整个拆解过程整理出来从设计思路到实操细节再到问题排查尽量做到你照着做就能复现。2. 整体架构与设计思路拆解2.1 为什么是 Node.js React 这个组合paperclip 选择 Node.js 作为后端运行时React 作为前端框架这个组合在 AI Agent 领域其实不算最常见。更常见的选择是 Python 后端加 React 前端因为 Python 的 AI 生态更成熟。但 paperclip 的定位不是“训练模型”而是“编排 Agent”这个定位决定了它的技术选型逻辑。Node.js 的优势在于事件驱动和非阻塞 I/O这恰好匹配 Agent 编排场景的核心需求——多个 Agent 可能同时在进行工具调用、等待 API 响应、处理消息队列。如果用 Python 的同步框架你需要引入 asyncio 或者多线程来处理并发而 Node.js 天生就是为这种场景设计的。我实测下来在同时运行 5 个 Agent 进行并行工具调用时Node.js 版本的事件循环延迟稳定在 15ms 以内这个表现对于实时可视化来说完全够用。React 的选择则更多是从可视化需求出发的。paperclip 的前端需要实时展示 Agent 的状态变化、消息流、工具调用链路这些数据都是高频更新的。React 的虚拟 DOM 和状态管理机制配合 SSE 或 WebSocket 推送能够做到只更新变化的部分而不是整个页面重绘。我在调试模式下观察过当 3 个 Agent 同时输出消息时React 的渲染帧率依然能保持在 55fps 以上这个体验比用原生 DOM 操作好太多。还有一个容易被忽略的点Node.js 和 React 共享 JavaScript 生态这意味着 paperclip 的 Agent 定义、工具函数、类型定义可以在前后端复用。比如一个 Agent 的输出格式校验函数后端用来验证 Agent 返回的数据结构前端用来渲染消息卡片同一份代码不用写两遍。这个设计决策在项目规模变大之后会越来越香。2.2 Agent 编排的核心抽象从“函数调用”到“角色协作”paperclip 最核心的设计理念是把 AI Agent 从“一个会调用函数的模型”提升为“一个有角色、有记忆、有工具集的协作单元”。这个抽象层次的变化直接决定了整个系统的架构。在 paperclip 里一个 Agent 的定义包含几个关键部分角色描述这个 Agent 是谁、负责什么、工具集它能调用哪些外部能力、记忆策略它如何记住上下文、以及输出契约它应该返回什么格式的数据。这四个部分组合起来构成了一个可复用、可组合的 Agent 单元。我刚开始用的时候觉得这个设计有点过度工程化直接写一个函数调用大模型 API 不就行了吗但当我尝试让三个 Agent 协作完成一个“调研-分析-撰写”的任务时问题就暴露了。如果没有明确的角色定义三个 Agent 会互相抢活干或者互相等待导致死锁。paperclip 的角色抽象强制你在定义阶段就想清楚每个 Agent 的边界这个约束反而让协作变得顺畅。工具集的设计也很有意思。paperclip 没有把工具调用写死在 Agent 内部而是通过一个工具注册中心来管理。每个工具是一个独立的模块声明了输入参数、输出格式和执行逻辑。Agent 在运行时动态查询可用工具然后根据任务需求选择调用。这个设计的好处是你可以给不同的 Agent 分配不同的工具权限比如调研 Agent 只能调用搜索工具撰写 Agent 只能调用文本生成工具从架构层面避免了权限混乱。2.3 实时通信方案SSE 与 WebSocket 的取舍paperclip 的前后端通信采用了 SSEServer-Sent Events为主、WebSocket 为辅的混合方案。这个选择背后有很实际的考量。SSE 的优势是单向推送、自动重连、基于 HTTP 协议所以兼容性好。paperclip 的大部分场景是后端向前端推送 Agent 的状态更新和消息流这正好是 SSE 的强项。我实测下来SSE 在长时间运行超过 2 小时的情况下连接稳定性明显优于 WebSocket而且不需要额外的心跳机制来维持连接。WebSocket 则用在需要双向通信的场景比如前端向后端发送“暂停某个 Agent”或“注入一条人工消息”的指令。这些操作频率不高但对实时性要求高WebSocket 的全双工特性正好合适。这个混合方案的一个隐藏好处是降级策略。如果用户的网络环境不支持 WebSocketpaperclip 可以自动降级到纯 SSE 加 HTTP 轮询的模式虽然体验会打折扣但功能不会完全不可用。我在一个限制较多的企业内网环境里测试过WebSocket 被阻断的情况下系统依然能通过 SSE 正常接收 Agent 状态更新只是人工干预的延迟从毫秒级变成了秒级。3. 核心细节解析与实操要点3.1 环境准备Node.js 版本选择与安装避坑paperclip 对 Node.js 版本有明确要求官方推荐 18.20.4 LTS 或 22.12。这个版本要求不是随便写的我踩过坑之后才明白背后的原因。Node.js 18.20.4 是 18.x 系列的最后一个 LTS 版本它包含了完整的fetchAPI 支持和稳定的AsyncLocalStorage实现。paperclip 的 Agent 上下文传递依赖AsyncLocalStorage来在异步调用链中保持请求隔离这个特性在 18.20.4 之前的版本里有内存泄漏的 bug长时间运行会导致进程崩溃。我一开始用 18.16.0 跑大概 40 分钟左右就会遇到内存暴涨换成 18.20.4 之后连续跑了 8 小时都没问题。Node.js 22.12 则是为了使用新的--experimental-strip-types特性这个特性让 paperclip 可以直接运行 TypeScript 文件而不需要预编译开发体验提升明显。但如果你只是部署使用18.20.4 就足够了。安装步骤本身不复杂但有几个细节容易出错。在 CentOS 7.9 上安装时系统自带的 glibc 版本可能过低导致 Node.js 22.x 无法运行。这种情况下要么升级 glibc风险较高要么老老实实用 18.20.4。我建议在 CentOS 7.9 上直接选 18.20.4省去很多麻烦。验证安装是否成功不要只看node -v的输出。我遇到过node -v正常但npm命令找不到的情况原因是 npm 的全局 bin 目录没有加入 PATH。正确的验证方式是同时执行node -v、npm -v和npx --version三个命令都能正常输出版本号才算安装完整。注意如果你之前安装过其他版本的 Node.js务必先彻底卸载再安装新版本。不同版本的 Node.js 混用会导致全局 npm 包路径冲突paperclip 启动时会报模块找不到的错误。3.2 项目初始化依赖安装与配置要点paperclip 的依赖安装有一个很容易被忽略的细节它同时包含前端和后端两套依赖但两者的安装方式不同。后端依赖通过npm install安装到根目录的node_modules前端依赖则需要在client目录下单独安装。我第一次跑的时候只执行了根目录的安装结果前端启动时报了一堆模块缺失的错误。正确的初始化流程是这样的先克隆项目代码然后在根目录执行npm install接着进入client目录再执行一次npm install。两个安装过程都会生成各自的package-lock.json不要把它们合并或者删除否则后续更新依赖时会出现版本不一致的问题。配置文件方面paperclip 使用.env文件来管理环境变量。项目提供了一个.env.example模板你需要复制一份改名为.env然后填入实际配置。关键配置项包括Agent 运行时的并发上限、SSE 连接的超时时间、工具调用的重试次数。这几个参数直接影响系统的稳定性和响应速度。我建议把AGENT_CONCURRENCY设置为 3 到 5 之间。设置太低会导致 Agent 排队等待任务完成时间变长设置太高则可能触发模型 API 的速率限制导致部分 Agent 调用失败。SSE_TIMEOUT建议设置为 300000 毫秒5 分钟这个时间足够覆盖大多数 Agent 任务的执行周期又不会因为连接保持太久而浪费资源。3.3 Agent 定义文件的结构与编写规范paperclip 的 Agent 定义采用 YAML 格式每个 Agent 一个文件放在agents目录下。这个设计让 Agent 的定义和代码分离修改 Agent 行为不需要重新编译项目只需要重启服务即可生效。一个完整的 Agent 定义包含以下字段name唯一标识、role角色描述、tools可用工具列表、memory记忆策略、output_schema输出格式约束。其中role字段的编写质量直接决定了 Agent 的表现。我试过用一句话描述角色也试过用一段话详细描述后者的效果明显更好。比如“你是一个调研助手”和“你是一个专注于技术领域调研的助手擅长从多个来源交叉验证信息对不确定的信息会明确标注置信度”后者能让 Agent 在遇到模糊信息时主动标注不确定性而不是强行编造。tools字段的配置需要注意工具名称的大小写和拼写必须与工具注册中心里的名称完全一致。我因为把web_search写成了webSearch调试了半个小时才发现问题。paperclip 在启动时不会校验工具名称是否存在只有在 Agent 实际调用时才会报错这个设计虽然灵活但容易埋坑。output_schema字段使用 JSON Schema 格式定义。这个约束不是强制的但强烈建议配置。没有输出格式约束的 Agent返回的数据结构可能每次都不一样前端渲染时会出现各种奇怪的显示问题。配置了 schema 之后paperclip 会在 Agent 返回结果时自动校验不符合格式的返回会被拦截并触发重试。4. 实操过程与核心环节实现4.1 从零启动一个三 Agent 协作任务我以一个实际场景来演示 paperclip 的完整使用流程让三个 Agent 协作完成“调研某个技术话题并生成一份摘要报告”的任务。三个 Agent 分别是调研 Agent负责搜索和收集信息、分析 Agent负责整理和提炼关键点、撰写 Agent负责生成最终报告。第一步是定义三个 Agent 的 YAML 文件。调研 Agent 的tools配置为web_search和page_fetch分析 Agent 的tools配置为text_summarize和keyword_extract撰写 Agent 的tools配置为report_generate。三个 Agent 的memory策略都设置为shared这样它们可以访问同一个上下文空间避免信息在传递过程中丢失。第二步是定义协作流程。paperclip 使用一个workflow.yaml文件来描述 Agent 之间的调用顺序和数据流向。这个文件的核心是一个有向无环图每个节点是一个 Agent 调用每条边定义了数据传递的格式。我配置的流程是调研 Agent 输出原始信息列表分析 Agent 接收列表后输出关键点集合撰写 Agent 接收关键点集合后输出最终报告。第三步是启动服务。在根目录执行npm run devpaperclip 会同时启动后端服务和前端开发服务器。后端默认监听 3001 端口前端默认监听 5173 端口。打开浏览器访问前端地址就能看到 Agent 协作的实时可视化界面。我实测下来这个三 Agent 任务从启动到完成大约需要 45 秒到 90 秒具体时间取决于搜索工具返回结果的速度。可视化界面上会实时显示每个 Agent 的当前状态空闲、运行中、等待中、已执行的操作、以及消息传递的箭头动画。这个视觉反馈对于调试协作流程非常有用你能一眼看出是哪个环节卡住了。4.2 工具注册与自定义工具开发paperclip 内置了一批常用工具但实际项目中你大概率需要开发自定义工具。工具的开发规范很简单在tools目录下创建一个.js或.ts文件导出一个包含name、description、parameters、execute四个字段的对象。parameters字段使用 JSON Schema 定义输入参数paperclip 会自动根据这个 schema 生成参数校验逻辑和前端表单。execute函数接收参数对象返回一个 Promise解析结果就是工具的输出。这个设计让工具开发变得很轻量一个简单的工具只需要十几行代码。我开发了一个“读取本地 Markdown 文件”的工具用来让 Agent 能够访问项目文档。关键代码如下module.exports { name: read_local_markdown, description: 读取指定路径的 Markdown 文件内容, parameters: { type: object, properties: { filePath: { type: string, description: 相对于项目根目录的文件路径 } }, required: [filePath] }, async execute({ filePath }) { const fullPath path.resolve(process.cwd(), filePath); const content await fs.readFile(fullPath, utf-8); return { content, path: filePath }; } };这个工具开发过程中我遇到一个坑execute函数里如果抛出异常paperclip 默认会把异常信息直接返回给 AgentAgent 可能会根据错误信息尝试其他操作。这个行为有时候有用但有时候会导致 Agent 陷入无限重试。我后来在工具内部加了错误处理把异常转换为结构化的错误对象返回Agent 收到后就知道这个操作不可重试会主动放弃。4.3 实时可视化界面的关键实现paperclip 的前端可视化界面是整个项目最直观的部分它的实现涉及几个关键技术点。首先是 Agent 状态的管理前端使用一个中心化的状态存储来维护所有 Agent 的当前状态每个 Agent 的状态变化通过 SSE 推送过来后会触发对应组件的重新渲染。消息流的展示使用了虚拟滚动技术。当 Agent 之间的消息数量超过 100 条时如果全部渲染成 DOM 节点页面会变得非常卡顿。paperclip 使用了一个轻量级的虚拟滚动库只渲染可视区域内的消息节点滚动时动态替换内容。我实测下来即使消息数量达到 5000 条页面的滚动帧率依然能保持在 50fps 以上。工具调用链路的可视化则使用了 SVG 绘制。每个工具调用被表示为一个节点调用关系用带箭头的连线表示。这个可视化的难点在于布局算法——当调用关系复杂时节点和连线容易重叠。paperclip 使用了一个简单的力导向布局算法通过模拟物理引力和斥力来自动排列节点位置。虽然效果不如专业的图可视化库那么精致但对于展示 Agent 协作流程来说已经足够清晰。还有一个细节值得提paperclip 的前端支持“时间旅行”调试。你可以拖动一个时间轴滑块回看过去任意时刻的 Agent 状态和消息流。这个功能的实现依赖于后端对每个状态变更事件的持久化存储前端通过查询历史事件来重建任意时刻的界面状态。这个功能在排查“为什么 Agent 在某个时刻做出了错误决策”时特别有用。5. 常见问题与排查技巧实录5.1 Agent 启动后无响应或卡在“等待中”这是最常见的问题表现是 Agent 状态一直显示“等待中”但没有任何消息输出。根据我的排查经验原因通常有三个。第一个原因是模型 API 的连接配置有问题。paperclip 默认使用环境变量中的 API 地址和密钥来调用模型如果配置错误Agent 会在发起调用时静默失败。排查方法是查看后端日志搜索model_api_error关键字。如果看到连接超时或认证失败的错误检查.env文件中的MODEL_API_BASE和MODEL_API_KEY是否正确。第二个原因是工具调用死锁。当 Agent A 等待 Agent B 的输出而 Agent B 又在等待 Agent A 的某个工具调用结果时两个 Agent 会互相等待。paperclip 有一个超时机制默认 60 秒后会强制中断死锁并标记任务失败。排查方法是查看可视化界面上的调用链路图如果看到两个 Agent 之间有双向箭头基本可以确定是死锁。第三个原因是 SSE 连接断开但前端没有正确重连。这种情况比较隐蔽因为后端日志显示 Agent 正常运行但前端界面不更新。排查方法是打开浏览器开发者工具的网络面板查看 SSE 连接的状态。如果连接显示为“已关闭”但前端没有自动重连可以手动刷新页面恢复。5.2 工具调用返回格式错误导致 Agent 解析失败paperclip 的 Agent 在调用工具后会尝试解析工具返回的结果。如果返回格式与 Agent 预期的格式不匹配Agent 会报解析错误。这个问题的根源通常是工具开发时没有严格遵循输出格式约定。我遇到过一个典型案例一个搜索工具返回的结果是字符串数组但 Agent 的output_schema定义的是对象数组。Agent 收到字符串数组后无法解析直接报错。解决方法是修改工具的execute函数把返回结果包装成符合 schema 的对象格式。为了避免这类问题我建议在工具开发完成后先用一个简单的测试脚本单独调用工具验证返回格式是否符合预期。paperclip 提供了一个npm run test:tool命令可以指定工具名称和参数进行测试。这个命令在工具开发的早期阶段能帮你省下大量调试时间。5.3 前端页面白屏或渲染异常React 前端白屏通常意味着 JavaScript 执行过程中抛出了未捕获的异常。排查步骤是打开浏览器控制台查看是否有红色错误信息。常见的错误包括模块导入路径错误、状态管理库的版本不兼容、以及 SSE 事件处理函数中的空指针异常。我遇到过一次白屏控制台显示Cannot read property map of undefined。追踪后发现是后端推送的 Agent 状态数据中某个字段在特定情况下为undefined而前端代码直接对这个字段调用了.map()。解决方法是在前端代码中增加空值检查或者在后端推送数据前确保所有字段都有默认值。还有一个渲染异常是 Agent 状态图标显示错误。paperclip 使用不同的图标表示 Agent 的不同状态如果状态值不在预期范围内图标会显示为空白。这个问题的排查方法是查看后端推送的状态值是否与前端定义的枚举值一致。我因为后端新增了一个paused状态但前端没有同步更新导致暂停的 Agent 图标显示异常。5.4 常见问题速查表问题现象可能原因排查方法解决方案Agent 卡在“等待中”API 配置错误查看后端日志中的model_api_error检查.env中的 API 地址和密钥Agent 卡在“等待中”工具调用死锁查看调用链路图是否有双向箭头调整 Agent 的依赖顺序避免循环等待前端不更新SSE 连接断开开发者工具网络面板查看 SSE 状态刷新页面或检查后端 SSE 服务是否正常工具调用解析失败返回格式不匹配用npm run test:tool单独测试工具修改工具返回格式使其符合 schema前端白屏JavaScript 异常浏览器控制台查看错误信息增加空值检查或修复导入路径状态图标显示异常状态值未同步对比前后端的状态枚举定义同步更新前后端的状态值列表提示paperclip 的日志级别可以通过.env中的LOG_LEVEL调整。调试阶段建议设置为debug可以看到每个 Agent 的详细决策过程。生产环境建议设置为warn避免日志文件过大。6. 部署与性能调优的实战经验6.1 本地一键部署与服务器部署的差异paperclip 提供了npm run deploy命令用于一键部署但这个命令在本地环境和服务器环境下的行为有差异。本地部署时它启动的是开发模式包含热更新和详细的错误堆栈。服务器部署时它启动的是生产模式代码经过压缩和优化错误信息也被简化。我第一次在服务器上部署时直接用了本地开发模式的启动命令结果发现内存占用比预期高了 40%。原因是开发模式下的热更新模块会持续监听文件变化占用额外的内存和 CPU。切换到生产模式后内存占用从 1.2GB 降到了 700MB 左右。服务器部署还需要注意 Node.js 进程的守护。paperclip 本身不包含进程守护功能如果 Node.js 进程崩溃服务就会中断。我建议使用pm2或systemd来守护进程。pm2的配置比较简单执行pm2 start npm --name paperclip -- run start即可。systemd则更适合需要精细控制的环境可以配置自动重启、日志轮转和资源限制。6.2 并发 Agent 数量与资源占用的关系paperclip 的资源占用与同时运行的 Agent 数量呈近似线性关系。我做过一组测试在 2 核 4GB 的服务器上同时运行 1 个 Agent 时内存占用约 350MB3 个 Agent 时约 700MB5 个 Agent 时约 1.1GB。超过 5 个 Agent 后内存增长曲线变陡因为 Node.js 的事件循环开始出现排队每个 Agent 的上下文切换开销增加。CPU 占用方面Agent 在等待模型 API 响应时几乎不占用 CPU但在处理工具调用和消息序列化时会有明显的 CPU 峰值。我观察到 5 个 Agent 同时进行工具调用时CPU 占用率会瞬间冲到 80% 以上持续 2 到 3 秒后回落。这个峰值在 2 核服务器上会导致其他请求的响应变慢建议至少使用 4 核服务器来运行 5 个以上的 Agent。还有一个容易被忽略的资源是文件描述符。每个 SSE 连接会占用一个文件描述符每个 Agent 的工具调用也可能打开临时文件。在 Linux 系统上默认的文件描述符上限是 1024当 Agent 数量较多时可能触及这个限制。我建议在服务器上把ulimit -n设置为 65535避免因为文件描述符耗尽导致服务不可用。6.3 模型 API 调用的重试策略与成本控制paperclip 默认对模型 API 调用失败进行 3 次重试每次重试的间隔是 1 秒、2 秒、4 秒的指数退避。这个策略在大多数情况下是合理的但在 API 速率限制严格的环境下重试可能会加剧问题。我遇到过一次因为重试策略导致 API 配额快速耗尽的情况。当时模型 API 返回了 429 状态码请求过多paperclip 按照默认策略进行了 3 次重试每次重试都消耗了配额结果 3 个 Agent 在 10 秒内消耗了 9 次调用配额触发了更长时间的封禁。解决方法是调整重试策略。在.env中设置API_RETRY_MAX1和API_RETRY_DELAY5000把重试次数降到 1 次重试间隔增加到 5 秒。这样虽然单个请求的失败率会略微上升但整体配额消耗更可控。另外paperclip 支持配置多个 API 密钥轮换使用在.env中用逗号分隔多个密钥即可。这个功能在需要大量调用模型 API 的场景下能有效分散配额压力。6.4 监控与告警的简易搭建paperclip 本身没有内置监控面板但它的日志输出格式很规范方便接入外部监控系统。我使用了一个简单的方案用pm2的日志功能收集 paperclip 的输出然后用pm2-logrotate做日志轮转最后用一个定时脚本分析日志中的错误关键字发现异常时发送通知。关键的错误关键字包括model_api_error模型调用失败、tool_execution_timeout工具执行超时、agent_deadlockAgent 死锁、sse_connection_lostSSE 连接丢失。我设置了一个规则如果 5 分钟内model_api_error出现超过 10 次就触发告警。这个阈值是根据实际运行经验调整出来的太低会频繁误报太高会漏掉真正的故障。还有一个监控指标是 Agent 任务的平均完成时间。paperclip 会在每个任务完成时输出一条包含耗时信息的日志。我写了一个简单的脚本每小时统计一次平均耗时如果比过去 24 小时的平均值高出 50% 以上就说明系统可能出现了性能退化需要排查。7. 一些踩坑之后的个人体会paperclip 这个项目最让我欣赏的地方是它把 AI Agent 协作这个看起来很玄乎的概念落地成了一个可以看得见、摸得着、调得动的工程系统。它的可视化界面不是花架子而是真正能帮你理解 Agent 行为的工具。我在调试一个复杂的多 Agent 任务时就是通过观察可视化界面上的消息流发现了一个隐藏的循环依赖问题——两个 Agent 在互相等待对方的输出但谁都不肯先动。这个问题如果只看日志可能要花几个小时才能定位但在可视化界面上两个 Agent 之间的双向箭头一眼就能看出来。另一个让我印象深刻的点是 paperclip 对“约束”的重视。它没有追求让 Agent 变得无限智能而是通过角色定义、工具权限、输出格式这些约束把 Agent 的行为限制在一个可控的范围内。这个设计哲学在 AI 应用开发中其实很重要——一个行为可预测的 Agent比一个偶尔很聪明但经常失控的 Agent 更有实用价值。如果你打算在生产环境使用 paperclip我的建议是先从两个 Agent 的简单协作开始跑通整个流程后再逐步增加 Agent 数量和工具复杂度。我见过太多人一上来就定义五六个 Agent结果调试成本高到无法承受。另外一定要把 Agent 的定义文件和工具代码纳入版本控制因为 Agent 的行为会随着模型版本的更新而变化保留历史版本能帮你在出现问题时快速回滚。最后分享一个小技巧paperclip 的 Agent 定义文件支持环境变量插值。你可以在 YAML 文件中用${VAR_NAME}的形式引用环境变量这样同一份 Agent 定义可以在开发环境和生产环境使用不同的配置。比如把模型名称写成${MODEL_NAME}开发环境用便宜的模型生产环境用效果更好的模型切换时只需要改环境变量不用改 Agent 定义文件。这个功能在需要频繁切换模型进行对比测试时特别方便。