ShvIA

Docs · Protocols

A2A agent

ShvIA can answer other agents over the Agent2Agent (A2A) protocol: another agent sends one question, and gets one answer.

What it is#

A narrow door. A peer sends text; ShvIA answers with a model that runs on the operator's own infrastructure. The model gets no tools, no knowledge base, no memory and no attachments, and the peer cannot choose the model. It gets the question, the earlier messages of the same context, the installation's own base instructions and a short preface that names the peer. It answers once and synchronously: there is no streaming and no push notification.

The turn is run as the administrator who registered the peer, and counts toward that administrator's quota. The exchange is stored: each context becomes a conversation in that administrator's account, with the text of both sides, and the administrator can read it. Send nothing you would not want them to read.

The agent card#

GET/.well-known/agent-card.json#

/.well-known/agent.json returns the same card. It needs no authentication.

json
{
  "name": "ShvIA",
  "description": "…",
  "url": "https://ai.shvia.org/a2a/v1",
  "protocolVersion": "1.0",
  "supportedInterfaces": [{ "url": "https://ai.shvia.org/a2a/v1", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" }],
  "capabilities": { "streaming": false, "pushNotifications": false, "stateTransitionHistory": false, "extendedAgentCard": false },
  "securitySchemes": { "bearer": { "httpAuthSecurityScheme": { "scheme": "bearer" } } },
  "securityRequirements": [{ "schemes": { "bearer": { "list": [] } } }],
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"],
  "skills": []
}

The card above is shortened. With a valid peer token, it also lists the one skill, perguntar, and the version of the gateway.

Authentication#

Send the peer token as Authorization: Bearer shvia_a2a_…. The header X-API-Key is not accepted, and a normal API key does not open this door: a peer token opens /a2a/v1 and nothing else.

A missing, wrong or switched-off token returns 401 with the code nao_autenticado. Each peer has a ceiling of calls per minute, 30 by default, set by the administrator. Past it, the call returns 429 with limite_de_requisicoes and Retry-After. There is also a ceiling of 120 requests per minute per address on the card and on the endpoint, and past that the answer is the plain {"message": "Too Many Attempts."}.

POST/a2a/v1#

A JSON-RPC 2.0 endpoint. It takes one request object at a time and answers every request, even one without an id.

MethodResult
SendMessage (or message/send)runs the model and returns {"task": …}
GetTask (or tasks/get)returns a task that this peer created. Tasks are kept for 24 hours
CancelTask (or tasks/cancel)always fails: tasks finish before you can cancel them
streaming, subscription, listing and push methodsnot supported, error -32004
json
{
  "jsonrpc": "2.0",
  "id": "r1",
  "method": "SendMessage",
  "params": {
    "message": {
      "role": "ROLE_USER",
      "messageId": "m-1",
      "parts": [{ "text": "What is the capital of Bahia?", "mediaType": "text/plain" }]
    }
  }
}
json
{
  "jsonrpc": "2.0",
  "id": "r1",
  "result": {
    "task": {
      "id": "task-3f2a9c1b7d4e5a60",
      "contextId": "ctx-0a1b2c3d4e5f6071",
      "status": {
        "state": "TASK_STATE_COMPLETED",
        "timestamp": "2026-10-10T12:00:00.000Z",
        "message": { "role": "ROLE_AGENT", "parts": [{ "text": "Salvador.", "mediaType": "text/plain" }], "messageId": "…", "contextId": "ctx-0a1b2c3d4e5f6071", "taskId": "task-3f2a9c1b7d4e5a60" }
      },
      "artifacts": [{ "artifactId": "…", "parts": [{ "text": "Salvador.", "mediaType": "text/plain" }] }]
    }
  }
}

The message#

  • Parts with a text are joined with line breaks. Parts with data become compact JSON text. File and URL parts are ignored. A message with no text at all is refused with -32005.
  • contextId is optional, 1 to 128 characters of letters, digits and ._:-. Send the same one to continue a conversation: the last 20 messages, about 10 exchanges, are replayed. Without one the server makes one up.
  • Text over 65536 bytes is cut, with a marker at the end.

Task states#

StateMeaning
TASK_STATE_COMPLETEDanswered. The text is in status.message and in artifacts
TASK_STATE_REJECTEDthe administrator behind the peer may not use the answering model, or has used up a token limit. The reason is in status.message
TASK_STATE_FAILEDthe model could not answer. Try again

A task is never WORKING or SUBMITTED: the call is synchronous.

Errors#

Request errors are JSON-RPC errors inside an HTTP 200: -32700 not JSON, -32600 a bad request or a batch, -32601 an unknown method, -32602 bad parameters, -32603 an internal failure (for example, no on-premises model is available), -32001 an unknown task, -32002 a task that cannot be cancelled, -32004 an unsupported operation and -32005 a message without text.