ShvIA

Docs · Protocolos

Agente A2A

O ShvIA pode responder a outros agentes pelo protocolo Agent2Agent (A2A): outro agente envia uma pergunta e recebe uma resposta.

O que é#

Uma porta estreita. Um par envia texto; o ShvIA responde com um modelo que roda na infraestrutura do próprio operador. O modelo não recebe ferramentas, nem base de conhecimento, nem memória, nem anexos, e o par não pode escolher o modelo. Ele recebe a pergunta, as mensagens anteriores do mesmo contexto, as instruções-base da própria instalação e um breve prefácio que nomeia o par. Responde uma vez e de forma síncrona: não há streaming nem notificação push.

O turno roda como o administrador que registrou o par, e conta na cota desse administrador. A troca é guardada: cada contexto vira uma conversa na conta desse administrador, com o texto dos dois lados, e o administrador pode lê-la. Não envie nada que você não gostaria que ele lesse.

O cartão do agente#

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

/.well-known/agent.json devolve o mesmo cartão. Não exige autenticação.

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": []
}

O cartão acima está encurtado. Com um token de par válido, ele também lista a única skill, perguntar, e a versão do gateway.

Autenticação#

Envie o token do par como Authorization: Bearer shvia_a2a_…. O header X-API-Key não é aceito, e uma chave de API normal não abre esta porta: um token de par abre /a2a/v1 e mais nada.

Um token ausente, errado ou desligado devolve 401 com o código nao_autenticado. Cada par tem um teto de chamadas por minuto, 30 por padrão, definido pelo administrador. Acima dele, a chamada devolve 429 com limite_de_requisicoes e Retry-After. Há também um teto de 120 requisições por minuto por endereço no cartão e no endpoint, e acima dele a resposta é o simples {"message": "Too Many Attempts."}.

POST/a2a/v1#

Um endpoint JSON-RPC 2.0. Ele recebe um objeto de requisição por vez e responde a toda requisição, até a que não tem id.

MétodoResultado
SendMessage (ou message/send)roda o modelo e devolve {"task": …}
GetTask (ou tasks/get)devolve uma tarefa que este par criou. As tarefas são guardadas por 24 horas
CancelTask (ou tasks/cancel)sempre falha: as tarefas terminam antes de você poder cancelá-las
métodos de streaming, de assinatura, de listagem e de pushnão suportados, erro -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" }] }]
    }
  }
}

A mensagem#

  • As partes com um text são unidas com quebras de linha. As partes com data viram texto JSON compacto. As partes de arquivo e de URL são ignoradas. Uma mensagem sem nenhum texto é recusada com -32005.
  • contextId é opcional, de 1 a 128 caracteres entre letras, dígitos e ._:-. Envie o mesmo para continuar uma conversa: as últimas 20 mensagens, cerca de 10 trocas, são reenviadas. Sem um, o servidor inventa um.
  • O texto acima de 65536 bytes é cortado, com uma marca no final.

Estados da tarefa#

EstadoSignificado
TASK_STATE_COMPLETEDrespondida. O texto está em status.message e em artifacts
TASK_STATE_REJECTEDo administrador por trás do par não pode usar o modelo que responde, ou esgotou um limite de tokens. O motivo está em status.message
TASK_STATE_FAILEDo modelo não conseguiu responder. Tente de novo

Uma tarefa nunca fica em WORKING nem em SUBMITTED: a chamada é síncrona.

Erros#

Os erros de requisição são erros JSON-RPC dentro de um HTTP 200: -32700 não é JSON, -32600 uma requisição ruim ou um lote, -32601 um método desconhecido, -32602 parâmetros ruins, -32603 uma falha interna (por exemplo, nenhum modelo on-premises disponível), -32001 uma tarefa desconhecida, -32002 uma tarefa que não pode ser cancelada, -32004 uma operação não suportada e -32005 uma mensagem sem texto.