# A2A 协作

A2A 协作把设备智能体发布到 EMQX A2A 网络，让其他智能体发现卡片、读取由设备规格命令生成的技能，并通过 MQTT v5 `SendMessage` 调用设备能力；实际执行仍由设备智能体按已接入设备、设备状态和命令定义完成。

## 适合什么时候用

A2A 适合让设备智能体参与跨系统或跨智能体协作，例如：

- 其他 A2A 智能体需要调用当前设备智能体的设备能力。
- 多个设备智能体需要组成一个协作流程，例如“传感器判断异常后，让灯光和门锁执行动作”。
- 需要把设备能力放到 A2A 市场里，让其他参与者按卡片发现和复用。

如果只是在当前控制台里对单个设备对话、调试或控制，不需要开启 A2A；普通设备控制走控制台对话、MQTT 或 SDK 即可。

## 准备条件

开启前先确认三件事：

1. EMQX 版本为 6.2.0 或以上，并启用了 A2A 注册表。仓库里的本地开发 EMQX 配置已经包含 `EMQX_A2A_REGISTRY__ENABLE=true`。
2. 设备智能体的设备规格至少定义一个 `commands` 命令。没有命令时不能发布 A2A 卡片，因为卡片里没有可调用技能。
3. 设备智能体网关能连接到同一个 MQTT 代理。A2A 发布和请求都复用运行时的 MQTT 配置。

A2A 发布身份由运行时配置决定：

| 配置 | 作用 | 默认值 |
| --- | --- | --- |
| `A2A_ORG_ID` | A2A 注册和发现使用的组织 ID | `default` |
| `A2A_UNIT_ID` | A2A 注册和发现使用的单元 ID | `default` |
| MQTT 代理配置 | 写入智能体卡片的 `supportedInterfaces[0].url`，也是实际通信地址 | 当前 MQTT 运行配置 |

如果要在控制台里看到 A2A 市场入口，还需要在网页控制台环境里开启：

```text
VITE_FF_A2A_MARKETPLACE_ENABLE=true
```

更多配置项见 [配置](../operate-reference/configuration.md)。

## 启用并发布

创建或编辑设备智能体时，在预览面板确认设备规格后打开 **启用 A2A 协作**。如果希望这张卡片出现在 A2A 市场，再打开 **发布 A2A 卡片**。

![启用 A2A 协作](../images/docs/usage/a2a/zh/01-enable-a2a.png)

<!--截图文件：源文件 apps/docs/public/images/docs/usage/a2a/zh/01-enable-a2a.png；引用 ![启用 A2A 协作](../images/docs/usage/a2a/zh/01-enable-a2a.png)。-->

保存后，系统会根据当前设备智能体生成智能体卡片。如果同时打开 **发布 A2A 卡片**，这张卡片会出现在 A2A 市场；否则只在当前 A2A 网络中被发现。

| 卡片字段 | 来源 |
| --- | --- |
| `name` | 使用设备智能体名称 |
| `description` | 使用设备智能体说明；没有说明时使用名称 |
| `version` | 当前固定为 `1.0.0` |
| `supportedInterfaces` | 使用 MQTT 代理地址，协议为 `MQTT5+JSONRPC` |
| `capabilities` | `streaming: true` |
| `defaultInputModes` / `defaultOutputModes` | `text/plain` |
| `skills` | 设备规格里的每个命令生成一个技能，`id` 和 `name` 都是命令名，`description` 来自命令说明 |

发布成功后，设备智能体会保持在线发布状态。EMQX 会根据连接状态判断这张卡片对应的智能体是在线还是离线。

编辑设备智能体时关闭 **启用 A2A 协作** 会取消发布。如果此前已经发布到 A2A 市场，卡片也会从市场移除。

## 其他智能体如何发现它

发布后的卡片会写入 EMQX A2A 发现主题：

```text
$a2a/v1/discovery/{org_id}/{unit_id}/{agent_id}
```

`agent_id` 由设备智能体根据当前命名空间和 `productId` 生成。你不需要手动拼接它；可以从 A2A 市场或发现主题中获取。

开启 A2A 市场后，进入 **A2A 市场** 可以看到：

- 卡片名称、说明和技能。
- 公开或私有可见性。
- 在线或离线状态。

市场列表会同时展示已公开登记的卡片，以及当前 EMQX 发现到的私有卡片。

<!--截图预留：A2A 市场卡片列表。源文件 apps/docs/public/images/docs/usage/a2a/zh/02-marketplace-cards.png；引用 ![A2A 市场卡片列表](../images/docs/usage/a2a/zh/02-marketplace-cards.png)。-->

## 其他智能体如何调用它

调用方使用 MQTT v5，并按 A2A 的 MQTT 通信约定发送 JSON-RPC 请求：

```text
请求主题：$a2a/v1/request/{org_id}/{unit_id}/{agent_id}
回复主题：$a2a/v1/reply/{org_id}/{unit_id}/{caller_agent_id}/{reply_suffix}
```

设备智能体网关当前处理 `SendMessage` 方法。请求必须设置 MQTT v5 的 `responseTopic`，否则网关无法回复。`correlationData` 可选；如果提供，回复时会原样带回。

任意支持 MQTT v5 的客户端都可以调用。先订阅自己的回复主题，再向请求主题发布下面的 JSON；发布时把 `responseTopic` 设置为回复主题，`correlationData` 可以设置为同一个任务 ID。

```json
{
  "jsonrpc": "2.0",
  "id": "task-001",
  "method": "SendMessage",
  "params": {
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "检查当前状态，如果温度过高就把空调切换到制冷模式。"
        }
      ],
      "taskId": "task-001"
    },
    "metadata": {
      "sender": "my-a2a-client"
    }
  }
}
```

请求进入设备智能体网关后，网关会把文本内容交给目标设备智能体处理。目标设备智能体可以查询状态、调用设备命令或使用它已有的工具。回复会发送到 `responseTopic`：

- 执行中状态返回 `statusUpdate`，状态通常是 `TASK_STATE_WORKING`。
- 文本结果返回 `artifactUpdate`，其中 `artifact.parts` 包含回复文本。
- 完成时返回 `TASK_STATE_COMPLETED`。
- 执行失败时返回 `TASK_STATE_FAILED`。

## 在市场里组合应用

开启 A2A 市场后，还可以在 **A2A 市场 → 应用** 中创建组合应用。选择多个已发现的设备智能体，填写应用名称和协作指令，然后创建应用。

组合应用会把所选智能体 ID 和协作指令发送给编排智能体。当前实现依赖名为 `skitter` 的 A2A 编排智能体；应用变为就绪后，可以在应用对话中发起任务，由编排智能体协调这些设备智能体完成。

例如，可以创建一个“机房环境助手”，选择温湿度设备智能体、空调设备智能体和告警设备智能体，并写入：

```text
持续关注机房温湿度。当温度超过阈值时，先查询空调状态，再切换到制冷模式，并在处理完成后返回简短报告。
```

## 验证发布是否成功

发布后可以按下面顺序检查：

1. 回到设备智能体列表或详情页，确认它显示 A2A 已启用。
2. 打开 **A2A 市场**，确认能看到对应卡片、技能和状态。
3. 打开 EMQX Dashboard，进入 A2A 注册表相关页面，按组织、单元或智能体标识查找这张卡片。本地开发环境的 Dashboard 默认地址是 `http://127.0.0.1:18083`。
4. 如果要从 MQTT 层验证，订阅当前组织的发现主题：

```text
$a2a/v1/discovery/{org_id}/+/+
```

5. 重启网关后，之前已经发布的卡片会从数据库恢复并重新发布。日志里会出现类似 `A2A Sync` 的恢复信息。

<!--截图预留：EMQX Dashboard 中的 A2A 注册表页面。源文件 apps/docs/public/images/docs/usage/a2a/zh/05-emqx-a2a-registry.png；引用 ![EMQX Dashboard A2A 注册表](../images/docs/usage/a2a/zh/05-emqx-a2a-registry.png)。-->

## 常见问题和限制

| 现象 | 排查方向 |
| --- | --- |
| 发布失败，提示需要技能 | 设备规格必须至少包含一个 `commands` 命令；补充命令后重新保存并发布。 |
| A2A 市场入口看不到 | 网页控制台需要开启 `VITE_FF_A2A_MARKETPLACE_ENABLE=true`。这个开关只影响市场入口显示，不影响 A2A 注册本身。 |
| 卡片看得到但状态是离线 | 发布连接已经断开，或网关没有运行。重启网关后，已发布卡片会尝试自动恢复。 |
| 调用后没有回复 | 确认请求使用 MQTT v5，设置了 `responseTopic`，并且请求主题里的 `org_id`、`unit_id`、`agent_id` 正确。 |
| 收到失败状态 | 查看网关日志，并确认目标设备在线、命令参数合理。 |
| 请求类型不生效 | 当前主要支持文本类 `SendMessage` 请求，回复以状态更新和文本结果返回。 |
| 组合应用无法就绪 | 组合应用是预览能力，依赖 `skitter` 编排智能体在线。 |
