# A2A agent

> Hand a video edit to Vidmoat from another agent over the Agent2Agent protocol: send a brief and a project, poll the task, read what was applied.

Vidmoat answers the [Agent2Agent protocol](https://a2a-protocol.org/latest/specification/) with one skill: edit a project from a brief. A task is the same server-side run of the editing agent that the Vidmoat editor starts, with the same gates, the same per-step credit charge and the same result on the timeline. Use MCP when your agent wants the individual tools; use A2A when it wants to delegate the whole edit.

| | |
| --- | --- |
| Agent Card | `https://vidmoat.com/.well-known/agent-card.json` (also on www, api and developer) |
| Endpoint | `https://api.vidmoat.com/api/a2a` |
| Binding | JSON-RPC 2.0 over `POST`, protocol `1.0` and `0.3` on the same URL |
| Methods | `SendMessage`, `GetTask`, `CancelTask` (0.3: `message/send`, `tasks/get`, `tasks/cancel`) |
| Auth | OAuth (the same authorization server as MCP) or a live API key, as a bearer token; a scoped credential needs `ai.agent` |
| Limits | 60 calls a minute per account, plus the agent's own limit (shared with every surface) and one live run per project |

## What it does not do

- **No streaming and no push notifications.** Both are `false` on the card. `SendMessage` returns the task at once, submitted; poll `GetTask` until it is completed, failed or canceled.
- **No file parts.** Upload media to the project first (MCP `upload_media` or `POST /v1/media`) and describe the edit in a text part. A file part is refused with `-32005`, not ignored.
- **No project creation.** Create one with MCP `create_project` or `POST /v1/projects` and pass its id.
- **No follow-up on a finished task.** Every task ends in a terminal state. Send a new message with `referenceTaskIds` naming the earlier task (up to three); the agent gets what was asked and what it said.
- **No batches** and no `ListTasks`. Keep the task ids you are given.
- **Test keys cannot start runs**, because runs spend real credits.
- Server-side runs need a plan that includes them (Creator and above) with server-side runs turned on for the account; otherwise `SendMessage` answers `-32000` with `data.code` `not_entitled` or `not_opted_in`.

## Send a brief

The project id goes in `message.metadata.projectId`, in a data part `{"projectId": "..."}`, or as the `contextId`. A context is one project: the task's `contextId` is always the project id.

```bash SendMessage
curl https://api.vidmoat.com/api/a2a \
  -H "Authorization: Bearer $VIDMOAT_API_KEY" \
  -H "A2A-Version: 1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", "id": 1, "method": "SendMessage",
    "params": { "message": {
      "messageId": "m-1", "role": "ROLE_USER",
      "parts": [{ "text": "Cut the silences and add bold captions." }],
      "metadata": { "projectId": "prj_123" }
    } }
  }'
```

```json The answer: a task, not yet started
{ "jsonrpc": "2.0", "id": 1, "result": { "task": {
  "id": "5d0c…", "contextId": "prj_123",
  "status": { "state": "TASK_STATE_SUBMITTED", "timestamp": "2026-10-26T12:00:00.000Z" },
  "metadata": { "projectId": "prj_123", "editorUrl": "https://www.vidmoat.com/editor?project=prj_123", "applied": 0, "attempted": 0 }
} } }
```

## Poll it

```json GetTask
{ "jsonrpc": "2.0", "id": 2, "method": "GetTask", "params": { "id": "5d0c…", "historyLength": 5 } }
```

A completed task carries the agent's closing message in `status.message`, its messages in `history`, and one artifact, `Edited project`, whose data part names the project, the editor link, the commands applied and attempted, and the credits left when the run last reported them. A failed task carries the reason in `status.message`.

`CancelTask` asks the run to stop at its next step boundary, so a half-applied batch never reaches the document. The task stays working (with `metadata.cancelRequested`) until it does, then reads canceled.

## Errors

| Code | When |
| --- | --- |
| `-32602` | No brief, no project, the brief is over 8000 characters (refused, never cut), or the project is not yours |
| `-32000` | Refused for a reason you can act on: rate limit, plan, opt-in, a run already live on the project (`data.taskId` names it), an account restriction, a missing `ai.agent` scope. `data.httpStatus` and `data.code` say which |
| `-32001` | No such task, or not yours |
| `-32002` | The task has already finished |
| `-32003`, `-32004` | Push notifications, streaming, `ListTasks`, or a message to a finished task |
| `-32005` | A file part |
| `-32009` | An `A2A-Version` other than 1.0 or 0.3 |

Google models are not used for runs started here, as for MCP, the REST API and the chat bots.

## Skills for your own agent

The editing craft the agent runs on is published as [Agent Skills](https://agentskills.io): the index is at `https://vidmoat.com/.well-known/agent-skills/index.json` (v0.2.0), each `SKILL.md` is served beside it with its sha256 digest in the index, and the source is the public repository [vidmoat/skills](https://github.com/vidmoat/skills).

---

Source: https://developer.vidmoat.com/developer/docs/a2a
Previous: [Plugins](https://developer.vidmoat.com/developer/docs/plugins.md)
Next: [Changelog](https://developer.vidmoat.com/developer/docs/changelog.md)
All documentation: https://developer.vidmoat.com/llms-full.txt
