去年底我接手了一个代号为 Agency Agents 的项目。这串英文名当时吓退过不少人,听得最多的问题是:Agency 是代理的意思,Agents 还是代理,叠在一起到底想干什么。等我把第一版跑通,再回看这个名字,反而觉得它概括得很准:这不是一个单独的工具,而是一组可以按需组合、协同工作的编程智能体集合,背后需要一整套运行时和平台抽象层,才能在不同操作系统、不同开发环境里稳定运转。
Agency Agents 要解决的真实痛点很直接:单个大模型写代码的 Demo 已经够多了,但一旦要放进真实项目,面对不同用户的终端环境、不同操作系统的路径规则、不同权限体系,绝大多数单体 Agent 方案会迅速失效。“跑得通”和“能落地”之间,差的正是跨平台适配、任务编排、工具调用安全这一整套工程化内容。所以这篇文章不只是介绍这个概念,而是把我从架构设计到工程落地全程的关键决策、核心代码组织、踩过的坑都拆出来。如果你正在做 AI 编程助手、本地自动化 Agent,或者想设计一套可插拔的智能体插件系统,这里的思路可以直接参考。
1. 项目背景与核心设计思路
1.1 什么是 Agency Agents:从“单个智能体”到“智能体生态”
先给这个概念划一条明确的边界。Agency Agents 本质上是一个项目代号,描述的是一组有明确分工、能互相协作的 AI Agent 集群。常见角色包括代码生成者、测试执行者、静态扫描者、文档维护者、命令执行者等。它们共享同一个运行时,通过统一协议交换消息和工具调用结果,最终对外表现为一个“跨平台 AI 编程智能体生态”。
这个名字里的 Agency 强调的不是网络代理,而是“代理处”这种组织形式。你可以把整个系统想象成一支开发小队:有人负责写代码,有人负责跑测试,有人负责查日志,有人负责收尾清理。每个 Agent 都是小队的成员,单看能力都不算全能,但组合起来能覆盖一个完整任务的闭环。单体 Agent 更像“全栈超人”,看起来什么都能做,一旦遇到环境差异、上下文超限、任务过长,就会变成谁都要管的瓶颈;而多 Agent 生态把复杂度拆到不同角色上,每个角色可以被单独替换、单独测试、单独升级。
这个设计也决定了我们后续所有的技术选型:Agent 之间不能硬编码调用,而是通过“意图”和“事件”通信;每个 Agent 只暴露自己擅长的工具接口;任务调度层负责拆解、分发、汇总。这样一个生态才能做到可插拔,否则就只是把一堆函数堆在一起,仍然不是 Agent 体系。
1.2 为什么跨平台是刚需:从单机脚本到多环境协作
很多人最开始不理解为什么要强调“跨平台”。我当时的判断是:如果一套 Agent 生态只能在开发者自己的笔记本上跑,那它就没有完成工程化的使命。实际落地时,同一个 Agent 编排很可能要出现在三类场景里:
- 用户在自己的桌面环境里通过命令行或编辑器插件调用;
- 团队在共享服务器上跑批量代码分析;
- CI 流水线里自动执行失败用例分析。
这三类环境的操作系统、终端、文件权限和可用命令完全不同。桌面环境可能是图形化系统,路径用反斜杠或正斜杠、换行符也不一样;服务器环境普遍是精简安装,很多常用命令不一定存在;CI 环境大概率是容器,默认没有图形界面,环境变量和用户权限也都不同。如果 Agent 直接拼装 shell 命令,同样的pytest tests/在不同平台上可能写法一样,但一旦涉及路径传参、环境变量注入、文件查找,差异立刻暴露。
跨平台抽象不是给每个平台写一份业务逻辑,而是把系统差异统一收敛到一个适配层,业务 Agent 只跟“读文件”“写文件”“执行命令”“解析路径”这类抽象能力打交道。这样当新平台接入时,只需要新しい适配器实现,不用改任何 Agent 业务代码。这个思路是整个 Agency Agents 架构的基础,也是我踩过大量坑之后最想强调的一点。
1.3 从单体脚本到生态:架构演进的三次重构
Agency Agents 不是一开始就长这样,前后经历了三次比较大的重构。
第一版是“单体脚本”。所有工具函数、模型调用、命令执行都写在同一个 Python 文件里,大概三千行。Demo 阶段很好用,往终端里输入一个任务描述,脚本就能生成一段代码并尝试运行。但问题很快出现:新增一个 Agent 能力就要改主流程;模型返回一个意外格式,整个任务就中断;想分析失败原因只能靠print满天飞。
第二版是“多 Agent 消息队列”。我把不同能力拆成独立 Python 服务,通过进程间消息通信联动。职责清晰了一些,但跨平台问题散落在每个 Agent 里,路径处理逻辑复制了三份,有一处不一致就会出现诡异问题。这让我意识到,缺少一个统一抽象层,所谓“多 Agent 协作”就是一句空话。
第三版就是我接下来要展开的架构:引入平台适配层、工具协议、会话上下文和插件注册机制。Agent 变成纯逻辑模块,不直接触碰操作系统细节;外部操作全部走工具层;平台相关代码只在适配器里出现。这次重构之后,新平台接入成本从改几十处降到只写一个适配器,新 Agent 扩展从改主流程降到新增一个文件。架构的收益是长期才能看出来的,但这次重构从第三天开始就明显减少了拉扯。
2. 总体架构设计:分层与模块拆解
2.1 分层模型:入口、编排、能力、基础设施
第三版架构按四层设计,每层职责单一,不互相越权。
| 层级 | 核心职责 | 主要模块 |
|---|---|---|
| 入口层 | 对接用户和外部系统 | 命令行工具、编辑器插件适配、HTTP 服务 |
| 编排层 | 管理任务、会话、Agent 路由 | 任务调度器、会话管理器、上下文缓存 |
| 能力层 | 实现具体智能体能力 | 代码生成 Agent、测试 Agent、文档 Agent |
| 基础设施层 | 屏蔽平台差异、控制权限、记录日志 | 平台适配器、工具沙箱、结构化日志 |
入口层解决的是“用户从哪进来”。同一个任务从终端发起和从编辑器插件发起,参数和反馈形式都不一样,但编排层接收到的应该是一份标准化任务描述。所以入口层只做格式转换,不拼装业务逻辑。
编排层是整个系统的心脏。它负责拆解用户意图,把大任务变成小步骤,决定哪个 Agent 先跑、哪个 Agent 后跑,以及整个任务是否已经收敛。它同时管理会话上下文,保证多轮对话和长任务有记忆。
能力层的 Agent 是纯逻辑模块。每个 Agent 接收一张任务卡,返回一份结果卡。它们不直接创建进程、不直接读写文件系统,所有动作都通过调用工具接口完成。这一条看似简单,却是后期安全和调试的基础。
基础设施层是跨平台的落点。它把路径解析、命令执行、环境变量、文件读写这些系统相关操作全部包起来,向上提供一个稳定接口。日志、指标和权限校验也放在这一层,确保整个生态可观测、可控。
2.2 跨平台抽象层:一套接口,三端适配
跨平台抽象层最核心的是一个很小的接口集合,我们称之为 PlatformAdapter。它只定义十来个方法,但所有业务代码都必须走这些方法。
class PlatformAdapter: def resolve(self, path): ... def read_text(self, path): ... def write_text(self, path, content): ... def execute(self, cmd, cwd, env, timeout): ... def exists(self, path): ... def list_dir(self, path): ...resolve 是所有路径操作的统一入口。它把上层传来的路径字符串改成当前平台的绝对路径,并做规范化处理,防止..路径穿越。read_text 和 write_text 负责文件读写,内部统一处理编码和换行符。execute 负责创建子进程,它接收的是一个参数列表而不是 shell 字符串,从根本上规避了 shell 语法在不同平台的差异。
我最想强调 execute 的入参设计。如果你给 Agent 一个“执行命令”的字符串参数,Agent 为了适配不同平台就必须自己判断 shell 类型、拼接引号、处理转义,这是灾难。让 Agent 和用户都传参数列表,平台适配器负责把参数列表转换成当前系统能执行的进程调用,业务逻辑就能彻底和 shell 解耦。比如要运行python -m pytest tests/,上层传的就是["python", "-m", "pytest", "tests/"],适配器在原平台用默认方式执行,在某些需要包装 shell 的环境里再内部处理,上层完全不感知。
2.3 会话上下文与记忆管理
AI 编程智能体和普通脚本最大的区别在于有状态。多轮对话、连续修改、逐步执行都要求系统记住“之前发生了什么”。但大模型的上下文窗口是有限的,直接无限积累历史消息会让程序越来越慢、越来越贵,最后报错。
Agency Agents 的会话管理分三层。第一层是全量会话存储,记录每次请求和响应的原始内容,方便审计和复盘;第二层是短期上下文,给模型用的最近若干轮消息;第三层是任务摘要,系统每隔一段时间把已执行的动作归纳成一段简短的进度总结,存进上下文,替代被裁剪掉的老消息。
我实际采用的参数策略是:如果模型上下文窗口按 token 计算,把总预算分成三份——输入历史占一半,工具返回结果占两成,模型输出预留三成。假设一个模型单次请求支持 32768 token,那么输入历史大约留 49152?不对,这里要重新计算。32768 的百分之五十是 16384,工具结果占 6554,输出预留 9830。这组数字只作为保守基线。真正做的时候还要根据模型实际最大输出限制再调整。只要发现某次工具返回超过几千 token,就不再原样塞进上下文,而是把结果写入工作目录的临时文件,让 Agent 拿到文件路径和头部摘要。这个做法让长任务稳定性提升非常明显。
2.4 多 Agent 协作与任务编排
多 Agent 协作不是简单地把多个 Agent 跑一遍,而是通过一套消息结构把任务拆开、分发、汇总。消息格式大致是:
{ "trace_id": "abc123", "sender": "dispatcher", "receiver": "code_writer", "intent": "generate_code", "payload": { "task_id": "t-42", "description": "实现一个跨平台文件扫描函数" } }每个 Agent 关注 receiver 和 intent。不匹配的消息直接忽略,避免互相打扰。任务调度器根据意图和当前状态决定下一跳。比如用户说“帮我修复测试失败”,调度器把任务分配给 code_reviewer 先读失败日志,再由 command_executor 重现失败,然后 code_writer 修改代码,最后反过来通知 dispatcher 重新跑测试。这样形成一个闭环。
协作过程中必须限制单次任务的迭代次数。我见过很多死循环案例:Agent 修完代码发现测试还是挂,继续修,又修坏了另一个测试,无限循环。给每个编排任务加一个max_iterations=5的上限,达到上限后强制让用户决定是继续还是停手,虽然简单但能保住整个系统的可用性。
3. 核心模块实现与工程实操指南
3.1 插件化 Agent 注册机制
为了让生态可以持续扩展,Agency Agents 内部做了一个非常朴素的插件注册表。每个 Agent 模块暴露一个装饰器,调度器启动时会扫描指定目录下所有 Python 文件,自动加载注册过的 Agent。
# agents/registry.py AGENT_REGISTRY = {} def register_agent(name): def decorator(cls): if name in AGENT_REGISTRY: raise ValueError(f"agent name duplicated: {name}") AGENT_REGISTRY[name] = cls return cls return decorator使用起来很直接,新 Agent 文件里写一个类,再加上装饰器:
# agents/code_writer.py @register_agent("code_writer") class CodeWriterAgent: def run(self, task, context): ... return result注册机制的核心价值是“约定大于配置”。新 Agent 无需改动任务调度器,只要遵循统一的run(task, context)接口签名,就能被加载。这要求所有 Agent 必须严格遵守输入输出结构,不能偷偷返回自定义对象。我们在工程中加重了协议校验,Agent 返回值如果缺少必填字段则直接报错,防止某一次上线把全链路带崩。
动态发现目录也要小心控制。不要让调度器去扫描整个全系统目录,而是限定在白名单目录内,避免从某个临时目录加载恶意模块。生产环境我们还对插件目录做了 Hash 校验,防止文件被动过。
3.2 工具调用协议与权限沙箱
Agent 生态最敏感的部分是工具调用。一个能执行命令、读写文件、安装依赖的 Agent,如果不设权限边界,本质上就是让大模型拿到了“万能执行器”。Agency Agents 把所有外部操作都收敛成 Tool 对象,Agent 不能直接调用操作系统 API,只能调用工具层提供的统一操作。
工具接口定义大致如下:
class Tool: name: str async def run(self, params, context) -> ToolResult: raise NotImplementedError调度器在每次 Agent 调用工具之前,会经历一次权限检查。权限规则按“默认拒绝,白名单放行”的原则设计。命令执行工具只允许执行白名单里的命令,例如git、python、pytest、rg;所有被禁止的命令直接返回拒绝结果。文件工具同样受限,每个任务被分配一个独立工作目录,工具内部验证目标路径必须位于该目录之下,越权访问一律拒绝。
这里有一个容易被忽略的坑:路径校验不能只做字符串前缀判断。/workspace/task1/../task2/secret.txt的前缀看起来在 task1 下面,实际打开的是 task2 的文件。必须先把路径标准化,再判断最终路径是否在允许目录内。这个逻辑我们在安全攻防演练中反复验证过,属于必改项。
3.3 跨平台进程与终端适配细节
命令执行是所有跨平台问题里最集中、最容易翻车的部分。我曾经遇到一种情况:同一个命令在调试阶段正常,打包之后莫名失败,最后定位到原因是执行器内部用了字符串拼接,不同系统的引号转义规则不一样。
现在我们的所有命令执行都用参数列表模式,禁止使用 shell 字符串执行。
import subprocess proc = subprocess.run( ["python", "-m", "pytest", str(test_path)], cwd=str(workspace), env=merged_env, capture_output=True, text=True, timeout=30, )这个写法有四个好处:不需要本地 shell 参与,减少了命令注入面;命令分割逻辑由系统正确处理,空格、引号、特殊字符不再是问题;超时控制明确;捕获输出时编码可控。不要写"VAR=value command"这种 POSIX 风格的环境变量赋值,在部分平台上完全无法运行。正确做法是把环境变量合并进env参数。
输出编码也要统一处理。大模型返回的内容几乎都是 UTF-8,但如果被调用的脚本输出 GBK 或系统默认编码,text=True时解码就会报乱码。我们统一给子进程设置encoding="utf-8",同时在启动环境里加上和 UTF-8 相关的环境变量,不让系统区域设置影响解析结果。如果遇到程序强制输出其他编码,就在适配器里做一次字节转码,而不是依赖默认行为。
3.4 日志、观测与失败恢复
分布式 Agent 体系如果没有可观测性,出了问题等于盲人摸象。Agency Agents 在日志层面做了一件简单但有效的事:所有日志都必须携带 trace_id、session_id、agent_name 三个字段。
{"time": "2025-01-12T10:22:31Z", "level": "INFO", "trace_id": "t-42-abc", "session_id": "s-88", "agent": "command_executor", "msg": "run cmd: ['pytest', 'tests/test_scan.py']", "duration_ms": 254}每条日志统一输出为 JSON 一行,方便后续用日志工具检索。排查问题时,只要拿到一个 trace_id,就能把所有 Agent 的动作串成一条完整链路,一眼看出卡在哪个环节。这个习惯看起来多写了几行代码,但真的能救命。
失败恢复采用检查点机制。每个 Agent 在执行前先写一条检查点,记录当前任务状态、依赖条件、已完成步骤;执行完成后更新检查点。调度器如果发现 Agent 进程崩溃或者网络超时,会读取最近的检查点,从断点继续而不是从头开始。重试时采用指数退避策略,第一次等 1 秒、第二次等 2 秒、第三次等 4 秒,不把压力继续压到模型服务和本地进程上。
4. 工程落地与部署实践
4.1 仓库结构与配置设计
一个可以落地的项目,仓库结构必须一眼可以看出“哪里有新的 Agent、哪里改适配器、哪里看日志”。Agency Agents 的目录是这样的:
agency_agents/ agents/ # Agent 模块,插件化发现 tools/ # 工具实现:命令执行、文件读写 adapters/ # 平台适配器实现 runtime/ # 调度器、会话管理、权限中心 entrypoints/ # CLI、编辑器插件适配、HTTP 服务 configs/ # 配置文件模板 workspaces/ # 任务工作目录 logs/ # 运行时日志配置文件采用 YAML 格式,核心示例:
model: endpoint: ${MODEL_ENDPOINT} max_tokens: 4096 runtime: workspace_root: ~/.agency_agents/workspaces default_timeout: 30 max_iterations: 5 tools: allowlist: ["git", "python", "pytest", "rg"] agents: enabled: ["code_writer", "code_reviewer", "command_executor"]配置里绝不写明文密钥。模型 API 密钥、数据库密码这类信息全部通过环境变量注入,配置文件里只保留占位符。项目里所有日志输出前会经过一层脱敏过滤器,把看似密钥的字符串替换成***,防止有人在调试时不小心把密钥打出来。
4.2 多平台构建与发布
跨平台程序的发布策略,我总结成一句话:能依赖纯 Python 版本库尽量用纯 Python 版本,少碰需要本地编译的扩展。大部分流行库会提供预编译包,但部分性能敏感的库在不同平台可能需要额外配置。为保证 Agent 能在更多环境中快速安装,我们把相对路径处理、文本解析等操作全部用标准库实现,只有确实有性能需求的地方才引入外部依赖。
发布物可以做成几种形态:命令行程序通过入口脚本暴露;编辑器插件端发布轻量级客户端;CI 场景发布容器镜像。容器化的最大好处是环境一致性,命令、权限、路径都是可控的,很多本地平台差异被容器层屏蔽。但容器也有局限,比如用户要访问本机文件、本机 Git 配置时,挂载和权限处理反而更复杂。因此容器主要用于服务端批处理,本地交互场景还是由平台适配器负责。
4.3 性能指标与质量基线
跨平台 Agent 生态需要一套明确的质量基线,否则很容易在“能跑”和“好用”之间摇摆。我们常用的指标如下:
| 指标 | 目标值 | 监控方式 |
|---|---|---|
| 启动时间 | 小于 2 秒 | CLI 入口记录 |
| 单次工具命令超时 | 默认 30 秒 | 子进程超时 |
| 上下文使用率 | 不超过 80% | 会话管理器统计 |
| 任务完成率 | 大于 90% | 调度器上报 |
| 未授权工具调用率 | 0 | 权限中心统计 |
性能优化时最值得投入的是“减少无效模型调用”。很多任务其实不需要大模型参与,比如执行一次pytest、读取一个文件内容,完全可以用确定性代码完成。Agency Agents 里默认动作是“先看有没有必要调模型”,能用工具逻辑完成的,绝不浪费模型调用。这一条既降延迟,又省钱,还能提高稳定性。
4.4 影响范围与落地形态
Agency Agents 做成之后,我们实际接了几个不同的业务场景。第一个是编辑器内嵌代码助手:用户选中一段代码,Agent 生态自动拆解成“读取选中内容—生成修改建议—在临时工作区验证—输出 diff”,全程跨平台行为一致。
第二个是命令行故障排查工具:运维人员描述一句现象,比如“磁盘占用突然升高”,调度器会把任务分给文件扫描 Agent 执行查找大文件、定位最近生成的临时文件、检查进程列表,最终汇总成结构化报告。
第三个是 CI 失败分析。原来每次流水线挂了,都要人工打开日志找原因。现在把失败日志直接交给日志分析 Agent,它先复现编译命令,再定位错误段落,随后把修复建议推到消息里。这个场景对并发要求不高,但跨平台稳定要求极高,因为 CI 环境经常清理缓存、权限受限,平台适配层在这里发挥了真正价值。
Agency Agents 的价值不只是“能自动改代码”,而是把 AI 能力变成了工程基础设施的一部分。不同的团队可以在同一套生态上接入自己的 Agent、工具和白名单策略,形成各自场景下的智能体工作流,同时不需要重复造基础设施。
5. 常见问题排查与避坑实录
5.1 “能跑但不稳定”:路径问题
最常见的不稳定来自相对路径。开发者在调试时工作目录恰好是项目根目录,所有路径都正常;打包或换目录执行后,Agent 读不到配置文件,生成的文件也找不到。Agency Agents 规定所有进入业务层的路径都必须是绝对路径,由适配器通过resolve统一处理。排查时看路径是绝对还是相对,通常一眼就能定位问题。
我在某次调试中遇到过:Agent 生成一个output.txt到当前目录,看起来成功了,但后续 Agent 根本找不到它。原因是执行时进程的工作目录被切换到了临时沙箱,和调度器当时记录的工作目录不一致。解决办法是让 Agent 显式传递目标路径给工具,而不是依赖“当前目录”这个隐式状态。这也是跨平台系统里比较隐蔽的坑。
5.2 跨平台边界问题:换行符、编码、命令差异
跨平台最容易出现的三类边界问题是换行符、默认编码和 shell 语法。换行符问题主要影响文本对比和 diff 生成,处理方法是所有文本写入统一使用\n,只在对外输出给不同平台时再转换。默认编码问题就是 3.3 节提到的子进程编码设置,在适配器层强制 UTF-8。shell 语法差异是最危险的,一旦出现“开发环境能跑、测试环境挂掉”的情况,优先怀疑有人绕过了参数列表模式,直接拼了 shell 字符串。
5.3 上下文爆炸:长任务和代码库扫描
代码库扫描是最容易触发上下文爆炸的场景。一个仓库可能有几千个文件,Agent 如果试图把每个文件内容都装进上下文,再大的窗口也不够用。我们的处理方式是:扫描类工具只返回文件路径、大小、扩展名和首行摘要;真正需要分析内容时,先过滤再读全文。同时给每个上下文窗口设置了硬上限,超过之后强制触发摘要压缩。发生过一次线上任务因为读了一个 10 万行的日志文件,把模型请求直接打爆;修复方式是工具层对读取文件大小设置了阈值,超过 200KB 不再允许直接读全文,而是分片读取或拒绝。
5.4 一次误删文件与命令注入教训
印象最深的一次事故是这样的:一个代码扫描 Agent 读到了仓库 README 里的一段恶意示例命令,里面包含删除操作。由于当时命令执行工具的白名单制度还不严格,Agent 把示例当成了真实指令,尝试执行,幸好目标路径被工作目录限制挡住,没有造成实际损失。但这已经足够敲响警钟。
后来我做了几件事:所有工具默认拒绝除白名单外的命令;Agent 想新增命令必须由用户在配置里明确打开;涉及删除、覆盖、安装这类高影响操作,一律先返回“需要人工确认”状态,由用户点了确认才真正执行。大模型本身没有恶意,但它会误解内容、会被输入里的恶意片段诱导,权限沙箱就是我们和事故之间的最后一道墙。
5.5 排查问题速查表
| 问题现象 | 直接原因 | 处理方案 |
|---|---|---|
| 同一条命令在不同系统结果不一致 | 内部使用了 shell 字符串 | 改为参数列表模式 |
| 中文输出乱码 | 子进程编码未固定 | 统一 UTF-8 并设置环境变量 |
| Agent 重复修同一处死循环 | 缺少迭代上限 | 配置 max_iterations |
| 模型上下文持续增长崩溃 | 工具输出全部塞进上下文 | 长输出写临时文件,只传摘要 |
| 找不到配置文件 | 依赖相对路径 | 用适配器 resolve 成绝对路径 |
| Agent 删除了不该删的文件 | 权限校验失效 | 默认拒绝、白名单、路径标准化 |
| 任务卡死 10 分钟不返回 | 子进程没有超时控制 | 设置 timeout 并 kill 超时进程 |
| 日志难以追踪跨 Agent 调用 | 缺少 trace_id | 所有日志带 trace_id 全链路检索 |
6. 实践经验与扩展建议
6.1 架构落地时最重要的三条铁律
跨平台 AI 编程智能体生态做了三轮重构之后,我总结出三条铁律。第一条是接口隔离:Agent 永远不直接触碰操作系统,所有文件、进程、环境变量都通过适配器访问。第二条是最小权限:默认拒绝一切外部操作,只有明确需要的工具才放开,高影响操作必须人工确认。第三条是可观测性:没有 trace_id、没有检查点、没有结构化日志的 Agent 体系基本不可维护,上线前先把观测做扎实。
这三条顺序不能乱。先有接口隔离,才能保证权限控制不绕路;先有权限控制,才能保证可观测数据可信。如果一个 Agent 绕过工具层直接调子进程,那日志再全也看不到真实动作,安全策略形同虚设。
6.2 可以继续扩展的方向
Agency Agents 目前的形态可以让很多场景快速落地。后续我觉得比较有潜力的扩展方向有几个:一是把任务编排升级成真正的 DAG 引擎,支持条件分支、自动重跑和并行分支;二是接入本地知识库检索,让 Agent 在修改代码前先搜索项目里的历史约定;三是增加多模态输入,比如把设计稿截图、报错弹窗直接交给视觉 Agent 分析;四是把审批流程和 Agent 执行集成得更紧密,形成“Agent 建议、人确认、Agent 执行”的闭环。
最后说一句我个人想强调的体会:不要把智能体当作一个黑盒“神仙函数”来写,把它当成一个带权限、带状态、带日志的微服务来设计。当你用这个心态去做跨平台 AI 编程智能体生态时,很多所谓的技术难点,其实在架构层面就被消解了。Agency Agents 只是这个概念下的一个具体工程样本,但它验证了一条路:AI Agent 要真正成为生产力工具,工程化设计和跨平台能力跟模型能力同等重要。