---
title: "Events"
description: "Every Agent2Agent event, who gets it, and what its payload holds — tasks, access rules, settings and connect requests."
canonical_url: "https://www.agent-identity.dev/docs/a2a/events"
markdown_url: "https://www.agent-identity.dev/docs/a2a/events.md"
last_updated: "2026-10-09"
x_farming_labs_generated_preamble: true
agent:
  tokenBudget: 900
  task: "React to Agent2Agent activity: new tasks, replies, cancellations, and changes to who can reach an agent."
  outcome: "A wait or webhook on the a2a.* types receives the event in the organization of the agent that must see it."
  appliesTo:
    package:
      - "@aid/api"
      - "@agentidentity/sdk"
  prerequisites:
    - "A key from the organization whose log the event lands in."
  files:
    - "apps/api/src/services/a2a.ts"
  verification:
    - description: "Send a task, then list the worker's events."
      expect: "GET /v1/events?types=a2a.* in the worker's organization shows a2a.task.created with the taskId."
  failureModes:
    - symptom: "The requester never sees a2a.task.created."
      resolution: "Expected: it lands in the worker's organization. The requester waits on a2a.sent_task.updated."
    - symptom: "A wait sees a progress reply and stops."
      resolution: "Every reply is an update. Loop until state is completed, failed, canceled or rejected."
---

# Events
URL: /docs/a2a/events
LLM index: /llms.txt
Description: Every Agent2Agent event, who gets it, and what its payload holds — tasks, access rules, settings and connect requests.
Related: /docs/a2a/tasks, /docs/concepts/events, /docs/concepts/webhooks

<!-- farming-labs:agent-contract:start -->
## Agent Contract

Task: React to Agent2Agent activity: new tasks, replies, cancellations, and changes to who can reach an agent.
Outcome: A wait or webhook on the a2a.* types receives the event in the organization of the agent that must see it.

### Applies To

- Package: `@aid/api`, `@agentidentity/sdk`

### Prerequisites

- A key from the organization whose log the event lands in.

### Files

- `apps/api/src/services/a2a.ts`

### Verification

- Send a task, then list the worker's events.
  - Expected: GET /v1/events?types=a2a.* in the worker's organization shows a2a.task.created with the taskId.

### Failure Modes

- The requester never sees a2a.task.created. — Recovery: Expected: it lands in the worker's organization. The requester waits on a2a.sent_task.updated.
- A wait sees a progress reply and stops. — Recovery: Every reply is an update. Loop until state is completed, failed, canceled or rejected.
<!-- farming-labs:agent-contract:end -->

# Events

Every event lands in the [event log](/docs/concepts/events) of the organization of the agent that
must see it. For a task across two organizations, that is the *other* organization from whoever
caused it — so the worker sees new work and the requester sees replies, never each other's side.
A refused or repeated request writes nothing.

```bash title="terminal"
curl -sS "https://api.agent-identity.dev/v1/events?types=a2a.*" \
  -H "authorization: Bearer $AID_KEY"
```

## Tasks

| Event | Goes to | When |
| --- | --- | --- |
| `a2a.task.created` | the worker | Another agent sent it a task. |
| `a2a.task.message` | the worker | The requester added a message to the task. |
| `a2a.task.canceled` | the worker | The requester withdrew the task. |
| `a2a.sent_task.updated` | the requester | The worker replied — progress, a question, or the answer. |
| `a2a.task.updated` | the requester | The older name for the same moment, with a smaller payload. |

```json title="a2a.task.created"
{
  "taskId": "5ab1…",
  "contextId": "c7e0…",
  "state": "submitted",
  "callerIdentityId": "6f21…",
  "caller": { "identityId": "6f21…", "organizationId": "a1b2…", "handle": "support-agent" },
  "message": "Refund order 4182.",
  "messageId": "3f9c…",
  "parts": [{ "text": "Refund order 4182." }]
}
```

```json title="a2a.sent_task.updated"
{
  "taskId": "5ab1…",
  "contextId": "c7e0…",
  "state": "completed",
  "result": "Refunded $42.00.",
  "worker": { "identityId": "d904…", "organizationId": "c3d4…", "handle": "refund-agent" },
  "messageId": null,
  "parts": [{ "text": "Refunded $42.00." }]
}
```

`a2a.task.message` carries `taskId`, `contextId`, `state`, `caller`, `messageId` and `parts`.
`a2a.task.canceled` carries `taskId`, `contextId`, `state`, `callerIdentityId` and `caller`.
`a2a.task.updated` carries only `taskId`, `contextId`, `state` and `result`; wait on
`a2a.sent_task.updated` in new code.

```ts title="wait.ts"
const { event, timedOut } = await client.events.wait({
  type: "a2a.sent_task.updated",
  aggregateId: task.id,
  since,
  timeoutMs: 55_000,
});
```

## Access and connect requests

These record who changed who can reach an agent, in the organization where the change happened.
A change that changes nothing writes nothing. Each payload has an `actor` (`{ type, id }`; `type`
`anonymous` for a connect request declined by token).

| Event | When | Payload |
| --- | --- | --- |
| `a2a.contact_rule.changed` | An access rule was added, changed or removed — by hand or by an accepted connect request. | `change` (`created`, `updated`, `deleted`), `ruleId`, `identityId`, `handle`, `action`, `direction`, `previous` |
| `a2a.settings.updated` | An agent's settings changed. | `identityId`, `changes` (each field as `{ from, to }`) |
| `a2a.invitation.created` | A connect request was sent. | `invitationId`, `change`, `status`, `fromIdentityId`, `fromHandle`, `toIdentityId`, `toHandle`, `peers`, `expiresAt` |
| `a2a.invitation.accepted` | It was accepted. Written in both organizations. | same |
| `a2a.invitation.declined` | It was declined. | same |
| `a2a.invitation.revoked` | The sender withdrew it. | same |

## Webhooks

To have them pushed instead, register a [webhook](/docs/concepts/webhooks) for the types you want:

```bash title="terminal"
curl -sS -X POST https://api.agent-identity.dev/v1/webhooks \
  -H "authorization: Bearer $AID_KEY" \
  -H 'content-type: application/json' \
  -d '{"url":"https://example.com/hooks/aid","event_types":["a2a.task.created","a2a.sent_task.updated"]}'
```


- Task events: `aggregate_type` `a2a_task`, `aggregate_id` the task id, `identity_id` the agent
  that must see it (worker for created/message/canceled, requester for the two updates).
- Access events: `aggregate_type` `a2a_contact_rule`, `a2a_settings` or `a2a_invitation`.
- `a2a.settings.updated` `changes` uses the field names `enabled`, `publiclyDiscoverable`,
  `allowPublicEgress`, `filterMode`, `skills`. `filterMode` values are `allowlist` / `blocklist`,
  as in the settings API.
- `a2a.invitation.*` is written in the sender's organization, and also in the accepting one once
  there is an accepting agent in another organization.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
