AAMP 协议详解——把邮箱变成 Agent 的异步任务网络
本文为「AI Agent 技术系列」第 10 篇。MCP(第 3 篇)解决”Agent 如何接入工具与数据”,A2A(第 8 篇)解决”独立 Agent 之间如何协作”,ACP(第 9 篇)解决”编辑器与编码 Agent 之间如何通信”。AAMP 补上第四个方向:当 Agent 无法暴露公网端点时,平台如何把任务异步派发给它,并把结果回写回来。
让两个 Agent 通过 HTTP 端点通信并不难。A2A 已经把这套交互约定标准化了:Agent Card 描述能力,Task 跟踪工作,Artifact 交付结果。但这套模型有一个隐含前提——执行方必须能暴露一个公网可达的 HTTP 端点。
这个前提在很多真实场景里不成立。Agent 跑在本地沙箱里、跑在厂商托管的运行时里、跑在内网某台不能对外开放的机器上。平台想把任务派给它,要么靠脆弱的胶水服务,要么靠私有 API 适配,最后往往退化成对某个中心化平台的强依赖 [1]。
AAMP(Agent Asynchronous Messaging Protocol)要解决的就是这个问题。它是飞书/Lark 团队开源的开放协议,核心思路是:给每个 Agent 一个邮箱地址,把普通邮箱变成 Agent 之间的异步任务网络 [1][2]。邮箱身份解决”怎么找到这个 Agent”,AAMP 在其上补一层协作语义——一组小而统一的 intent 词汇、机器可读的头字段、以及可移植的发现模型,让 Agent、工作流系统和人工操作员无需共享同一个运行时,就能完成协调协作 [1]。
本文以当前稳定的 AAMP 1.1 为基准,讲清它的架构、核心概念、信任模型与生态工具链,再单列一节与 A2A、ACP 做对比,给出落地建议。除特别说明,方法名与字段以官方规范为准 [2]。
一、AAMP 是什么:把邮箱变成 Agent 的异步任务网络
官方定义与本文版本
AAMP 是 Agent Asynchronous Messaging Protocol 的缩写,是一个以邮箱为原生控制面的异步任务协作协议,用于在独立 Agent 运行时之间完成任务派发、执行、人工升级与结果交换 [2]。它结合了三个现有标准 [1]:
- SMTP:负责可靠的消息投递;
- JMAP:负责邮箱同步、推送和附件获取;
- X-AAMP-* 结构化头:负责机器可读的任务生命周期表达。
本文以 AAMP 1.1 为基准。规范主文档见仓库内的 docs/AAMP_CORE_SPECIFICATION.md [2],SDK 能力对齐情况见 docs/SDK_CAPABILITY_MATRIX.md [1]。示例中的邮箱地址和任务 ID 仅用于说明结构,不代表可调用的服务。
什么时候 HTTP 端点不够用
把一个 Agent 包装成 A2A Server,是合理的集成方式。A2A 的任务生命周期、流式推送、webhook 通知都已经标准化得很好。但”帮我审查这个 PR”或”把这个需求拆成子任务”不一样:执行方可能是一个跑在本地的 Codex 实例,或者一个托管在厂商运行时里的 Claude,它们都没有公网入口。
两类交互的侧重点可以这样理解 [1][3]:
| 维度 | A2A 的 HTTP 端点模型 | AAMP 的邮箱线程模型 |
|---|---|---|
| 执行方需要暴露什么 | 公网可达的 HTTP URL | 一个邮箱地址 |
| 任务如何传递 | HTTP POST 到端点 | SMTP 发送邮件 |
| 结果如何回传 | HTTP 响应或 webhook 推送 | SMTP 回复到同一线程 |
| 长任务如何跟进 | SSE 流式或 webhook 推送 | JMAP 推送或轮询 |
| 适用场景 | 执行方有公网入口,需要实时交互 | 执行方无公网入口,任务天然异步 |
这不是说 A2A 做不了异步——A2A 的 webhook 推送和 returnImmediately 都支持异步场景 [3]。问题在于,webhook 仍然要求执行方能接收来自外部的 HTTP 请求。如果执行方连入站 TCP 连接都开不了,webhook 也无从谈起。
AAMP 把这个问题绕过去了:邮箱地址是全局可路由的,SMTP 投递是去中心化的,任务线程天然持久化在邮箱里。执行方只需要能发邮件和收邮件,就能参与协作。
一个直观的协作场景
以 Meego 需求自动生成代码包为例 [4][5]:产品经理在 Meego 工作项里点击”生成代码包”,Meego 作为 dispatcher 向 Codex Agent 的邮箱发送一封 task.dispatch 邮件;Codex 读取需求描述和附件,生成实现代码、说明文档和测试用例,然后通过 task.result 邮件把结果回写到原工作项。
sequenceDiagram
participant PM as 🧑💻 产品经理
participant Meego as 📋 Meego<br/>Dispatcher
participant Codex as 🤖 Codex Agent<br/>Executor
participant Mail as 📧 邮箱基础设施
PM->>Meego: 点击"生成代码包"
Meego->>Mail: task.dispatch 邮件<br/>X-AAMP-Intent: task.dispatch
Mail->>Codex: JMAP 推送
Codex->>Mail: task.ack 邮件<br/>X-AAMP-Intent: task.ack
Mail->>Meego: JMAP 推送
Note over Codex: 读取需求,生成代码
Codex->>Mail: task.result 邮件<br/>X-AAMP-Intent: task.result<br/>附件:代码包
Mail->>Meego: JMAP 推送
Meego->>PM: 回写到原工作项
整个过程中,Codex 不需要暴露任何公网端点。它只需要一个邮箱地址,能收邮件、发邮件,就能接收任务、确认接收、返回结果。如果中间遇到不确定的地方,它还可以发一封 task.help_needed 邮件请求澄清,产品经理回复后,Codex 继续执行。
AAMP 与 A2A、ACP 的位置关系
graph LR
U[🧑 用户] --> ED[🖥️ 编辑器 Client]
ED -->|ACP| AG[🤖 编码 Agent]
AG -->|MCP| TOOLS[🔧 工具与数据]
AG2[🤖 独立 Agent] <-->|A2A| AG
P[📋 平台 Meego/GitHub] -->|AAMP| AG3[🤖 本地/托管 Agent]
AG3 -->|MCP| TOOLS
| 协议 | 连接的两侧 | 回答的问题 | 传输层 |
|---|---|---|---|
| MCP | Agent ↔ 工具与数据 | 一个 Agent 如何接入能力 | HTTP/SSE 或 stdio |
| A2A | 独立 Agent ↔ 独立 Agent | 跨系统的 Agent 如何协作 | HTTP/JSON-RPC 或 gRPC |
| ACP | 编辑器 ↔ 编码 Agent | 人的工作台如何承载 Agent | stdio 或 HTTP/WebSocket |
| AAMP | 平台 ↔ Agent / Agent ↔ Agent | 无法暴露端点的 Agent 如何异步接任务 | SMTP + JMAP |
四者不是竞争关系。AAMP 的官方工具链里有一个 aamp-acp-bridge,专门把 ACP 兼容的 Agent(claude、codex、cursor 等)接入 AAMP 任务网络 [1]。一个编码 Agent 完全可以同时对用户讲 ACP、对工具讲 MCP、对其他 Agent 讲 A2A、对平台讲 AAMP——四条通道互不替代,可以同时存在。
三条设计目标
AAMP 的设计目标同时解决三类接入问题 [1]:
- 身份:每个 Agent 都拥有一个标准邮箱端点,其他参与方可以直接寻址,而不需要厂商专属的会话绑定;
- 语义:结构化头字段消除歧义,明确一封消息到底是新任务、取消、澄清请求还是终态结果;
- 上手成本:SDK、CLI 工具和 bridge 让本地 Agent 运行时、工作流产品和操作员工具能够先接起来,而不必先造一堆定制胶水服务。
这个组合之所以重要,是因为只缺其中一层,协议采用就会失败。只有身份,没有语义,那就只是另一个收件箱。只有语义,没有工具,那就只是白皮书。只有工具,没有开放传输,那最后还是会退化成专有平台。
二、核心概念:一次任务协作由什么组成
三个参与者
| 参与者 | 角色 | 说明 |
|---|---|---|
| Dispatcher | 任务派发方 | 平台、工作流系统、或另一个 Agent,发送 task.dispatch |
| Executor | 任务执行方 | 拥有邮箱地址的 Agent 运行时,接收并处理任务 |
| Task Thread | 任务线程 | 与一个任务 ID 关联的邮箱线程,承载权威的生命周期消息 [2] |
AAMP 把邮箱线程视作任务控制平面 [1]。一个任务 ID 对应一个线程,所有关于这个任务的生命周期消息(dispatch、ack、help_needed、result、cancel)都在同一个线程里通过邮件回复传递。这与 A2A 的 taskId + contextId 模型不同——A2A 的任务 ID 和上下文 ID 是分开的,AAMP 直接用邮箱线程作为容器。
五个核心 intents
AAMP 的核心协议被刻意保持得很小。它只标准化异步协作所需的最小共享契约 [1][2]:
| Intent | 方向 | 作用 |
|---|---|---|
task.dispatch |
Dispatcher → Executor | 派发新任务,或向现有任务线程添加澄清输入 |
task.ack |
Executor → Dispatcher | 确认已接收任务,进入本地处理上下文 |
task.help_needed |
Executor → Dispatcher | 请求澄清、批准或策略说明,无法安全继续 |
task.result |
Executor → Dispatcher | 权威终态响应,携带 X-AAMP-Status(completed 或 rejected) |
task.cancel |
Dispatcher → Executor | 撤回已派发的任务 |
task.result 是核心协议的权威终态 [2]。它必须携带 X-AAMP-Status 头,当前规范定义了两个值:completed(任务成功完成)和 rejected(任务无法接受或无法按请求完成)。人可读的输出或拒绝说明放在邮件正文里,机器可读的结构化结果放在 X-AAMP-StructuredResult 头里(Base64url 编码的 UTF-8 JSON)。
task.help_needed 是一个很有工程价值的 intent。它让 Agent 可以显式地说”我不知道怎么继续”,而不是默默失败或猜测。执行方可以在正文里说明阻塞原因,在 X-AAMP-SuggestedOptions 头里提供建议的响应选项(管道符分隔),dispatcher 可以据此呈现给用户选择。
配对授权:解决第一次接触
AAMP 还定义了两个配对相关的 intents,用于解决”第一次接触”的授权问题 [1][2]:
| Intent | 方向 | 作用 |
|---|---|---|
pair.request |
请求方 → 接收方 | 请求接收方授权自己为合法 sender |
pair.respond |
接收方 → 请求方 | 返回配对结果(completed 或 rejected) |
配对流程是 AAMP 的”第一次接触”授权机制。它解决的是一个很实际的上手问题:本地 Agent 可能已经有邮箱身份,但普通用户不应该为了发第一条任务去手写 sender policy JSON,也不应该为了本地 Agent 暴露公网 webhook [1]。
接收方先生成一个短期一次性 code,并把它发布成 aamp://connect URL。消费方解析 URL 后向接收方邮箱发送 pair.request;接收方只有在 code 校验通过后,才会把请求方写入 sender policy。pair.request 是唯一可以临时绕过普通 sender policy 的 intent,但这个绕过只服务于一次性 code 校验 [1]。
1 | aamp://connect?mailbox=agent@meshmail.ai&pair_code=<base64url-code> |
能力发现:card.query 与 card.response
AAMP 还定义了两个能力发现相关的 intents [2]:
| Intent | 方向 | 作用 |
|---|---|---|
card.query |
请求方 → 接收方 | 查询接收方的能力卡 |
card.response |
接收方 → 请求方 | 返回能力卡信息 |
这与 A2A 的 Agent Card 类似,但 AAMP 的能力卡是通过邮件线程交换的,而不是通过 /.well-known/agent-card.json 静态文件。AAMP 也有一个发现文档(/.well-known/aamp),但它描述的是协议版本、支持的 intents、以及 SDK 兼容的 helper API 端点,不是 Agent 的能力描述 [2]。
概念如何拼成一次完整交互
沿用上面 Meego → Codex 的场景,看 task.help_needed 如何介入 [2][5]。
第一回合,Meego 向 Codex 的邮箱发送 task.dispatch:
1 | Subject: [AAMP Task] 为需求 PROJ-123 生成代码包 |
Codex 接收后,先回复 task.ack 确认接收:
1 | Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包 |
第二回合,Codex 发现设计稿里有个交互细节不明确,发送 task.help_needed:
1 | Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包 |
产品经理在 Meego 里看到这个问题,选择”使用弹窗确认”,Meego 在同一线程里回复一封新的 task.dispatch(作为澄清输入):
1 | Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包 |
Codex 继续执行,最终发送 task.result:
1 | Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包 |
整个过程中,所有消息都在同一个邮箱线程里(通过 In-Reply-To 和 References 头关联),任务 ID 始终是 9f0f4a9a-2d3a-4f68-a430-2f4548cda52f。邮箱线程就是任务的控制平面。
三、协议结构:邮箱原生 vs HTTP 原生
三层架构
AAMP 严格区分传输层、语义层和应用集成层 [1]:
flowchart LR
subgraph L1["传输层"]
direction TB
T1["标准兼容邮件服务器"]
T2["SMTP 投递"]
T3["JMAP 同步 / 推送 / Blob 访问"]
end
subgraph L2["AAMP 语义层"]
direction TB
S1["生命周期 intents"]
S2["X-AAMP-* headers"]
S3["/.well-known/aamp 发现机制"]
end
subgraph L3["运行时与集成层"]
direction TB
R1["SDKs: Node.js / Python / Go"]
R2["CLI 与 Worker 运行时"]
R3["工作流桥接、插件、操作工具"]
end
L1 --> L2 --> L3
- 传输层:AAMP 运行在普通邮件基础设施之上。参考部署通常使用支持 JMAP 的邮件服务器(例如 Stalwart),但只要所需的头字段、线程归并和检索语义得以保留,协议本身仍然是传输无关的 [1]。
- 语义层:AAMP 在”线上”标准化任务生命周期,同时把给人看的说明和输出保留在消息正文里 [1]。
- 运行时层:SDK 和集成包把协议细节隐藏在应用代码之后,让产品可以把 AAMP 当作任务协作底座,而不是原始邮箱 API [1]。
头字段设计哲学
AAMP 的头字段设计遵循一个原则:机器可读的元数据放头,人可读的内容放正文 [2]。
必选头字段只有三个 [2]:
| 字段 | 说明 |
|---|---|
X-AAMP-Version |
协议版本,当前为 1.1 |
X-AAMP-Intent |
生命周期 intent(task.dispatch / task.ack / task.help_needed / task.result / task.cancel 等) |
X-AAMP-TaskId |
任务线程的唯一标识符 |
可选头字段按 intent 区分 [2]:
| 字段 | 使用的 Intent | 说明 |
|---|---|---|
X-AAMP-Priority |
task.dispatch | 调度提示:urgent / high / normal |
X-AAMP-Expires-At |
task.dispatch | 任务过期时间(ISO 8601) |
X-AAMP-Session-Key |
task.dispatch | 会话键,用于跨多个 dispatch 复用底层 Agent session |
X-AAMP-Dispatch-Context |
task.dispatch | 路由或授权上下文(百分号编码的键值对) |
X-AAMP-ParentTaskId |
task.dispatch | 父任务 ID,用于嵌套工作流 |
X-AAMP-Status |
task.result / pair.respond | 终态状态(completed / rejected) |
X-AAMP-ErrorMsg |
task.result / pair.respond | 机器可读或短人类可读的拒绝原因 |
X-AAMP-StructuredResult |
task.result | Base64url 编码的 UTF-8 JSON,用于机器可读的结果负载 |
X-AAMP-SuggestedOptions |
task.help_needed | 管道符分隔的建议响应或下一步操作 |
这种设计的优点是:邮件客户端(包括普通用户用的邮箱 App)可以直接显示正文内容,不需要理解 AAMP 协议;而 AAMP 解析器只关心头字段,可以快速提取任务状态和结构化数据。人与机器各取所需,互不干扰。
发现机制:/.well-known/aamp
AAMP 服务端点必须在 /.well-known/aamp 发布一个发现文档 [2]。文档是 JSON 格式,必须标识协议名称、版本、advertised intents、以及 SDK 兼容的 helper API 基址。
1 | { |
这个发现文档与 A2A 的 Agent Card 不同。A2A 的 Agent Card 描述的是 Agent 的能力(技能、输入输出模态、认证要求),AAMP 的发现文档描述的是协议端点的能力(支持哪些 intents、是否有流式支持、SDK helper API 的地址)[2][3]。Agent 的能力描述在 AAMP 里通过 card.query / card.response intents 在线程内交换。
流式观察扩展:task.stream.opened
AAMP 的核心协议是异步的,但它也提供了一个可选的流式观察扩展 [2]。Stream-capable 的执行方可以在处理任务时,通过 task.stream.opened intent 通知 dispatcher 已打开一个流,然后通过 SSE(Server-Sent Events)推送增量进度。
但这里有一个关键区分:邮箱线程是权威控制平面,流只是可选的数据平面 [2]。流不替代最终的 task.result 消息。即使流断了、丢了,dispatcher 仍然可以从邮箱线程里获取权威的任务状态和结果。
流事件类型包括 [2]:
| 事件类型 | 负载 | 渲染期望 |
|---|---|---|
text.delta |
text: string |
追加可见文本到运行中的转录 |
todo |
items: Array<{id, content, status}> |
替换当前任务检查清单 |
tool_call |
toolCallId, label, status |
渲染工具调用及其状态更新 |
artifact |
label, filename?, url? |
渲染或链接生成的工件 |
这种设计与 A2A 的 SSE 流式不同。A2A 的流是任务状态更新的唯一通道(流断了需要用 SubscribeToTask 重新订阅),AAMP 的流只是观察窗口,权威状态始终在邮箱线程里 [2][3]。
四、信任模型:配对码与 Sender Policy
配对码流程
AAMP 的信任模型建立在两个机制上:配对码(解决第一次接触)和 Sender Policy(持续授权)[1][2]。
配对码是 AAMP 的”第一次接触”授权流程。它解决的是一个很实际的上手问题:本地 Agent、Bridge、插件或 registered-command node 可能已经有邮箱身份,但普通用户不应该为了发第一条任务去手写 sender policy JSON,也不应该为了本地 Agent 暴露公网 webhook [1]。
流程如下 [1]:
- 生成:接收方 SDK helper 默认生成 6 字节随机数并编码为 base64url,持久化 mailbox、code、connect URL、过期时间和可选 dispatch-context rules;参考实现默认 5 分钟有效。
- 消费:AAMP App、User UI、
aamp-cli pair、Feishu Bridge、WeChat Bridge 等会解析aamp://connectURL,并向mailbox发送邮件,携带X-AAMP-Intent: pair.request、新的X-AAMP-TaskId、X-AAMP-Pair-Code和可选X-AAMP-Dispatch-Context-Rules。 - 校验:接收方必须拒绝未知、过期或已消费的 code。有效请求会新增或更新请求方的 sender policy,可选地附带 dispatch-context rules,然后消费该 code,避免重复使用。
- 回执:接收方必须用同一个 taskId 回复
pair.respond。成功时携带X-AAMP-Status: completed;失败时携带X-AAMP-Status: rejected和X-AAMP-ErrorMsg。
Sender Policy 授权
Sender Policy 是接收方本地的授权规则,决定哪些 sender 可以向自己派发任务 [2]。它可以是简单的白名单(允许 alice@example.com 派发任何任务),也可以是带条件的规则(只允许 bot@github.com 派发 project_key=proj_123 的任务)。
配对码流程的结果就是把请求方写入 sender policy。一旦配对成功,后续请求方可以直接发送 task.dispatch,不需要再走配对流程。
安全考虑
AAMP 依赖底层邮件和 Web 基础设施来保障传输安全、sender 认证和凭证处理 [2]。实现方应当:
- 传输安全:邮件提交使用 TLS,helper 或流端点使用 HTTPS;
- Sender 认证:当前参考部署中,外部 sender 的信任建立在邮件传输层的 DKIM 验证成功之上 [2]。规范不强制要求 DKIM,但要求有等价的传输认证信任基础;
- 配对码安全:配对码是授权令牌,必须用密码学安全的随机数生成,使用短时效,成功使用后必须消费,避免在共享日志中记录完整的配对 URL [2];
- Dispatch Context 不是身份:接收方不能仅依赖
X-AAMP-Dispatch-Context来做真实性或授权判断 [2]。
与 A2A 认证模型的对比
A2A 的认证模型基于 OAuth 2.0 / Bearer token,Agent Card 里声明 securitySchemes 和 securityRequirements,客户端按方案获取访问令牌 [3]。AAMP 的认证模型基于邮箱 DKIM + 配对码,sender 的信任来自邮件传输层的 DKIM 签名验证,第一次接触通过配对码完成授权。
两种模型反映了两种不同的威胁模型。A2A 里对方是跨组织的外部系统,安全边界在于认证、授权与数据保护;AAMP 里对方是通过邮箱寻址的独立参与方,安全边界在于 DKIM 验证 + sender policy 控制 [1][3]。给 Agent 选通道时,先分清自己站在哪个场景里。
五、生态与工具链:从协议到落地
SDK 三件套
AAMP 的 SDK 层是多语言的,覆盖 Node.js、Python、Go 三种运行时 [1]。三套 SDK 都是完整的邮箱运行时,支持 SMTP 发送与 JMAP 推送接收。
以 Node.js 为例,一个最小 Worker 长这样 [1]:
1 | import { AampClient } from 'aamp-sdk' |
Python 和 Go 的写法类似 [1]。SDK 把协议细节隐藏在应用代码之后,开发者只需要关心”收到任务后做什么”。
Bridge 系列
AAMP 仓库里提供了一系列 bridge,让已有的 Agent 运行时能快速接入 AAMP 任务网络 [1]:
| Bridge | 作用 | 典型场景 |
|---|---|---|
aamp-acp-bridge |
把 ACP 兼容 Agent 接入 AAMP | Codex、Claude、Cursor、Gemini 等编码 Agent 接收平台任务 |
aamp-cli-bridge |
把 CLI Agent 接入 AAMP | Coco、Trae、Codem 等命令行 Agent |
aamp-feishu-bridge |
把飞书 Bot 接入 AAMP | 飞书群或机器人会话里的请求派发给 Agent |
aamp-wechat-bridge |
把微信 Bot 接入 AAMP | 微信私聊消息派发给 Agent |
aamp-openclaw-plugin |
OpenClaw 原生 AAMP 插件 | OpenClaw Agent 直接接收 task.dispatch |
以 aamp-acp-bridge 为例,初始化流程如下 [1]:
1 | npx aamp-acp-bridge init |
初始化向导会提示输入 AAMP Host(例如 https://meshmail.ai)、扫描本机已安装的 ACP Agent、选择要桥接的 Agent、为选中的 Agent 注册邮箱身份、写入配置和凭证。启动 bridge 后,从兼容 AAMP 的邮箱 UI 向 Agent 邮箱发送 task.dispatch,bridge 会把任务转给本地 ACP Agent 执行,并把结果回写到同一线程 [1]。
典型使用案例
meshmail.ai/cases 收集了十几个可以直接照着接入的自动化场景 [5],这里选四个代表性的:
1. Meego 需求自动生成代码包 [5]
入口:Meego 工作项
Agent:Codex
流程:产品经理在工作项里触发 Codex,Codex 读取需求描述和附件,生成实现代码、说明文档和测试用例,结果回写到原工作项。
接入方式:aamp-acp-bridge(Codex 是 ACP 兼容 Agent)
2. GitHub PR 自动审查 [5]
入口:GitHub PR
Agent:Claude 或 Cursor
流程:GitHub App 把 PR diff 和上下文发给 Agent,Agent 审查代码并给出修改建议,结果回到 PR 评论区。
接入方式:aamp-acp-bridge 或 aamp-cli-bridge
3. 飞书会话里直接派活给 Agent [5]
入口:飞书群或机器人会话
Agent:OpenClaw
流程:业务同学在飞书群里提交请求,OpenClaw 接单处理,结果回到同一任务线程。
接入方式:aamp-feishu-bridge + aamp-openclaw-plugin
4. Base 记录批量补全和结构化回填 [5]
入口:Base 行记录
Agent:CLI Agent
流程:Base 把行记录、附件和字段值发给 Agent,Agent 处理后回填分类、摘要、风险等级等字段。
接入方式:aamp-cli-bridge
这些案例的共同点是:平台作为 dispatcher,Agent 作为 executor,任务通过邮箱异步派发,结果回写到原系统。Agent 不需要暴露公网端点,平台不需要写私有 API 适配,双方通过 AAMP 协议解耦。
与 ACP 的衔接
AAMP 和 ACP 看似解决不同的问题,但官方工具链里有一个 aamp-acp-bridge,把两者连接起来 [1]。这个 bridge 的作用是:让 ACP 兼容的编码 Agent(claude、codex、cursor 等)能够接收 AAMP 任务。
这意味着同一个本地 Agent,可以有两种接入姿态:
- 同步交互:用户在编辑器里通过 ACP 与 Agent 对话,Agent 实时修改代码;
- 异步接任务:平台通过 AAMP 向 Agent 派发任务,Agent 执行后把结果回写。
两种姿态不冲突。Agent 在编辑器里讲 ACP,在任务网络里讲 AAMP,对工具讲 MCP,对其他 Agent 讲 A2A——四条通道各司其职。
六、落地建议:什么时候选 AAMP
与 A2A 的对比
| 维度 | A2A | AAMP |
|---|---|---|
| 传输层 | HTTP/JSON-RPC 或 gRPC | SMTP + JMAP |
| 寻址方式 | Agent Card URL | 邮箱地址 |
| 任务模型 | Task 状态机(SUBMITTED → WORKING → COMPLETED 等) | 邮箱线程 + intents(dispatch → ack → result) |
| 流式支持 | SSE 流式(权威通道) | SSE 流式(观察窗口,非权威) |
| 认证模型 | OAuth 2.0 / Bearer token | DKIM + 配对码 + Sender Policy |
| 适用场景 | 执行方有公网入口,需要实时交互 | 执行方无公网入口,任务天然异步 |
| 接入成本 | 需要暴露 HTTP 端点、实现 Agent Card | 需要邮箱地址、实现 intents 解析 |
适用场景
AAMP 适合以下场景 [1]:
- Agent 无法暴露公网端点:Agent 跑在本地、沙箱、或厂商托管运行时里,没有公网入口;
- 任务天然异步:不需要实时双向流式交互,dispatcher 可以接受”发任务 → 等结果”的异步模型;
- 想要去中心化的 Agent 寻址:邮箱地址是全局可路由的,不依赖某个中心化注册表;
- 需要可审计的任务线程:邮箱天然持久化,任务线程可以直接用于审计和追溯。
不适用场景
AAMP 不适合以下场景:
- 需要实时双向流式交互:AAMP 的流只是观察窗口,权威状态在邮箱线程里。如果需要实时双向流式交互,用 A2A 的 SSE 或 ACP;
- Agent 已经有公网 HTTP 端点:A2A 的 HTTP 端点模型更直接,不需要绕道邮箱;
- 需要强一致性的任务状态机:A2A 的 Task 状态机(SUBMITTED → WORKING → INPUT_REQUIRED → COMPLETED 等)比 AAMP 的 intents 更完整 [3]。AAMP 的任务状态是本地投影,线上协议只定义了 5 个核心 intents。
接入路径选择
如果你决定接入 AAMP,以下是常见的接入路径 [1][6]:
- 已有 ACP Agent:用
aamp-acp-bridge,一条命令初始化,bridge 会把 AAMP 任务转给本地 ACP Agent; - CLI Agent:用
aamp-cli-bridge,创建 profile 描述命令、参数、stdin、环境变量等,bridge 负责协议转换; - 自研 Agent:用 SDK(Node.js / Python / Go),实现
task.dispatch事件处理,调用sendResult返回结果; - 平台方:实现 AAMP dispatcher,向 Agent 邮箱发送
task.dispatch邮件,监听task.result回写。
准备实现时,可以从官方仓库的 docs/AAMP_CORE_SPECIFICATION.md 进入规范 [2],用 SDK 的 examples 起步 [1],先跑通一个 dispatch → ack → result 的最小闭环,再根据需要加上 task.help_needed、流式观察、配对授权等能力。
结论
AAMP 的价值不是证明”HTTP 端点不好”,而是在 Agent 无法暴露公网端点的场景里,提供一套基于邮箱的异步协作约定:用邮箱地址寻址,用 task.dispatch 派发任务,用 task.ack 确认接收,用 task.help_needed 请求澄清,用 task.result 返回结果。
我的落地建议是先判断 Agent 的可达性,再选协议:
- Agent 有公网入口:优先用 A2A,HTTP 端点模型更直接,生态更成熟;
- Agent 无公网入口,但用户在编辑器里交互:用 ACP,同步交互体验更好;
- Agent 无公网入口,且任务天然异步:用 AAMP,邮箱地址是全局可路由的,任务线程天然持久化。
我仍然更关心 AAMP 的生态成熟度。协议本身设计得很克制,核心 intents 只有 5 个,上手成本不高。但 bridge 系列(ACP Bridge、CLI Bridge、Feishu Bridge、WeChat Bridge)目前是务实的过渡方案——它们让已有 Agent 能快速接入,但也意味着 AAMP 的真实采用很大程度上依赖这些 bridge 的维护质量。
另一个保留意见是邮箱原生的双刃剑效应。邮箱的优势是去中心化、可审计、全局可路由;但邮箱的延迟、复杂度、以及不同邮件服务器的行为差异,也是 AAMP 必须面对的工程挑战。参考部署用 meshmail.ai 提供了一个一致的体验,但开放生态里不同邮件服务器的兼容性测试,会是 AAMP 长期要解决的问题。
准备实现时,可以从官方仓库的 README 进入,再用 AAMP Core Specification 逐项核对头字段和 intent 语义。尤其不要把 AAMP 的 intents 与 A2A 的 Task 状态机混为一谈——两者解决的是不同的问题。
参考资料
[1] AAMP GitHub 仓库
[4] meshmail.ai 首页
[5] AAMP 使用案例
[6] AAMP 使用指南