# A2A Collaboration

A2A collaboration publishes a Device Agent to an EMQX A2A network. Other agents discover its card, read command-derived skills, and call capabilities through MQTT v5 `SendMessage`; execution still follows connected devices, state, and command definitions.

## When to Use It

Use A2A when a Device Agent needs to participate in cross-system or cross-agent collaboration, for example:

- Other A2A agents need to call this Device Agent's device capabilities.
- Multiple Device Agents need to work together in one flow, such as "after a sensor detects an abnormal state, ask the light and door lock to act."
- Device capabilities need to be listed in the A2A Marketplace so others can discover and reuse them from a card.

If you only need conversation, debugging, or control for one device inside the current console, leave A2A disabled; use console chat, MQTT, or the SDK for normal device control.

## Prerequisites

Before enabling A2A, check three things:

1. EMQX is version 6.2.0 or later and the A2A registry is enabled. The local development EMQX configuration in this repository already includes `EMQX_A2A_REGISTRY__ENABLE=true`.
2. The Device Agent's device specification defines at least one `commands` command. A card cannot be published without commands because there are no callable skills.
3. The Device Agent gateway can connect to the same MQTT broker. A2A publishing and requests reuse the runtime MQTT configuration.

A2A publishing identity comes from runtime configuration:

| Config | Purpose | Default |
| --- | --- | --- |
| `A2A_ORG_ID` | Organization ID used for A2A registration and discovery | `default` |
| `A2A_UNIT_ID` | Unit ID used for A2A registration and discovery | `default` |
| MQTT broker config | Written to `supportedInterfaces[0].url` in the agent card and used as the actual communication address | Current MQTT runtime config |

To show A2A Marketplace entries in the web console, also enable:

```text
VITE_FF_A2A_MARKETPLACE_ENABLE=true
```

See [Configuration](../operate-reference/configuration.md) for more settings.

## Enable and Publish

When creating or editing a Device Agent, confirm the device specification in the preview panel, then turn on **Enable A2A Collaboration**. To show the card in the A2A Marketplace, also turn on **Publish A2A Card**.

![Enable A2A collaboration](../images/docs/usage/a2a/en/01-enable-a2a.png)

<!--Screenshot file: source file apps/docs/public/images/docs/usage/a2a/en/01-enable-a2a.png; reference ![Enable A2A collaboration](../images/docs/usage/a2a/en/01-enable-a2a.png).-->

After saving, the system generates an agent card from the current Device Agent. If **Publish A2A Card** is also enabled, the card appears in the A2A Marketplace; otherwise it is discoverable only inside the current A2A network.

| Card field | Source |
| --- | --- |
| `name` | Uses the Device Agent name |
| `description` | Uses the Device Agent description; falls back to the name when empty |
| `version` | Currently fixed to `1.0.0` |
| `supportedInterfaces` | Uses the MQTT broker address with `MQTT5+JSONRPC` |
| `capabilities` | `streaming: true` |
| `defaultInputModes` / `defaultOutputModes` | `text/plain` |
| `skills` | One skill is generated for each command in the device specification; `id` and `name` use the command name, and `description` uses the command description |

After publishing succeeds, the Device Agent stays published online. EMQX uses the connection state to determine whether the agent behind the card is online or offline.

Turning off **Enable A2A Collaboration** while editing the Device Agent unpublishes it. If the card was published to the A2A Marketplace, it is removed from the marketplace too.

## How Other Agents Discover It

The published card is written to the EMQX A2A discovery topic:

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

`agent_id` is generated by Device Agent from the current namespace and `productId`. You do not need to assemble it manually; get it from the A2A Marketplace or discovery topic.

After A2A Marketplace is enabled, open **A2A Marketplace** to see:

- Card name, description, and skills.
- Public or private visibility.
- Online or offline state.

The marketplace list shows both public registered cards and private cards currently discovered from EMQX.

<!--Screenshot placeholder: A2A Marketplace card list. Source file apps/docs/public/images/docs/usage/a2a/en/02-marketplace-cards.png; reference ![A2A Marketplace card list](../images/docs/usage/a2a/en/02-marketplace-cards.png).-->

## How Other Agents Call It

The caller uses MQTT v5 and sends a JSON-RPC request following the A2A MQTT topic convention:

```text
Request topic: $a2a/v1/request/{org_id}/{unit_id}/{agent_id}
Reply topic:   $a2a/v1/reply/{org_id}/{unit_id}/{caller_agent_id}/{reply_suffix}
```

The Device Agent gateway currently handles the `SendMessage` method. The request must set the MQTT v5 `responseTopic`, otherwise the gateway cannot reply. `correlationData` is optional; when provided, replies include it unchanged.

Any MQTT v5 client can call the agent. Subscribe to your reply topic first, then publish the following JSON to the request topic. Set `responseTopic` to the reply topic, and optionally set `correlationData` to the same task ID.

```json
{
  "jsonrpc": "2.0",
  "id": "task-001",
  "method": "SendMessage",
  "params": {
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "Check the current state. If the temperature is too high, switch the air conditioner to cooling mode."
        }
      ],
      "taskId": "task-001"
    },
    "metadata": {
      "sender": "my-a2a-client"
    }
  }
}
```

After the request reaches the Device Agent gateway, the gateway passes the text to the target Device Agent. The target Device Agent can query state, call device commands, or use its existing tools. Replies are published to `responseTopic`:

- In-progress updates return `statusUpdate`, usually with `TASK_STATE_WORKING`.
- Text results return `artifactUpdate`, where `artifact.parts` contains the response text.
- Completion returns `TASK_STATE_COMPLETED`.
- Failure returns `TASK_STATE_FAILED`.

## Compose Applications in the Marketplace

After A2A Marketplace is enabled, you can also create composed applications in **A2A Marketplace → Applications**. Select multiple discovered Device Agents, enter an application name and collaboration instructions, then create the application.

The composed application sends the selected agent IDs and instructions to the orchestration agent. The current implementation depends on the A2A orchestration agent named `skitter`. After the application becomes ready, you can start tasks in the application chat and let the orchestration agent coordinate the selected Device Agents.

For example, create a "Server Room Environment Assistant", select a temperature and humidity Device Agent, an air conditioner Device Agent, and an alert Device Agent, then use instructions like:

```text
Monitor server room temperature and humidity. When temperature exceeds the threshold, query the air conditioner status, switch it to cooling mode, and return a short report after handling it.
```

## Verify Publishing

After publishing, check in this order:

1. Return to the Device Agent list or detail page and confirm that A2A is enabled.
2. Open **A2A Marketplace** and confirm that the card, skills, and state are visible.
3. Open EMQX Dashboard, go to the A2A registry page, and find the card by organization, unit, or agent ID. In local development, the Dashboard is available at `http://127.0.0.1:18083`.
4. To verify at the MQTT layer, subscribe to the discovery topic for the current organization:

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

5. After restarting the gateway, previously published cards are restored from the database and published again. The logs should include an `A2A Sync` message.

<!--Screenshot placeholder: A2A registry page in EMQX Dashboard. Source file apps/docs/public/images/docs/usage/a2a/en/05-emqx-a2a-registry.png; reference ![EMQX Dashboard A2A registry](../images/docs/usage/a2a/en/05-emqx-a2a-registry.png).-->

## Troubleshooting and Limits

| Symptom | What to check |
| --- | --- |
| Publishing fails with a skills-related message | The device specification must contain at least one `commands` command. Add a command, then save and publish again. |
| A2A Marketplace entry is missing | The web console needs `VITE_FF_A2A_MARKETPLACE_ENABLE=true`. This flag only controls marketplace entry points; it does not affect A2A registration itself. |
| The card is visible but offline | The publishing connection is disconnected, or the gateway is not running. Restarting the gateway should restore previously published cards. |
| No reply after calling the agent | Confirm that the request uses MQTT v5, sets `responseTopic`, and has the correct `org_id`, `unit_id`, and `agent_id` in the request topic. |
| The task returns a failed state | Check gateway logs, device online state, and command parameters. |
| The request type is not handled | Device Agent currently focuses on text-based `SendMessage` requests and returns status updates plus text results. |
| A composed application does not become ready | Composed applications are a preview feature and depend on the `skitter` orchestration agent being online. |
