前段时间我被一个挺抽象的问题缠住当我把同一个需求分别丢给“规划”“编码”“审查”三个 Agent 时收到的往往是三份自说自话的答复没有一份能拼成完整可交付的结果。真正让我想明白这件事的是同时摸完 Codex 的命令行工作方式和 A2A 协议之后——所谓多 Agent 协作靠的不是给每个 Agent 塞更多提示词而是把任务拆出清晰边界再用协议把它们串起来。这篇文章就把我这段时间的观察、踩坑和实操记录下来适合正在调研多 Agent 落地、做 AI 编程工具选型或者想在内部服务里把 Agent 当“员工”编排的开发者。1. 多 Agent 协作到底在解决什么问题1.1 单 Agent 的瓶颈上下文、错误与权限都集中在一条链上单个 Agent 做长任务时问题往往不是“模型笨”而是结构上扛不住。以写代码为例一个 Agent 需要理解需求、读项目结构、改文件、跑测试、再根据报错调整这一整条链全靠同一个上下文窗口承载。任务一长前面读过的代码细节会被后面的对话冲淡模型开始“凭印象”猜接口改出来的代码风格不统一甚至为了满足某个过时假设反复打补丁。我把这种现象叫作“上下文漂移”它比幻觉更隐蔽因为单看每一步都合理合在一起却离原始目标越来越远。另一个被低估的问题是权限。单 Agent 要完成复杂任务就必须同时拥有读写文件、执行命令、访问网络等能力这意味着它在某个环节出错时破坏半径非常大。你可能只是让它改一行日志格式它却在理解偏差下重写了整个模块的公共方法。狭义的 Agent 本身没有“负责范围”概念它只知道“尽可能完成任务”。多 Agent 的初衷不是把多个模型堆在一起显得先进而是把一个大目标切成若干“认知工作单元”每个单元有独立的上下文、窄化的工具权限、明确的产出物以及一个可被其他单元消费的结果格式。这就像团队协作一个人再厉害同时负责需求分析、编码、测试、上线错误率必然上升真正有效的做法是设边界、定接口、分阶段验收。1.2 编排模式中心调度、管线串联与黑板式协作多 Agent 协作的常见模式有三类照搬任何一类都要结合场景判断。第一类是中心调度也叫“领导-下属模式”。一个主控 Agent 负责任务拆分、结果校验和下一步分配其他 Agent 只做被安排的事。优点是控制力强适合流程固定的场景比如“生成接口文档—生成代码—生成测试用例”缺点是主控 Agent 容易成为瓶颈一旦它拆分错误整个链路都歪掉。第二类是管线串联每个 Agent 只处理上一个 Agent 的输出。这种模式适合有明确先后顺序的任务但要注意每个环节的产出格式必须严格定义否则一个字段名变化都会让下游报错。我见过不少团队用“让每个 Agent 自由发挥”的方式做管线结果第一条就崩了——模型不擅长在无约束情况下保持接口稳定。第三类是黑板式协作多个 Agent 共享一个工作空间各自读写同一个任务看板或消息总线。它适合探索性强、子任务相互耦合的场景但对消息格式、冲突处理、任务认领逻辑要求极高。现实中多数企业服务落地还是从第一类和第二类开始因为心智负担小出问题也好追溯。不管用哪种编排真正决定协作质量的不是“谁更聪明”而是三个约定消息格式、上下文边界、终止条件。消息格式解决“一个 Agent 怎么让另一个 Agent 理解自己”上下文边界解决“每个 Agent 能看多少信息避免互相污染”终止条件解决“任务什么时候算完防止无限迭代”。这三点想清楚了用什么框架都是次要的。2. Codex 内部机制拆解单个 Agent 是怎么工作的2.1 Codex 不是代码补全工具而是一个自带工具集的自主 Agent在我用过的 AI 编程工具里OpenAI Codex 的定位比较特殊。它不是一个 IDE 插件式的补全工具而是一个跑在命令行里的自主编码代理。你给它一个自然语言任务它会自己决定看哪些文件、执行哪些命令、做哪些修改最后输出一份变更说明。它的工作循环大致是任务解析 → 生成计划 → 调用工具 → 观察结果 → 修正计划 → 重复直到满足验收条件。Codex 的工具集覆盖了写代码需要的几个基本动作读取文件、写入文件、执行 shell 命令、正则搜索、获取 URL 内容。这一组工具看似简单组合起来却很关键。比如拿到一个“升级某个依赖并修好兼容性问题”的任务Codex 会先读 package.json 和依赖使用位置然后执行升级命令再跑测试看报错最后根据报错逐文件修正。这个过程里上下文、工具输出、模型决策不断交替本质上是一个小型“感知-决策-行动”闭环。这里我觉得最有借鉴意义的是它的隔离机制。Codex 在 Linux 上通过沙盒限制工具执行范围在 Windows 上则依赖一个后台 daemon 来实现文件系统和进程隔离。它的设计思路是Agent 可以调用危险的命令但必须发生在受控环境里不能直接碰宿主系统。这个理念在企业的多 Agent 场景里非常重要——你不可能让每个 Agent 都直接在核心系统上执行命令隔离是所有安全和审计的前提。2.2 安装、登录与首次跑通把 Agent 先在本地“转”起来Codex 的安装对熟手来说很简单但对新手而言坑基本集中在环境依赖和认证上。我以当前最常见的 npm 安装方式为例列出完整步骤。环境上需要 Node.js 18 及以上最好再装好 Git。安装命令是npm install -g openai/codex安装完成后先初始化工作区codex initcodex init会生成一个codex.toml部分版本是config.toml和一份AGENTS.md。前者是运行配置后者是给 Codex 的项目说明文件相当于“按这份文档理解项目”。很多人在这一步跳过了AGENTS.md导致 Codex 对项目结构一无所知任务质量明显下降。接着是认证。登录 OpenAI 账号的方式是codex login命令会打开浏览器完成授权并把凭证写到本地配置目录。如果不想用账号登录也可以设置 API Key 相关的环境变量让 Codex 以 API 认证方式请求模型。两种认证方式对应不同的模型可用范围后面我会专门说这个坑。登录之后可以拿一个最小任务验证链路codex exec 在项目根目录创建一个 README.md内容包括项目简介和启动命令首次执行时Codex 会扫描项目结构、创建沙盒、启动执行环境然后按照自己的计划逐步操作。如果一切正常你会看到它先后调用读取目录、读取文件、写入文件等工具并附带简短的思考摘要。这一步跑通说明 Codex 本身工作正常后面再聊多 Agent 编排才有基础。提示不要把整个项目目录当成工作区喂给 Codex。尤其是带大量node_modules、构建产物、临时文件的项目最好把真正相关的代码目录单独初始化或者通过配置把无关目录排除掉。上下文越干净Agent 的计划越聚焦。2.3 配置与模型选型卡住过很多人的几个细节codex.toml的核心配置项不多但每一项都会直接影响行为。我常用的关键字段包括model指定使用哪个模型例如gpt-5.2-codex这类代码模型。model_provider指定模型提供方可以是 OpenAI 官方也可以是其他提供 OpenAI 兼容接口的服务用 API Key 方式接。approval_policy工具的许可策略决定哪些操需要人工确认。sandbox_mode沙盒模式决定命令是否在隔离环境执行。配置报错里最常见的一条是codex is ignoring 1 unrecognized configuration setting. check for typos这条消息几乎都是配置项写错了比如model拼成modle或者写了一个当前版本不支持的字段。建议逐字核对官方文档字段名不要想当然缩写。另外一条高频报错是the gpt-5.6-sol model is not supported when using codex with a chatgpt account意思是某个模型在“ChatGPT 账号登录”模式下不被支持。很多模型只允许通过 API Key 认证方式访问。遇到这种情况要么切换认证方式要么在配置里更换成当前账号可用范围内的模型。理解这个机制的关键在于账号登录和 API Key 是两套不同的凭证体系能访问的模型清单并不完全一样。再有一个跑 Codex 时容易忽略的点是日志。出问题不要瞎猜用codex exec --log-file codex.log 任务描述把日志导出来里面包含工具调用的详细记录和报错上下文。实际排查时我会先看日志里最后一次工具调用的输出再判断是模型决策问题还是环境问题。3. A2A 协议把单个 Agent 连接成企业服务网络3.1 为什么企业服务需要 A2AAgent 之间的“普通话”Codex 解决的是单个 Agent 怎么把任务做扎实但企业里的真实场景通常是多个 Agent 来自不同团队、跑在不同系统、由不同模型驱动。一个负责订单分析一个负责库存预测一个负责客服回复它们如果各说各话协同就无从谈起。A2AAgent2Agent协议解决的正是这个层面让不同 Agent 之间能互相发现、发任务、传结果就像企业内部服务之间通过统一接口互相调用一样。有个容易混淆的点MCP 和 A2A 经常被一起提。MCP 解决的是“Agent 怎么调用工具”它把外部工具封装成标准化的“能力接口”让 Agent 不用为每种工具单独写适配器。A2A 解决的是“Agent 怎么和另一个 Agent 对话”它的通信对象是另一个智能体而不是普通 API。可以这么理解MCP 是给 Agent 装插座A2A 是让两台电器互相听懂对方的状态信号。两者定位不同但可以叠加使用——A2A 连接 AgentAgent 内部再用 MCP 调用工具。对于企业内部服务A2A 的核心价值在于标准化。一个 Agent 只要实现了 A2A 的服务端接口暴露自己的 Agent Card其他 Agent 就能通过统一流程发现它、理解它的能力、给它下发任务、拿回结果。不用再为每个系统写一套私有 SDK也不用在 Agent 之间点对点拉群——这是架构层面的事情不是提示词层面的事情。3.2 A2A 协议核心概念Agent Card、Task 与 MessageA2A 协议里最需要理解的是三个概念。第一个是 Agent Card。它是每个 Agent 的“自我介绍文件”通常放在一个固定的 HTTP 路径上比如/.well-known/agent-card.json。内容包括 Agent 的名称、描述、技能列表、支持的任务类型、通信地址以及认证要求。其他 Agent 通过拉取这张卡片来判断“这个 Agent 能帮我做什么怎么联系它”。这就好比每个微服务都有服务注册信息Agent Card 就是 Agent 世界的服务注册表。第二个是 Task。A2A 里所有工作都是围绕 Task 进行的。一个 Task 有生命周期通常包括submitted、working、completed、failed、canceled等状态。任务创建后客户端可以轮询状态也可以通过流式方式接收进度更新。Task 之下的输入输出都封装为Message而 Message 的内容由Part组成不同类型的内容用不同 Part 表示比如文本、文件内容、结构化数据等。第三个是传输层。A2A 使用 HTTP 作为传输协议消息格式基于 JSON-RPC 2.0。也就是说通信过程是一系列带方法名和参数的结构化请求不是自由文本。这个设计非常关键企业网关、负载均衡、日志审计都能直接处理标准 HTTP 请求而不用为了 Agent 专门设计一套私有协议。在安全方面A2A 支持多种认证方式包括 OAuth 2.0、API Key 和双向 TLS。具体用哪种取决于内部环境的信任模型。我自己的建议是在同网段内部服务之间先用 API Key 或 mTLS 做身份校验跨组织协作时再上 OAuth 2.0。先跑通业务逻辑再逐步加强安全。3.3 最小 A2A 协作流程从 Agent Card 到任务下发一个最小的 A2A 调用流程可以拆成三步拉取 Agent Card、发送任务、轮询结果。假设有一个“编码审查 Agent”的卡片地址是https://agent.internal/review/card。客户端先请求这个地址拿到 Agent 的基础信息GET /review/card返回的 Agent Card 大概长这样只保留核心字段{ name: code-reviewer, description: 对代码变更进行静态审查并输出问题清单, skills: [code_review], endpoints: { path: /review } }然后客户端向https://agent.internal/review发送一个 JSON-RPC 2.0 请求创建一个 Task{ jsonrpc: 2.0, method: tasks/send, params: { taskId: task-001, message: { role: user, parts: [ { kind: text, text: 请审查 src/order_service.py 中 check_order 函数的异常处理 } ] } } }Agent 后台开始执行审查客户端可以轮询 Task 状态{ jsonrpc: 2.0, method: tasks/get, params: { taskId: task-001 } }直到返回状态completed且输出中包含审查结论。如果 Agent 支持流式推送客户端也可以改用长连接接收message事件但轮询永远是兼容性最好、最容易排错的方式。这个流程看起来简单但它是 A2A 的骨架。企业里无论把多少 Agent 接进来最终跑通的都是类似路径发现能力、下发任务、等待结果。把这条链路做稳定比给 Agent 增加多少高级能力都重要。4. 从 Codex 到 A2A我搭的一个多 Agent 最小闭环4.1 角色拆解与任务划分Planner、Coder、Reviewer理论讲完说点实际的。我用 Codex 作为执行型 Agent再用 A2A 协议把三个角色串起来搭了一个最小闭环。角色定义如下。角色核心职责输入输出Planner把自然语言需求拆成可执行任务需求文本结构化任务清单spec.jsonCoder按任务清单修改代码spec.json代码变更 diff 和说明Reviewer审查变更质量diff 和说明结构化缺陷清单review.json这里的关键点是每个角色的输入和输出都是结构化文件而不是一段自由聊天文本。我一开始犯过的错误是让 Planner 输出一段自然语言描述结果 Coder 每次理解都不一样审查结果也没法自动关联到具体代码行。改成 JSON 之后准确率和可追溯性立刻上了一个台阶。第二个关键点是每个 Agent 的上下文要严格隔离。Coder 不需要看完整需求背景只需要 spec.json 里的任务项Reviewer 不需要知道任务是怎么拆出来的只需要拿到 diff。这样每个 Agent 的上下文窗口都留给最重要的事也避免 A 角色输出的杂念污染 B 角色的判断。4.2 实现步骤Agent 注册、任务下发、状态轮询我用 Python 实现了一个最小调度器把三个 A2A 服务串起来。先给每个角色配置 Agent Card然后用 requests 库调用。核心流程的简化代码如下import requests import json def send_task(endpoint, task_id, text): payload { jsonrpc: 2.0, method: tasks/send, params: { taskId: task_id, message: {role: user, parts: [{kind: text, text: text}]} } } r requests.post(endpoint, jsonpayload, timeout30) return r.json() def wait_for_result(endpoint, task_id, max_poll30): status submitted for _ in range(max_poll): resp requests.post(endpoint, json{ jsonrpc: 2.0, method: tasks/get, params: {taskId: task_id} }).json() status resp.get(result, {}).get(status, {}) if status in (completed, failed, canceled): return resp raise TimeoutError(ftask {task_id} not finished after {max_poll} polls) # 1. 下发需求给 planner t1 send_task(planner_endpoint, plan-001, 把登录模块的会话过期时间改为15分钟) # 2. 等 planner 完成 r1 wait_for_result(planner_endpoint, plan-001) spec extract_text(r1) # 3. 把 spec 交给 coder t2 send_task(coder_endpoint, code-001, spec) r2 wait_for_result(coder_endpoint, code-001) code_diff extract_code_diff(r2) # 4. 把 diff 交给 reviewer t3 send_task(reviewer_endpoint, review-001, code_diff) r3 wait_for_result(reviewer_endpoint, review-001) review json.loads(extract_text(r3))这个调度器看起来很简单但它把“多 Agent 协作”真正落地了。每个角色由独立的 Codex 实例驱动通过 A2A 协议通信调度器只负责转发和状态判断不参与具体内容生成。在实际跑的过程中我发现wait_for_result里的轮询间隔很关键。间隔太短会给 Agent 服务造成无谓压力间隔太长任务链路延迟高。我最终采用了递增轮询策略前 5 次间隔 1 秒之后每次翻倍最多 30 秒。这样既保证响应及时也不会把服务打崩。项目里如果追求更快可以用 A2A 支持的事件流模式但轮询放在初期绝对够用而且排错时能看到每一步的请求响应非常直观。4.3 参数与上下文设计避免 Token 爆炸和“信息过载”多 Agent 编排里最常见的翻车点不是协议没通而是上下文没做好。我有一次把 Planner 的完整输出直接塞给 Coder再把 Coder 的全量日志塞给 Reviewer结果每个 Agent 都在处理大量与自身无关的信息模型的能力被稀释得厉害。从那以后我定了一条规矩传给每个 Agent 的内容只包含它能完成当前任务所必需的最小集合。具体来说Coder 只接收 spec.json 中与本次改动相关的任务项Reviewer 只接收 diff 文本和一份简短的“审查重点”。每个任务都设置超时和最大 token 上限防止某个 Agent 因为输入过大而进入低质量循环。另外还留了一个重要字段termination_condition明确告诉 Agent“任务在什么条件下算完成”。比如对 Coder终止条件是“所有任务项都有对应文件变更”对 Reviewer终止条件是“输出缺陷审查清单且每个缺陷关联具体文件行号”。没有终止条件多 Agent 极容易陷入无限自我修正。参数设置的参考值如下表具体按业务场景调整参数建议值说明单任务最大上下文8000 token 左右超过后自动拆分避免模型处理超长输入单 Agent 超时120 秒超过后标记失败交给上一层重新规划轮询初始间隔1 秒前 5 次使用之后递增Reviewer 输出大小不超过 5 个缺陷条目结构清晰便于自动复核5. 实操中反复出现的坑和排查思路5.1 Codex 安装与启动常见问题速查表我整理了一份高频问题速查表都是实际跑 Codex 时经常遇到、也最容易被搜索引擎带偏的问题。报错或现象可能原因处理方式codex auth token is unavailable未登录或认证凭证失效执行codex login重新授权确认会话有效start the windows daemon from a non-elevated terminal; shared...Windows 沙盒 daemon 启动方式不正确用非管理员权限的终端重新启动 Codex再跑任务codex is ignoring 1 unrecognized configuration setting配置文件字段拼写错误逐字检查codex.toml字段名删除未知配置项model X is not supported when using codex with a chatgpt account当前模型不支持账号登录认证仅支持 API Key切换认证方式或改用账号可访问的模型任务执行到一半卡住沙盒内命令等待输入或工具权限策略阻塞查看日志定位最后调用调整approval_policy输出结果偏离项目上下文AGENTS.md没有写清楚项目约束在AGENTS.md补充模块结构、代码风格、禁止改动目录等信息排查这类问题我一般先做三步第一步看错误信息里有没有具体的配置字段名第二步看codex login的认证状态第三步把日志导出来看最后一次工具调用的输出。大部分问题都能在这三步里定位。5.2 A2A 集成中的坑从 Agent Card 到任务状态A2A 集成看起来标准但真正落地的坑不少。我踩过的比较典型的有几个。第一个是 Agent Card 路径不一致。有的 Agent 实现把卡片放在/card.json有的放在/.well-known/agent-card.json如果客户端发现逻辑写死就会失败。解决方法是把 Agent Card 地址作为服务注册信息统一登记在内部服务目录里避免客户端自己猜路径。第二个是任务状态永远停在submitted。这通常不是协议问题而是服务端没有真正把任务放进执行队列。很多初版 Agent 只实现了tasks/send的接口壳没有接后台任务处理逻辑。排查时直接看服务端日志有没有收到任务、有没有触发执行线程。第三个是消息重试导致重复执行。企业网络环境中HTTP 请求可能因为超时重发同一个 Task 被 Agent 执行两次。我会要求所有 Agent 对taskId实现幂等处理如果收到一个已执行过的任务直接返回上次的结果而不是重新跑一遍。这是一个成本低但收益极高的设计。第四个是内网网络设施不支持长连接。如果企业网关或者负载均衡不支持长时间 HTTP 流式响应建议直接放弃事件推送改走轮询。不要为了“实时性”牺牲链路稳定性在多数业务场景里轮询间隔 2 到 5 秒完全够用。5.3 一条实用的多 Agent 调试验证路径多 Agent 系统出问题时最忌讳直接看全链路日志因为变量太多。我习惯按下面这条路径逐步验证。第一步验证单个 Agent。直接对 Codex 下发一个靠近真实任务的小任务确认它在独立环境下能稳定完成。如果这一步都不稳定问题在模型或提示词不在编排。第二步验证协议层。用 curl 或 Python 直接向 Agent 的 A2A 端点发送tasks/send确认请求能到达、任务能启动、结果能返回。这一步可以绕开调度器单独排查协议实现。第三步验证两个 Agent 之间的链路。先接 Planner 和 Coder用固定输入跑三个用例确认 spec 的格式能被 Coder 稳定消费。再接入 Reviewer确认审查结果能结构化返回。第四步才是全链路验证。全链路测试时我会给每个任务加一个trace_id贯穿规划、编码、审查、汇总全过程日志里带上这个标识一旦出问题可以快速过滤出全部相关环节。这已经是分布式系统调试的基本功了放到多 Agent 场景里同样适用。多 Agent 协作这块内容后续还可以扩展的方向很多比如给每个 Agent 配独立的日志和审计、把任务结果存成可回放的记录、或者把 A2A 网关与服务网格打通。我个人在实际操作中的一个体会是多 Agent 系统最大的隐患往往不是模型能力不足而是角色之间的接口约定太随意。Codex 让我看到了单个 Agent 可以多可靠A2A 让我看到了多个 Agent 可以多好地组合但把它们真正连起来的还是那几条朴素的设计规则——明确边界、约定格式、控制上下文、留好日志。最后再分享一个小技巧不管用什么框架给每个 Agent 写一份固定的 AGENTS.md 或系统提示词把“不做什么”写得比“要做什么”还要详细效果比叠加任何花哨提示词都明显。