# A2A agents

> Send messages to A2A agents (Agent2Agent protocol) as another agent sends them, and check what they answer: the tasks they run, with their states and their artifacts, as they answer or as they stream.

Source: https://axx.nimbusxr.us/next/references/packs/a2a/

Send messages to A2A agents (Agent2Agent protocol) as another agent sends them, and check what they answer: the tasks they run, with their states and their artifacts, as they answer or as they stream.

```gherkin
Given the parcels a2a agent with the following properties:
  | url | http://localhost:8400 |
When a message is sent to the parcels a2a agent:
  """
  Where is PX-A2A-9201?
  """
Then the parcels a2a agent's task is completed
And the parcels a2a agent's answer contains 'out for delivery'
```

- **The card is the contract:** it is read at `/.well-known/agent-card.json` (or from a file), checked for what A2A 1.0 requires, and says how to reach the agent: JSON-RPC, HTTP+JSON or gRPC.
- **A conversation:** a message starts one; a reply continues the agent's last task, which is how a task that asks for input (`input-required`) gets it.
- **Streams belong to the scenario,** which ends them when it ends. The checks wait (10 seconds, or `within {duration}`) for what the stream has not sent yet.
- **States are written as people say them:** `submitted`, `working`, `completed`, `input-required`, `auth-required`, `failed`, `canceled`, `rejected`.
- **Secrets stay secret:** `${env:..}` values in the properties are masked in logs and failures, and `${token:..}` names a token of the scenario.

Add it to a project with `axx pack add a2a`.

## Steps

### `a2a.agent`

```gherkin
Given the {word} a2a agent with the following properties:
  | property | value |
```

The table may start with the row naming its columns, as above, or go straight to its rows.

Register an A2A agent under a name: its card is read and checked for what A2A 1.0 requires, and says how to reach it (JSON-RPC, HTTP+JSON or gRPC).

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

| Property | Takes | Values | Default |
|---|---|---|---|
| `url` | the agent's URL; its card is read at `/.well-known/agent-card.json` on its origin |  | |
| `card` | the agent's card, when it is not there: a file of the project, or a URL |  | |
| `transport` | how to reach the agent, among the interfaces its card lists | `JSONRPC`, `HTTP+JSON`, `GRPC` | `the card's first` |
| `header.<name>` | a header sent with every request, such as `header.Authorization` |  | |
| `timeout` | how long a call may take, like `10s` |  | `30s` |
| `push url` | where the agent sends its tasks' updates (a webhook, such as a WireMock the mock pack checks) |  | |
| `push token` | the token the agent sends with them, for the webhook to check |  | |

A `url` or a `card` is required. Values are expanded (`${env:..}`, `${sys:..}`, `${token:..}`); what `${env:..}` references expand to is masked everywhere.

**Example:**

```gherkin
Given the parcels a2a agent with the following properties:
  | url | http://localhost:8400 |
Given the carrier a2a agent with the following properties:
  | url                  | https://agents.carrier.example |
  | transport            | HTTP+JSON                      |
  | header.Authorization | Bearer ${token:carrier}        |
```

_Since 0.1.5._

### `a2a.card`

```gherkin
Then the {word} a2a agent's card has the following properties:
  | property | value |
```

The table may start with the row naming its columns, as above, or go straight to its rows.

Check the agent's card: what another agent reads to find out what it does and how to reach it.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

A row is a path into the card (`name`, `capabilities.streaming`, `skills[0].id`) and its value.

**Example:**

```gherkin
Then the parcels a2a agent's card has the following properties:
  | name                   | Parcels agent |
  | capabilities.streaming | true          |
```

_Since 0.1.5._

### `a2a.skill`

```gherkin
Then the {word} a2a agent has the {word} skill
```

Check that the agent's card lists a skill, by its id.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Example:**

```gherkin
Then the parcels a2a agent has the track-parcel skill
```

_Since 0.1.5._

### `a2a.send`

```gherkin
When a message is sent to the {word} a2a agent:
  """
  ...
  """
```

Send the doc string as a text message, which starts a conversation, and wait for the agent's answer: a reply, or a task that ended or waits for input.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Example:**

```gherkin
When a message is sent to the parcels a2a agent:
  """
  Where is PX-A2A-9201?
  """
```

_Since 0.1.5._

### `a2a.send.file`

```gherkin
When the {filepath} message is sent to the {word} a2a agent
```

Send the message of a file of the project, an A2A message in JSON (its `parts`: text, data, files), which starts a conversation, and wait for the agent's answer.

| Parameter | Takes | For example |
|---|---|---|
| `{filepath}` | a file of the project: a path relative to the feature file's directory, the `resources` directories or axx.yaml's directory (looked for in that order), or an absolute path, quoted when it has a space | `seeds/parcels.yaml`, `kafka/scan-delivered.json` |
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Example:**

```gherkin
When the a2a/hold-request.json message is sent to the parcels a2a agent
```

_Since 0.1.5._

### `a2a.stream`

```gherkin
When a message is streamed to the {word} a2a agent:
  """
  ...
  """
```

Send the doc string as a text message, which starts a conversation, and take the agent's answer as it streams: the checks read its updates as they come. The stream belongs to the scenario, which ends it when it ends.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Example:**

```gherkin
When a message is streamed to the parcels a2a agent:
  """
  Where is PX-A2A-9203?
  """
```

_Since 0.1.5._

### `a2a.reply`

```gherkin
When a reply is sent to the {word} a2a agent:
  """
  ...
  """
```

Send the doc string as a text message that continues the agent's last task: how a task that asks for input (`input-required`) gets it. Wait for the agent's answer.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Example:**

```gherkin
When a reply is sent to the parcels a2a agent:
  """
  2026-10-05
  """
```

_Since 0.1.5._

### `a2a.cancel`

```gherkin
When the {word} a2a agent is asked to cancel its task
```

Ask the agent to cancel its last task; check that it did with `the {word} a2a agent's task is canceled`. An agent that will not (a task that ended) fails the step with its error.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Example:**

```gherkin
When the parcels a2a agent is asked to cancel its task
```

_Since 0.1.5._

### `a2a.state`

```gherkin
Then [[within {duration} ]]the {word} a2a agent's task is {word}
```

Check the state of the agent's last task: `submitted`, `working`, `completed`, `input-required`, `auth-required`, `failed`, `canceled` or `rejected`.

- The check waits for a task still at work (10 seconds, or `within {duration}`), and fails at once for a task that ended or waits for input in another state.

| Parameter | Takes | For example |
|---|---|---|
| `{duration}` | a duration in seconds (`s`) or minutes (`m`) | `5s`, `2m` |
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

**Variants**, the parts in `[[...]]` said or left out:

- `the {word} a2a agent's task is {word}`
- `within {duration} the {word} a2a agent's task is {word}`

**Example:**

```gherkin
Then the parcels a2a agent's task is input-required
Then within 30s the parcels a2a agent's task is completed
```

_Since 0.1.5._

### `a2a.answer`

```gherkin
Then the {word} a2a agent's answer contains {string}
```

Check that the agent's answer has a text: its reply, or its task's status message and artifacts. It waits for a task still at work.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

**Example:**

```gherkin
Then the parcels a2a agent's answer contains 'out for delivery'
```

_Since 0.1.5._

### `a2a.artifact`

```gherkin
Then the {word} a2a agent's task has an artifact where:
  | property | value |
```

The table may start with the row naming its columns, as above, or go straight to its rows.

Check that an artifact of the agent's last task has the table's properties: `name`, `description`, `text` (its text parts), `data` (its first data part: `data.status`) and `parts`. It waits for a task still at work.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

A row is a path into the artifact, and its value.

**Example:**

```gherkin
Then the parcels a2a agent's task has an artifact where:
  | name        | parcel-status    |
  | data.status | OUT_FOR_DELIVERY |
```

_Since 0.1.5._

### `a2a.update`

```gherkin
Then [[within {duration} ]]the {word} a2a agent's stream received an update where:
  | property | value |
```

The table may start with the row naming its columns, as above, or go straight to its rows.

Check that the stream of the message streamed last sent an update with the table's properties.

- A status update has `kind` `status`, its `state` and its `message`; an artifact update has `kind` `artifact` and its `artifact` (`artifact.name`, `artifact.text`, `artifact.data.status`...).
- The check waits (10 seconds, or `within {duration}`), and fails at once when the stream has ended.

| Parameter | Takes | For example |
|---|---|---|
| `{duration}` | a duration in seconds (`s`) or minutes (`m`) | `5s`, `2m` |
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |

A row is a path into the update, and its value.

**Variants**, the parts in `[[...]]` said or left out:

- `the {word} a2a agent's stream received an update where:`
- `within {duration} the {word} a2a agent's stream received an update where:`

**Example:**

```gherkin
Then the parcels a2a agent's stream received an update where:
  | state   | working                  |
  | message | Looking up PX-A2A-9203   |
```

_Since 0.1.5._
