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]:

  1. 身份:每个 Agent 都拥有一个标准邮箱端点,其他参与方可以直接寻址,而不需要厂商专属的会话绑定;
  2. 语义:结构化头字段消除歧义,明确一封消息到底是新任务、取消、澄清请求还是终态结果;
  3. 上手成本: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
2
3
4
5
6
7
8
Subject: [AAMP Task] 为需求 PROJ-123 生成代码包
X-AAMP-Version: 1.1
X-AAMP-Intent: task.dispatch
X-AAMP-TaskId: 9f0f4a9a-2d3a-4f68-a430-2f4548cda52f
X-AAMP-Priority: high
X-AAMP-Dispatch-Context: project_key=proj_123; user_key=alice

请根据需求描述和附件中的设计稿,生成实现代码、单元测试和说明文档。

Codex 接收后,先回复 task.ack 确认接收:

1
2
3
4
5
6
Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包
X-AAMP-Version: 1.1
X-AAMP-Intent: task.ack
X-AAMP-TaskId: 9f0f4a9a-2d3a-4f68-a430-2f4548cda52f

已接收任务,开始处理。

第二回合,Codex 发现设计稿里有个交互细节不明确,发送 task.help_needed

1
2
3
4
5
6
7
Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包
X-AAMP-Version: 1.1
X-AAMP-Intent: task.help_needed
X-AAMP-TaskId: 9f0f4a9a-2d3a-4f68-a430-2f4548cda52f
X-AAMP-SuggestedOptions: 使用标准表单|使用弹窗确认|跳过此步骤

设计稿中"提交订单"按钮的二次确认交互不明确:是使用标准表单提交,还是弹窗确认?

产品经理在 Meego 里看到这个问题,选择”使用弹窗确认”,Meego 在同一线程里回复一封新的 task.dispatch(作为澄清输入):

1
2
3
4
5
6
Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包
X-AAMP-Version: 1.1
X-AAMP-Intent: task.dispatch
X-AAMP-TaskId: 9f0f4a9a-2d3a-4f68-a430-2f4548cda52f

使用弹窗确认。

Codex 继续执行,最终发送 task.result

1
2
3
4
5
6
7
Subject: Re: [AAMP Task] 为需求 PROJ-123 生成代码包
X-AAMP-Version: 1.1
X-AAMP-Intent: task.result
X-AAMP-TaskId: 9f0f4a9a-2d3a-4f68-a430-2f4548cda52f
X-AAMP-Status: completed

已完成代码包生成,包含实现代码、单元测试和说明文档。详见附件。

整个过程中,所有消息都在同一个邮箱线程里(通过 In-Reply-ToReferences 头关联),任务 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"protocol": "aamp",
"version": "1.1",
"intents": [
"task.dispatch",
"task.cancel",
"task.ack",
"task.help_needed",
"task.result",
"task.stream.opened",
"pair.request",
"pair.respond",
"card.query",
"card.response"
],
"capabilities": {
"stream": {
"transport": "sse",
"createAction": "aamp.stream.create",
"subscribeUrlTemplate": "/api/aamp/streams/{streamId}/events"
}
},
"api": {
"url": "/api/aamp",
"actions": [
"aamp.mailbox.check",
"aamp.mailbox.register",
"aamp.mailbox.credentials",
"aamp.mailbox.send",
"aamp.mailbox.inbox",
"aamp.mailbox.thread"
]
},
"endpoints": {
"discovery": "/.well-known/aamp",
"api": "/api/aamp",
"jmapSession": "/.well-known/jmap",
"jmapApi": "/jmap/"
}
}

这个发现文档与 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]:

  1. 生成:接收方 SDK helper 默认生成 6 字节随机数并编码为 base64url,持久化 mailbox、code、connect URL、过期时间和可选 dispatch-context rules;参考实现默认 5 分钟有效。
  2. 消费:AAMP App、User UI、aamp-cli pair、Feishu Bridge、WeChat Bridge 等会解析 aamp://connect URL,并向 mailbox 发送邮件,携带 X-AAMP-Intent: pair.request、新的 X-AAMP-TaskIdX-AAMP-Pair-Code 和可选 X-AAMP-Dispatch-Context-Rules
  3. 校验:接收方必须拒绝未知、过期或已消费的 code。有效请求会新增或更新请求方的 sender policy,可选地附带 dispatch-context rules,然后消费该 code,避免重复使用。
  4. 回执:接收方必须用同一个 taskId 回复 pair.respond。成功时携带 X-AAMP-Status: completed;失败时携带 X-AAMP-Status: rejectedX-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 里声明 securitySchemessecurityRequirements,客户端按方案获取访问令牌 [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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { AampClient } from 'aamp-sdk'

const client = AampClient.fromMailboxIdentity({
email: 'agent@example.com',
smtpPassword: '<smtp-password>',
baseUrl: 'https://meshmail.ai',
})

client.on('task.dispatch', async (task) => {
await client.sendResult({
to: task.from,
taskId: task.taskId,
status: 'completed',
output: `Finished: ${task.title}`,
inReplyTo: task.messageId,
})
})

await client.connect()

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-bridgeaamp-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]:

  1. Agent 无法暴露公网端点:Agent 跑在本地、沙箱、或厂商托管运行时里,没有公网入口;
  2. 任务天然异步:不需要实时双向流式交互,dispatcher 可以接受”发任务 → 等结果”的异步模型;
  3. 想要去中心化的 Agent 寻址:邮箱地址是全局可路由的,不依赖某个中心化注册表;
  4. 需要可审计的任务线程:邮箱天然持久化,任务线程可以直接用于审计和追溯。

不适用场景

AAMP 不适合以下场景:

  1. 需要实时双向流式交互:AAMP 的流只是观察窗口,权威状态在邮箱线程里。如果需要实时双向流式交互,用 A2A 的 SSE 或 ACP;
  2. Agent 已经有公网 HTTP 端点:A2A 的 HTTP 端点模型更直接,不需要绕道邮箱;
  3. 需要强一致性的任务状态机: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 的可达性,再选协议:

  1. Agent 有公网入口:优先用 A2A,HTTP 端点模型更直接,生态更成熟;
  2. Agent 无公网入口,但用户在编辑器里交互:用 ACP,同步交互体验更好;
  3. 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 仓库

[2] AAMP Core Specification

[3] A2A 协议详解——Agent 间通信的开放标准

[4] meshmail.ai 首页

[5] AAMP 使用案例

[6] AAMP 使用指南

[7] ACP 协议详解——编辑器与编码 Agent 之间的开放标准