MCP & agents / A2A

# A2A agents

Reach the gateway from other agents over the Agent2Agent protocol: an Agent Card for discovery, tasks for every message, the final price on every run.

`POST` `/v1/a2a` `inference:invoke`

Yelno answers Agent2Agent (A2A 0.3) JSON-RPC requests as an agent with one skill, `chat`: it runs your message on the model you name, under your organization's routing policy, guardrails, limits and balance, and charges it at the model's final price. Every run is an ordinary request; its id is in the task's `metadata.yelno.request_ids`.

## Agent Card

Agents discover Yelno at `https://yelno.ai/.well-known/agent-card.json` (also served at `/.well-known/agent.json`). The card is public; every call to the endpoint needs an API key as a bearer token.

## Send a message

Name the model in `metadata.model` (a model id from `GET /v1/models`). Text parts are sent as text and data parts as JSON text. To continue a conversation, send the next message with the same `contextId`: earlier tasks of that context are included as history while their content is kept.

Send a message

```
curl https://yelno.ai/v1/a2a \
  -H "Authorization: Bearer $YELNO_API_KEY" -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "message/send", "params": {
        "message": {"role": "user", "messageId": "m-1",
                    "parts": [{"kind": "text", "text": "Summarize this ticket: ..."}]},
        "metadata": {"model": "MODEL"}}}'
```

Task

```
{
  "kind": "task", "id": "a2at_…", "contextId": "a2ac_…",
  "status": {"state": "completed", "timestamp": "…"},
  "history": [{"role": "user", "parts": [{"kind": "text", "text": "Summarize this ticket: ..."}], …}],
  "artifacts": [{"artifactId": "a2at_…-answer", "name": "answer", "parts": [{"kind": "text", "text": "…"}]}],
  "metadata": {"yelno": {"model": "MODEL", "request_ids": ["req_…"], "content_retained": true,
                         "expires_at": "…", "cost": {"state": "final", "currency": "USD", "amount": "0.000412"}}}
}
```

## Methods

| Method | What it does |
| --- | --- |
| message/send | Run a message and return the task. configuration.blocking: false returns at once; poll tasks/get. |
| message/stream | The same over server-sent events: the task, working, answer chunks as artifact updates, then the final status with the charge. |
| tasks/get | A task by id, with historyLength to trim its history. |
| tasks/cancel | Stop a task that has not ended; usage up to that point is charged. |
| not offered | Push notifications (-32003), tasks/resubscribe and continuing an ended task (-32004), file parts (-32005). |

A task refused before any model ran (your policy, balance, budget, rate limit or a guardrail) ends `rejected`; a provider failure ends `failed`. Either way `status.message` says why and `metadata.yelno.error_code` names it.

## What is stored, and for how long

- A task's state, model and request ids are kept for 24 hours, then deleted with everything else about the task.
- The task's messages and answer are kept encrypted for that time so `tasks/get` can return them, and only when your organization allows content to be kept. If your policy requires zero data retention or a retention ceiling of 0 days, no content is stored: the answer comes back only in the response that produced it, and the task says `content_retained: false`.

Source: https://yelno.ai/docs/a2a
