> ## Documentation Index
> Fetch the complete documentation index at: https://agents.nanonets.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent marketplaces (A2A)

> List an agent on an A2A marketplace and let other platforms run it with a key you issue.

[A2A (Agent2Agent)](https://a2a-protocol.org) is an open protocol that agent marketplaces use to
discover agents and call them. Any agent can be exposed over A2A **v1.0**, using the **JSON-RPC**
binding. The marketplace gets one URL per agent and a key that works for that agent only.

## Turn it on

1. Open the agent, go to the **API** tab, and switch on **List on agent marketplaces (A2A)**.
2. **Publish** the agent. The listing follows the published version, so it goes live, or comes
   down, with the next publish.
3. Under **Marketplace keys**, create a key. It is shown once; copy it then.

Until all three are done, both URLs below answer `404`, the same as for an agent that does not
exist.

## What the marketplace needs

| | |
| - | - |
| Agent card URL | `https://<your host>/api/v1/a2a/agents/<agent_id>/.well-known/agent-card.json` |
| API key | The marketplace key, in the `X-API-Key` header. `Authorization: Bearer` also works; when both are sent, `X-API-Key` is used |
| Protocol | A2A `1.0`, JSON-RPC. Send `A2A-Version: 1.0`; a request without the header is accepted when its method is a v1.0 method |

`<agent_id>` is the agent's group id. It stays the same across publishes, so the marketplace
never needs a new URL.

## What a marketplace key can do

A marketplace key is scoped to one agent:

* It works only on that agent's A2A endpoint. Every other API refuses it with `401`.
* A caller using it sees only the runs it started. Other callers' runs, and runs started in the
  app, answer `TaskNotFoundError`.
* It cannot be given a role.
* Each agent can have up to 10 marketplace keys. They do not count toward the workspace's own API key limit.

Runs started over A2A appear in your workspace like any other run, with source `a2a`, and are
billed to your workspace. Revoke a key from the same tab, or from **Settings → API keys**.

## Supported methods

| Method | Behaviour |
| - | - |
| `SendMessage` | Starts a run, or continues one when `message.taskId` is set. Waits for the result unless `configuration.returnImmediately` is true; if the run outlasts the wait, the task comes back `TASK_STATE_WORKING` and you poll `GetTask`. |
| `SendStreamingMessage` | Same, as a Server-Sent Events stream: the task, a status update on each state change, the result, then the final status. Streams stay open for up to 30 minutes and send a keep-alive every 15 seconds. When the server is at its stream limit, the stream sends the task and closes; poll `GetTask` for the rest. |
| `GetTask` | Current state and results. Pass `historyLength` for the conversation. |
| `CancelTask` | Stops a run. A finished run answers `TaskNotCancelableError`. |

`SubscribeToTask`, `ListTasks`, `GetExtendedAgentCard` and push notifications are not supported;
the agent card says so.

## Messages and results

**In.** Text parts become the request. `data` parts are passed to the agent as JSON. Files go
inline as `raw` (base64) parts, or as `url` parts pointing at a public `https://` address that
is downloaded before the run starts. Each file can be up to 20 MB, and a request up to 64 MB.

**Retries.** A message is identified by its `messageId`. Sending the same message again with the
same key and `messageId` returns the task the first one started; it does not start a second
run or add the reply twice. Reusing a `messageId` for a different message is an error.

**Out.** A finished run returns its result as an artifact: text for a summary, JSON for
structured output, chosen by the agent's **Synchronous run result** setting. Files the run
produced come back as download links.

**Questions.** When the agent asks the caller something, the task goes to
`TASK_STATE_INPUT_REQUIRED` with the question in `status.message`. Answer with `SendMessage` on
the same `taskId` (a `contextId` on the reply is optional; the task keeps its own). Pauses that something else resolves, such as an owner's review or a
background wait, stay `TASK_STATE_WORKING`.

| Agent status | A2A state |
| - | - |
| Pending, queued | `TASK_STATE_SUBMITTED` |
| Running, in review | `TASK_STATE_WORKING` |
| Waiting on the caller | `TASK_STATE_INPUT_REQUIRED` |
| Completed | `TASK_STATE_COMPLETED` |
| Failed | `TASK_STATE_FAILED` (with a generic message; details stay in the app) |
| Stopped | `TASK_STATE_CANCELED` |

## Example

```bash theme={null}
curl -N https://<your host>/api/v1/a2a/agents/<agent_id> \
  -H "X-API-Key: $MARKETPLACE_KEY" \
  -H "A2A-Version: 1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", "id": 1, "method": "SendStreamingMessage",
    "params": { "message": {
      "messageId": "m-1", "role": "ROLE_USER",
      "parts": [{ "text": "Check this expense: hotel, USD 310, client workshop." }]
    } }
  }'
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.