Documentação oficial desta página · v0.20.6
A2A (Agente para Agente)
O A2A é o protocolo aberto Agent2Agent (v1.0, mantido pela Linux Foundation) para comunicação entre agentes de IA independentes. O plugin de A2A do Hermes funciona nos dois sentidos: o seu agente pode chamar outros agentes A2A como ferramentas, e outros agentes podem mandar tarefas para o seu Hermes por HTTP.
Ele conversa com qualquer par compatível com A2A — outro Hermes, LangChain, CrewAI, agentes do
Google ADK ou qualquer coisa construída sobre o a2a-sdk oficial.
Quando usar A2A
- Hermes ↔ Hermes entre máquinas — deixe o agente do seu desktop passar tarefas a um Hermes num servidor, ou o contrário, cada um com memória, ferramentas e credenciais próprias.
- Delegar a agentes especialistas — um par que anuncia skills de
web_search/research/codingno Cartão de Agente dele pode ser descoberto e chamado no meio da conversa. - Ser um serviço chamável — exponha o seu Hermes para que agentes de outros frameworks mandem tarefas a ele.
Quando você quer vários agentes na mesma máquina, prefira a delegação (subagentes no mesmo processo) ou o quadro kanban (fila de trabalho durável com vários perfis) — o A2A é para cruzar fronteiras de processo, de máquina ou de framework.
Ligar
hermes gateway setup # escolha A2A
Ou no ~/.hermes/config.yaml:
gateway:
platforms:
a2a:
enabled: true
extra:
port: 9900
As ferramentas de cliente de saída vêm no conjunto a2a, desligado por padrão — ligue por
plataforma:
hermes tools enable a2a --platform cli # sessões de CLI/TUI
hermes tools enable a2a --platform telegram # ou qualquer plataforma de mensagem
hermes tools enable a2a --platform a2a # deixa tarefas A2A que chegam chamarem outros pares (encadeamento de agentes)
As ferramentas ficam disponíveis em todo tipo de processo — CLI, TUI, gateway e cron — sem necessidade de ligar a plataforma de entrada.
Saída: chamar outros agentes
Com o conjunto de ferramentas a2a ligado, o agente ganha:
| Ferramenta | O que faz |
|---|---|
a2a_discover(url) | Busca e resume o Cartão de Agente de um par |
a2a_call(agent, message, context_id?) | Manda uma tarefa e recebe a resposta; várias rodadas via context_id |
a2a_list() | Pares configurados, conversas salvas e métricas |
a2a_history(context_id) | Recupera uma conversa A2A persistida |
a2a_orchestrate(capability, message, mode?) | Espalha uma tarefa para todo par que anuncia uma capacidade (all / first / best) |
Configure os pares conhecidos no config.yaml:
a2a_agents:
researcher:
url: "http://caixa-de-pesquisa.local:9900"
auth: { type: bearer, token: "..." }
timeout: 120
capabilities: [web_search, research]
Aí é só pedir: "Peça ao agente researcher para resumir as publicações de hoje no arXiv." URLs
diretas também funcionam — o a2a_call aceita qualquer endpoint A2A.
Entrada: ser chamável
Com a plataforma ligada, o Hermes serve:
- Cartão de Agente em
GET /.well-known/agent-card.json(o caminho canônico da v1.0; o antigoagent.jsontambém responde) — anuncia o nome do seu agente, as skills (derivadas dos conjuntos de ferramentas ligados) e as exigências de autenticação. - JSON-RPC 2.0 em
POST /— métodos canônicos da v1.0 (SendMessage,SendStreamingMessage,GetTask,ListTasks,CancelTask,SubscribeToTask, CRUD da configuração de notificação push) mais os apelidos em formato de caminho anteriores à 1.0 (message/send, …). - Streaming por SSE para o
SendStreamingMessage, com quadros envelopados em JSON-RPC conforme a especificação. - Notificações push (webhooks) para tarefas longas, assinadas com HMAC-SHA256.
As tarefas que chegam são injetadas numa sessão de gateway viva — o mesmo agente, a mesma
memória e as mesmas ferramentas que atendem os seus outros canais — e a resposta final volta a quem
chamou como resultado da tarefa. As conversas são indexadas pelo contextId do A2A, então um par
consegue manter uma troca de várias rodadas.
A interoperabilidade é verificada contra o a2a-sdk oficial em Python (resolução de cartão,
SendMessage e streaming).
Modelo de segurança
Seguro por padrão; cada passo que amplia o alcance é explícito:
- Sem token ⇒ só localhost. O servidor escuta em
127.0.0.1. Expor para fora exige um token bearer e umA2A_HOSTexplícito. - Tokens por par —
A2A_PEER_TOKENS="alice:tok1,bob:tok2"dá a cada par uma credencial própria; o nome autenticado comanda o limite de taxa, a confiança e a auditoria. - Filtro de injeção de prompt — o texto que chega é filtrado e enquadrado como entrada não confiável de um par. Pares remotos não conseguem invocar comandos de barra de operador.
- Redação na saída — strings com cara de credencial (chaves de API, JWTs, tokens) são apagadas das respostas.
- Log de auditoria — toda troca é anexada a
~/.hermes/a2a_audit.jsonl. - Anti-laço — tetos de rodadas por contexto impedem que dois agentes fiquem batendo bola para sempre.
Referência de configuração
| Variável de ambiente | Padrão | Significado |
|---|---|---|
A2A_PEER_TOKENS | (não definida) | Credenciais por par no formato nome:token,… (preferido) |
A2A_BEARER_TOKEN | (não definida) | Token compartilhado; a identidade recai no IP de quem chama |
A2A_HOST | 127.0.0.1 | Host de escuta — só amplia quando há um token definido |
A2A_PORT | 9900 | Porta de entrada |
A2A_AGENT_NAME | derivado do hostname | Nome no Cartão de Agente |
A2A_PUBLIC_URL | (não definida) | URL roteável anunciada no cartão (proxies reversos / k8s) |
A2A_TRUSTED_PEERS | (não definida) | Lista de permissão de identidades autenticadas |
A2A_ALLOW_ALL_USERS | false | Aceita qualquer par autenticado (só para desenvolvimento) |
A2A_RATE_LIMIT | 60 | Requisições por minuto por identidade |
A2A_MAX_PINGPONG_TURNS | 5 | Teto anti-laço de rodadas por contexto (máximo 20) |
A2A_REPLY_TIMEOUT | 300 | Segundos de espera pela resposta do agente |
A2A_PUSH_SECRET | o token bearer | Segredo HMAC para assinar as notificações push |
A2A_ADVERTISED_TOOLSETS | todos os registrados | Restringe quais skills aparecem no Cartão de Agente |
Atrás de um proxy reverso ou de um Service do Kubernetes, defina A2A_PUBLIC_URL (ou confie em
X-Forwarded-Host/X-Forwarded-Proto) para que o Cartão de Agente anuncie uma URL que os pares
consigam de fato chamar de volta.
Teste rápido
# De outra máquina / outro agente:
curl http://seu-host:9900/.well-known/agent-card.json
curl -X POST http://seu-host:9900/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{"jsonrpc":"2.0","id":1,"method":"SendMessage",
"params":{"message":{"messageId":"m1","role":"ROLE_USER",
"parts":[{"text":"Quais ferramentas você tem?"}]}}}'
Solução de problemas
- Os pares não alcançam a URL do cartão — o cartão estava anunciando o endereço de escuta;
defina
A2A_PUBLIC_URLcom a URL roteável de fora. 401 Unauthorized— token errado; confiraA2A_PEER_TOKENS/A2A_BEARER_TOKENno servidor e o blocoauth:do par.- O servidor não escuta fora do localhost — é de propósito: defina um token bearer primeiro e
depois
A2A_HOST=0.0.0.0. - As respostas estouram o tempo em tarefas longas — aumente o
A2A_REPLY_TIMEOUT, ou faça quem chama registrar uma configuração de notificação push e consultar oGetTask.