← Voltar à lista

Agent Card em A2A: exemplo JSON completo e análise dos campos

Um Agent Card é um documento JSON que indica a um agente cliente quem chamar, para onde enviar a tarefa e quais skills estão disponíveis. No protocolo A2A (Agent2Agent) o cartão costuma ser publicado em /.well-known/agent-card.json: sem ele o agente é difícil de descobrir; com uma descrição vaga, difícil de rotear bem.

  • Agent Card - contrato público das capacidades do agente
  • Discovery - localização do cartão via URL well-known ou registry
  • skills - habilidades concretas, não um genérico «sei fazer tudo»
  • capabilities - streaming, push, cartão estendido
  • security - esquemas de autenticação no estilo OpenAPI

Para que serve o Agent Card

A2A liga agentes independentes: um atua como cliente, outro como executor. Antes de enviar a tarefa, o cliente lê o cartão e responde:

  1. Este agente corresponde à intenção do utilizador?
  2. Que endpoint aceita tarefas?
  3. Que tipos MIME são suportados na entrada e na saída?
  4. É necessária autenticação e de que tipo?
  5. Há streaming de eventos e notificações webhook?

O cartão não é texto de marketing. Orquestradores e routers LLM analisam-no. Quanto mais precisos forem description, skills e examples, mais estável será a escolha do executor.

Exemplo JSON completo

Abaixo está um exemplo funcional para um agente que pesquisa produtos no site, calcula o preço e cria um pedido após confirmação do utilizador. Os campos usam camelCase, como nos cartões JSON típicos de A2A.

{
  "name": "Site Commerce Agent",
  "description": "Pesquisa produtos no catálogo do site, calcula preço e prazo de entrega, e cria um pedido após confirmação do utilizador. Trabalha com catálogo, carrinho-rascunho e estados de encomenda. Não processa pagamentos nem altera preços.",
  "version": "1.2.0",
  "protocolVersion": "0.3.0",
  "url": "https://api.example.com/a2a",
  "documentationUrl": "https://docs.example.com/a2a/commerce-agent",
  "iconUrl": "https://example.com/icons/commerce-agent.svg",
  "provider": {
    "organization": "Example Shop",
    "url": "https://example.com"
  },
  "capabilities": {
    "streaming": true,
    "pushNotifications": true,
    "stateTransitionHistory": true,
    "extendedAgentCard": false
  },
  "defaultInputModes": [
    "text/plain",
    "application/json"
  ],
  "defaultOutputModes": [
    "text/plain",
    "application/json"
  ],
  "skills": [
    {
      "id": "search-products",
      "name": "Pesquisa de produtos",
      "description": "Pesquisa produtos por consulta, categoria, preço e disponibilidade. Devolve candidatos com id, nome, preço e descrição curta.",
      "tags": ["catalog", "search", "products"],
      "examples": [
        "Encontra portáteis até 800 euros com entrega esta semana",
        "Mostra planos disponíveis para uma equipa de 20 pessoas"
      ],
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["application/json", "text/plain"]
    },
    {
      "id": "calculate-quote",
      "name": "Cálculo de orçamento",
      "description": "Calcula preço, impostos, envio e prazo para os itens e quantidades selecionados. Não cria a encomenda.",
      "tags": ["pricing", "quote", "shipping"],
      "examples": [
        "Calcula o custo de 3 unidades de product_id=sku-1042 com entrega em Berlim",
        "Compara os planos Basic e Pro para 50 utilizadores"
      ],
      "inputModes": ["application/json", "text/plain"],
      "outputModes": ["application/json"]
    },
    {
      "id": "create-lead",
      "name": "Criação de pedido",
      "description": "Cria um rascunho de lead ou pedido após confirmação explícita do utilizador. Exige contacto e consentimento para tratamento de dados.",
      "tags": ["lead", "order-draft", "crm"],
      "examples": [
        "Cria um pedido do plano Pro para a ACME, contacto: ops@acme.example",
        "Prepara um rascunho de encomenda a partir de quote_id=q-7781"
      ],
      "inputModes": ["application/json"],
      "outputModes": ["application/json", "text/plain"]
    },
    {
      "id": "get-order-status",
      "name": "Estado da encomenda",
      "description": "Devolve o estado de pagamento e entrega por order_id para um utilizador autenticado ou um número de tracking público.",
      "tags": ["orders", "status", "tracking"],
      "examples": [
        "Qual é o estado da encomenda ORD-20441?",
        "Onde está a encomenda com tracking TRK-998877?"
      ]
    }
  ],
  "securitySchemes": {
    "bearer": {
      "type": "http",
      "scheme": "bearer",
      "bearerFormat": "JWT"
    },
    "oauth2": {
      "type": "oauth2",
      "flows": {
        "clientCredentials": {
          "tokenUrl": "https://auth.example.com/oauth/token",
          "scopes": {
            "catalog:read": "Leitura de catálogo e orçamentos",
            "leads:write": "Criação de pedidos",
            "orders:read": "Leitura de estados de encomenda"
          }
        }
      }
    }
  },
  "security": [
    {
      "oauth2": ["catalog:read"]
    },
    {
      "bearer": []
    }
  ]
}

No A2A v1.0 o endpoint costuma ser descrito com o array supportedInterfaces em vez de um único url de topo. A ideia é a mesma: indicar para onde enviar tarefas e que binding usar (JSONRPC, HTTP+JSON, GRPC, etc.).

Fragmento de exemplo para v1.0:

{
  "supportedInterfaces": [
    {
      "url": "https://api.example.com/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ]
}

Análise dos campos de topo

Campo Obrigatório Finalidade
name Sim Nome legível do agente
description Sim Resumo concreto: o que faz e o que não faz
version Sim Versão da implementação (preferível semver)
url / supportedInterfaces Sim* Endpoint(s) de tarefas, não a URL do cartão
skills Sim Pelo menos um skill
capabilities Recomendado Flags honestas de capacidades
defaultInputModes / defaultOutputModes Recomendado MIME por omissão
provider Não Organização proprietária
documentationUrl / iconUrl Não Documentação e ícone para a UI
protocolVersion Depende do esquema Versão do protocolo (muitas vezes no topo em v0.3)
securitySchemes / security Não Como o cliente se deve autenticar

* Nos esquemas v0.3 url costuma ser obrigatório. No v1.0 o papel do endpoint passa para supportedInterfaces.

name e description

name serve a pessoas e logs. description é lida pelos routers. Mau: «Um agente útil para o site». Bom: listar operações, limites e formato do resultado.

version

É a versão da implementação do agente, não necessariamente a do protocolo. Incremente major em breaking changes de skills ou do contrato de resposta. Clientes podem cachear o cartão e atualizá-lo quando a versão muda.

url - erro frequente

url é o endereço para onde vão message/send / as tarefas. Não é o caminho para /.well-known/agent-card.json.

Errado:

"url": "https://example.com/.well-known/agent-card.json"

Correto:

"url": "https://api.example.com/a2a"

capabilities

Flag Significado
streaming Suporta respostas em streaming (SSE / stream)
pushNotifications Webhooks para tarefas longas
stateTransitionHistory Histórico de transições de estado da tarefa
extendedAgentCard Após auth há um cartão estendido/privado

Coloque true só se o comportamento estiver realmente implementado. Um cliente que abrir um stream contra um agente sem streaming receberá erro.

defaultInputModes e defaultOutputModes

MIME por omissão para todo o agente. Um skill pode sobrescrevê-los. Valores típicos: text/plain, application/json, application/pdf, image/png.

Análise de skills

Um skill é uma unidade de routing. Um skill = uma capacidade clara.

Campo Obrigatório Comentário
id Sim Único no agente; kebab-case funciona bem
name Sim Nome curto para a UI
description Sim O que aceita, o que devolve, que limites tem
tags Não Palavras-chave para pesquisa e filtragem
examples Não, mas muito recomendado 2-3 prompts reais para o orquestrador
inputModes / outputModes Não Override MIME deste skill

Os exemplos não são decoração. Sem eles o orquestrador adivinha as entradas só pela descrição e falha mais.

Skill mau:

{
  "id": "website",
  "name": "Website",
  "description": "Trabalha com o site"
}

Um skill bom é como no exemplo completo: id concreto, limites claros, tags e examples.

Autenticação: securitySchemes e security

Os esquemas costumam seguir a abordagem OpenAPI:

  • apiKey
  • http (Basic / Bearer)
  • oauth2
  • openIdConnect
  • mutualTLS

securitySchemes descreve os métodos disponíveis. security define o requisito por omissão:

  • vários objetos no array security = alternativas (OR);
  • várias chaves num mesmo objeto = é preciso tudo de uma vez (AND).

Publique como autenticar, não os segredos. Não coloque API keys, refresh tokens nem hostnames internos no JSON.

Discovery: como o cartão é encontrado

Fluxo típico:

  1. O cliente conhece o domínio base do agente.
  2. Pede https://agent.example.com/.well-known/agent-card.json.
  3. Valida os campos obrigatórios.
  4. Escolhe um skill por descrição, tags e examples.
  5. Autentica-se segundo security.
  6. Envia a tarefa para url / supportedInterfaces.

O cartão também é publicado em registries ou diretórios. Nesse caso o discovery passa por pesquisa, e o well-known continua a ser a fonte de verdade do proprietário.

Verificação local:

curl -s https://api.example.com/.well-known/agent-card.json

O que não publicar no Agent Card

  • API keys, passwords, private keys;
  • URLs internas de admin ou staging sem proteção;
  • operações indisponíveis a clientes externos;
  • capabilities infladas (streaming: true sem implementação);
  • skills vagos do tipo «faz tudo no site».

O cartão público é ao mesmo tempo superfície de ataque e de routing. Mantenha-o preciso e minimamente suficiente.

Erros frequentes

  1. Confundir url com a URL do cartão.
  2. Array skills vazio. O agente fica quase impossível de rotear.
  3. Descrição sem limites. Não se diz o que o agente não faz (pagamento, eliminação, alteração de preços).
  4. Sem examples. O orquestrador entende pior a entrada válida.
  5. localhost num cartão de produção. O endpoint tem de ser alcançável.
  6. Um único skill para todo o produto. Prefira vários skills estreitos com direitos e MIME diferentes.

Mini checklist antes de publicar

  1. O cartão é servido por HTTPS com Content-Type: application/json.
  2. Tem name, description, version, endpoint e pelo menos um skill.
  3. As descrições são concretas.
  4. Os skills-chave têm examples e tags.
  5. capabilities correspondem ao servidor real.
  6. O JSON não contém segredos.
  7. O endpoint do cartão responde a uma tarefa de teste.
  8. A versão sobe em breaking changes.

Conclusão

O Agent Card é o principal contrato de discovery no A2A. Um JSON completo com skills precisos, capabilities honestas e security explícita dá aos agentes cliente dados suficientes para encontrar o executor certo e não chamar o errado.

Se precisa de ajuda a desenhar um Agent Card, um servidor A2A ou a ligação de um agente à API do site - contacte-me.

Perguntas frequentes

Onde deve ficar o Agent Card?

O caminho público padrão é /.well-known/agent-card.json no domínio do agente. Também pode registá-lo num catálogo ou registry, mas a URL well-known continua a ser um ponto de discovery conveniente sem um índice separado.

Em que url difere do endereço do cartão?

O endereço do cartão serve para discovery; url (ou supportedInterfaces) para executar tarefas. O cliente primeiro lê o JSON e depois envia mensagens/tarefas para o endpoint de trabalho do agente.

Quantos skills deve ter um cartão?

Tantos quantas capacidades realmente distintas com entradas ou permissões diferentes. Em geral 3-7 skills estreitos são melhores do que um genérico «faz tudo». Para o routing importam limites claros, tags e examples.

A autenticação é obrigatória no Agent Card?

Nem sempre. Um agente público só de leitura pode omitir security. Para escrita, dados pessoais e operações pagas declare securitySchemes e security, e guarde os segredos fora do cartão.

É preciso atualizar o cartão em cada deploy?

Atualize quando mudarem skills, endpoint, capabilities, auth ou o significado do agente. Um patch técnico sem mudança de contrato pode refletir-se em version; breaking changes merecem major e documentação explícita.

Contato