# A2A

> How OWG hands a task to another organization's agent over the Agent2Agent protocol, and keeps the meaning, the authority and the record that the protocol leaves out.

**Status:** draft, needs v0.93. Three additive fields: the `a2a` executor type, `participant.agent_card` and `task.delegation`. Publishing a workflow *as* an A2A agent needs no schema change at all.

## What A2A is

The [Agent2Agent protocol](https://a2a-protocol.org/) (A2A) lets one organization's agent find another organization's agent and hand it a task, whoever built either one. It reached v1.0 in April 2026 with signed Agent Cards and is governed in the open alongside the Model Context Protocol.

A job crosses in four moves:

1. **Discover.** The caller fetches the remote agent's **Agent Card** from `https://<domain>/.well-known/agent-card.json`. It names the agent, its **skills**, the transports it speaks and how to authenticate. A signed card proves who published it.
2. **Send.** The caller sends a message; the remote agent opens a **task** with its own id.
3. **Follow.** The task moves through `submitted`, `working`, `input-required`, `auth-required`, and ends `completed`, `failed`, `canceled` or `rejected`. The caller polls, streams, or receives push notifications.
4. **Collect.** Results come back as **artifacts**. The remote agent's tools and reasoning stay private.

MCP connects an agent to tools it directs. A2A connects an agent to another agent that decides how to do the job. Both belong in a production; OWG already had an `mcp` executor, and v0.93 adds `a2a` beside it.

## What A2A leaves out, and OWG supplies

The protocol moves the job. It deliberately does not say three things a production needs:

| Question | A2A | OWG |
|---|---|---|
| What does this task mean? | A message with text or data | The task, its inputs, outputs and assets, in a vocabulary aligned with [OMC](/standards-bindings#omc-the-vocabulary-not-a-neighbour) |
| Who may ask for it, on whose say-so? | Each hop authenticates its own caller | [`operated_by` and `works_for`](/participants-and-authority#agent-authority) on the remote agent, and `task.delegation` on the hand-off |
| What happened across the whole chain? | Status and artifacts per task | One [run record](/runs#remote-attempts) across every hop, with the actual performer of each attempt |

That division is the binding: A2A is the transport, OWG is what travels in it and what is kept afterwards.

## The hooks

**Outbound: a task performed by another party's agent.**

```json
{
  "participants": [
    { "id": "ops_lead", "kind": "human", "works_for": "org_studio",
      "identity": { "id": "urn:studio:ops-lead", "credential_scope": ["read:masters", "write:deliverables"] } },
    { "id": "vendor_dub_agent", "kind": "agent", "works_for": "org_vendor",
      "agent_card": "https://agents.vendor.example/.well-known/agent-card.json" }
  ],
  "tasks": [
    { "id": "localize_audio",
      "executor": { "type": "a2a", "ref": "localize-dub" },
      "ai_role": "generative",
      "performed_by": "vendor_dub_agent",
      "delegation": { "by": "ops_lead", "scope": ["read:masters"], "expires_at": "2026-12-31T23:59:59Z" },
      "used": ["masters"], "produced": ["dub_tracks"] }
  ]
}
```

| Field | Holds |
|---|---|
| `executor.type: "a2a"` | The task is delegated to another party's agent |
| `executor.ref` | The skill id on that agent's Agent Card |
| `performed_by` | The remote agent, as a participant. Required |
| `participant.agent_card` | Where that agent's card is published. Identifies it; grants it nothing |
| `task.delegation.by` | Who on the sending side handed the task across |
| `task.delegation.scope` | What the remote agent may do with the task's inputs |
| `task.delegation.expires_at` | When that authority lapses, independent of completion |

**Inbound: publishing a workflow as an agent.** No schema change. A definition already carries what a card needs: its `id` becomes the skill id, its `objective` the skill description, and its `params` the inputs a caller must supply. The organization offering the work is the card's provider. The card describes capability only; it never names the executors, vendors or infrastructure behind the tasks.

## How it maps

| A2A | OWG |
|---|---|
| Agent Card | `participant.agent_card` on the remote agent (outbound); derived from the definition (inbound) |
| Skill | `executor.ref` (outbound); the definition's `id`, `objective` and `params` (inbound) |
| Task | One attempt of an OWG task, holding the remote `task_id` |
| Context (a series of related tasks) | `remote.context_id` on each attempt |
| `input-required`, `auth-required` | Attempt `running`, with `remote.state` showing the wait |
| `completed` | Attempt `succeeded` |
| `failed`, `canceled`, `rejected` | Attempt `failed`, with distinct error codes |
| Artifacts | Assets in the task's `produced[]` |
| The caller's identity | `task.delegation.by`, traced up its `operated_by` chain |

## Authority across organizations

A studio hands a season to a production company's agent, which hands the dubbing to a vendor's agent. Each hop is a task with a `delegation`, and the vendor's output traces back by document fields alone:

`dub_ep1` → produced by `vendor_agent` → delegated by `prodco_agent` → delegated by `exec` (a person at the studio)

**Authority only narrows.** When a delegator declares an `identity.credential_scope`, a delegation from it may grant only a subset; anything wider is a validation error (`OWG_DELEGATION_WIDENS`). The production company can pass on less than the studio gave it, never more. Like every scope in OWG this is declared, not enforced: the systems on each side must still check it. Work on standard delegated credentials for agents is under way at the IETF; `delegation` is where such a credential would be recorded.

## Reference workflow

[`a2a-deal-to-delivery.owg.json`](/corpus/a2a-deal-to-delivery.owg.json): a sales team's assistant hands a closed licensing deal to media operations. Media operations runs it with three vendors reached three ways (an API, an MCP tool and another organization's agent over A2A), archives the result, and confirms delivery back to the sales assistant over A2A.

```bash
curl -O https://openworkflowgraph.org/corpus/a2a-deal-to-delivery.owg.json
owg-validate a2a-deal-to-delivery.owg.json --json
```

**What to take from it:**

- The intake task records the sales assistant as `delegation.by`: the inbound hand-off is in the record, not only in a log.
- API, MCP and A2A vendors differ only in `executor.type`. Their outputs converge in one archive task and one lineage.
- Every agent traces to a person, through `operated_by` or a department's `works_for`.

## What stays in A2A

OWG does not reimplement discovery, transport, streaming, push notifications or card signing. Those are A2A's, and an implementation uses an A2A SDK for them. OWG holds which agent was called, for what, on whose authority, and what came back.

## Known gaps

- `delegation.scope` strings are not yet a shared vocabulary. Two organizations must agree what `read:masters` means.
- The validator checks scope narrowing only when the delegator declares a `credential_scope`. An undeclared scope is not second-guessed.
- A2A runs between agents. A task handed to a person at another organization is a [turnover](/subgraphs-and-turnovers), and can carry `delegation` too.
- v0.93 is a draft, pending review.

See also: [Participants and authority](/participants-and-authority), [Subgraphs and turnovers](/subgraphs-and-turnovers), [Run records](/runs), [Security model](/security-model), [Standards bindings](/standards-bindings).
