Phase 16 - Lesson 03
Protocolos de Comunicação
Agentes que não conseguem falar a mesma língua não são uma equipe. São estranhos gritando no vazio.
Tipo: Build Linguagens: TypeScript Pré-requisitos: Phase 14 (Agent Engineering), Lesson 16.01 (Why Multi-Agent) Tempo: ~120 minutos
Objetivos de Aprendizado
- Implementar a descoberta e invocação de ferramentas do MCP para que os agentes possam usar ferramentas expostas por servidores externos
- Construir um Agent Card e um endpoint de tarefa A2A que permita a um agente delegar trabalho a outro por meio de HTTP
- Comparar MCP (acesso a ferramentas), A2A (agente para agente), ACP (auditoria corporativa) e ANP (confiança descentralizada) e explicar qual protocolo resolve qual problema
- Conectar múltiplos protocolos em um único sistema onde os agentes descobrem ferramentas via MCP e delegam tarefas via A2A
O Problema
Você dividiu seu sistema em múltiplos agentes. Um pesquisador, um programador, um revisor. Eles são ótimos em seus trabalhos individuais. Mas agora você precisa que eles realmente conversem entre si.
Sua primeira tentativa é óbvia: passar strings de um lado para o outro. O pesquisador retorna um bloco de texto, o programador o analisa da forma que puder. Funciona até que o programador interprete incorretamente um resumo de pesquisa, ou dois agentes entrem em deadlock esperando um pelo outro, ou você precise que agentes construídos por equipes diferentes colaborem. De repente, "apenas passar strings" desmorona.
Este é o problema do protocolo de comunicação. Sem um contrato compartilhado de como os agentes trocam informações, os sistemas multiagente são frágeis, não auditáveis e impossíveis de dimensionar além de um punhado de agentes que você mesmo escreveu.
O ecossistema de IA respondeu com quatro protocolos, cada um resolvendo uma parte diferente do problema:
- MCP para acesso a ferramentas
- A2A para colaboração de agente para agente
- ACP para auditabilidade corporativa
- ANP para identidade descentralizada e confiança
Esta lição vai fundo. Você lerá formatos reais de mensagens de cada especificação, construirá implementações funcionais e conectará todos os quatro em um sistema unificado.
O Conceito
O Cenário dos Protocolos
Pense nesses quatro protocolos como camadas, cada um abordando uma questão diferente:
block-beta
columns 1
block:ANP["ANP — Como os agentes confiam em estranhos?\nIdentidade descentralizada (DID), E2EE, meta-protocolo"]
end
block:A2A["A2A — Como os agentes colaboram em objetivos?\nAgent Cards, ciclo de vida de tarefas, streaming, negociação"]
end
block:ACP["ACP — Como os agentes conversam em sistemas auditáveis?\nExecuções, metadados de trajetória, continuidade de sessão"]
end
block:MCP["MCP — Como um agente usa uma ferramenta?\nDescoberta de ferramentas, execução, compartilhamento de contexto"]
end
style ANP fill:#f3e8ff,stroke:#7c3aed
style A2A fill:#dbeafe,stroke:#2563eb
style ACP fill:#fef3c7,stroke:#d97706
style MCP fill:#d1fae5,stroke:#059669
Eles não são concorrentes. Eles resolvem problemas diferentes em níveis diferentes.
MCP (Recapitulação)
O MCP é abordado em detalhes na Fase 13. Recapitulação rápida: o MCP padroniza como um LLM se conecta a ferramentas externas e fontes de dados. É um protocolo cliente-servidor onde o agente (cliente) descobre e chama ferramentas expostas por um servidor.
sequenceDiagram
participant Agent as Agente (cliente)
participant MCP1 as Servidor MCP<br/>(banco de dados, API, arquivos)
Agent->>MCP1: listar ferramentas
MCP1-->>Agent: definições de ferramentas
Agent->>MCP1: chamar ferramenta X
MCP1-->>Agent: resultado
O MCP é a comunicação agente para ferramenta (agent-to-tool). Ele não ajuda os agentes a conversarem entre si.
A2A (Protocolo Agent2Agent)
Criado por: Google (agora sob a Linux Foundation como lf.a2a.v1)
Versão da especificação: 1.0.0
Problema: Como os agentes autônomos colaboram, negociam e delegam tarefas entre si?
O A2A é o protocolo para colaboração de agente para agente ponto a ponto (peer-to-peer). Enquanto o MCP conecta um agente a ferramentas, o A2A conecta um agente a outros agentes. Cada agente publica um Agent Card em uma URL bem conhecida (well-known), e outros agentes descobrem, negociam e delegam tarefas a ele.
Como o A2A Funciona
sequenceDiagram
participant Client as Agente Cliente
participant Remote as Agente Remoto
Client->>Remote: GET /.well-known/agent-card.json
Remote-->>Client: Agent Card (habilidades, modos, segurança)
Client->>Remote: POST /message:send
Remote-->>Client: Tarefa (submetida/em execução)
alt Polling
Client->>Remote: GET /tasks/{id}
Remote-->>Client: Status da tarefa + artefatos
else Streaming
Client->>Remote: POST /message:stream
Remote-->>Client: SSE: statusUpdate
Remote-->>Client: SSE: artifactUpdate
Remote-->>Client: SSE: completed
end
O Agent Card Real
É assim que um A2A Agent Card realmente se parece em produção. Servido em GET /.well-known/agent-card.json:
{
"name": "Research Agent",
"description": "Searches documentation and summarizes findings",
"version": "1.0.0",
"supportedInterfaces": [
{
"url": "https://research-agent.example.com/a2a/v1",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
},
{
"url": "https://research-agent.example.com/a2a/rest",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}
],
"provider": {
"organization": "Your Company",
"url": "https://example.com"
},
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "web-research",
"name": "Web Research",
"description": "Searches the web and synthesizes findings",
"tags": ["research", "search", "summarization"],
"examples": ["Research the latest changes in React 19"]
},
{
"id": "doc-analysis",
"name": "Documentation Analysis",
"description": "Reads and analyzes technical documentation",
"tags": ["docs", "analysis"],
"inputModes": ["text/plain", "application/pdf"],
"outputModes": ["application/json"]
}
],
"securitySchemes": {
"bearer": {
"httpAuthSecurityScheme": {
"scheme": "Bearer",
"bearerFormat": "JWT"
}
}
},
"security": [{ "bearer": [] }]
}
Pontos importantes a observar:
- Skills (habilidades) são o que um agente pode fazer. Cada uma tem um ID, tags e tipos MIME de entrada/saída suportados. É assim que um agente cliente decide se este agente remoto pode lidar com sua solicitação.
- supportedInterfaces lista múltiplas vinculações de protocolo. Um único agente pode falar JSON-RPC, REST e gRPC simultaneamente.
- Security (segurança) é integrada ao card. O cliente sabe qual autenticação precisa antes de fazer uma única solicitação.
Ciclo de Vida da Tarefa
As tarefas são a unidade central de trabalho no A2A. Elas passam por estados definidos:
stateDiagram-v2
[*] --> submitted
submitted --> working
working --> input_required: precisa de mais informações
input_required --> working: cliente envia dados
working --> completed: sucesso
working --> failed: erro
working --> canceled: cliente cancela
submitted --> rejected: agente recusa
completed --> [*]
failed --> [*]
canceled --> [*]
rejected --> [*]
note right of completed: Estados terminais são imutáveis.\nAcompanhamentos criam novas tarefas\ndentro do mesmo contextId.
Todos os 8 estados (a especificação também define UNSPECIFIED como um sentinela, omitido aqui):
| Estado | Terminal? | Significado |
|---|---|---|
TASK_STATE_SUBMITTED |
Não | Reconhecida, mas ainda não em processamento |
TASK_STATE_WORKING |
Não | Ativamente sendo processada |
TASK_STATE_INPUT_REQUIRED |
Não | O agente precisa de mais informações do cliente |
TASK_STATE_AUTH_REQUIRED |
Não | Autenticação necessária |
TASK_STATE_COMPLETED |
Sim | Concluída com sucesso |
TASK_STATE_FAILED |
Sim | Concluída com erro |
TASK_STATE_CANCELED |
Sim | Cancelada antes da conclusão |
TASK_STATE_REJECTED |
Sim | O agente recusou a tarefa |
Uma vez que uma tarefa atinge um estado terminal, ela é imutável. Nenhuma mensagem adicional é enviada. Os acompanhamentos criam uma nova tarefa dentro do mesmo contextId.
Formato da Mensagem (Wire Format)
O A2A usa JSON-RPC 2.0. Veja como é uma troca de mensagens real:
O cliente envia uma tarefa:
{
"jsonrpc": "2.0",
"id": 1,
"method": "SendMessage",
"params": {
"message": {
"messageId": "msg-001",
"role": "ROLE_USER",
"parts": [{ "text": "Research React 19 compiler features" }]
},
"configuration": {
"acceptedOutputModes": ["text/plain", "application/json"],
"historyLength": 10
}
}
}
O agente responde com uma tarefa:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"task": {
"id": "task-abc-123",
"contextId": "ctx-xyz-789",
"status": {
"state": "TASK_STATE_COMPLETED",
"timestamp": "2026-03-27T10:30:00Z"
},
"artifacts": [
{
"artifactId": "art-001",
"name": "research-results",
"parts": [{
"data": {
"findings": [
"React 19 compiler auto-memoizes components",
"No more manual useMemo/useCallback needed",
"Compiler runs at build time, not runtime"
]
},
"mediaType": "application/json"
}]
}
]
}
}
}
Streaming via SSE:
POST /message:stream HTTP/1.1
Content-Type: application/json
A2A-Version: 1.0
data: {"task":{"id":"task-123","status":{"state":"TASK_STATE_WORKING"}}}
data: {"statusUpdate":{"taskId":"task-123","status":{"state":"TASK_STATE_WORKING","message":{"role":"ROLE_AGENT","parts":[{"text":"Searching documentation..."}]}}}}
data: {"artifactUpdate":{"taskId":"task-123","artifact":{"artifactId":"art-1","parts":[{"text":"partial findings..."}]},"append":true,"lastChunk":false}}
data: {"statusUpdate":{"taskId":"task-123","status":{"state":"TASK_STATE_COMPLETED"}}}
ACP (Agent Communication Protocol)
Criado por: IBM / BeeAI Versão da especificação: 0.2.0 (OpenAPI 3.1.1) Status: Sendo fundido ao A2A sob a Linux Foundation Problema: Como os agentes se comunicam com auditabilidade total, continuidade de sessão e rastreamento de trajetória?
O ACP é o protocolo corporativo. Ao contrário do que muitos resumos afirmam, o ACP não usa JSON-LD. É uma API REST/JSON direta definida via OpenAPI. O que o torna especial é o TrajectoryMetadata: cada resposta do agente pode carregar um registro detalhado das etapas de raciocínio e chamadas de ferramentas que a produziram.
sequenceDiagram
participant Client
participant ACP as Agente ACP
participant Audit as Registro de Auditoria
Client->>ACP: POST /runs (modo: sync)
ACP->>ACP: Processar requisição...
ACP->>Audit: Registrar trajetória:<br/>raciocínio + chamadas de ferramenta
ACP-->>Client: Resposta + TrajectoryMetadata
Note over Audit: Cada etapa registrada:<br/>tool_name, tool_input,<br/>tool_output, raciocínio
Descoberta de Agentes no ACP
O ACP define quatro métodos de descoberta:
graph LR
A[Descoberta de Agentes] --> B["Runtime<br/>GET /agents"]
A --> C["Aberto<br/>.well-known/agent.yml"]
A --> D["Registro<br/>Catálogo centralizado"]
A --> E["Embutido<br/>Rótulos de contêiner"]
style B fill:#dbeafe,stroke:#2563eb
style C fill:#d1fae5,stroke:#059669
style D fill:#fef3c7,stroke:#d97706
style E fill:#f3e8ff,stroke:#7c3aed
O AgentManifest é mais simples que o Agent Card do A2A:
{
"name": "summarizer",
"description": "Summarizes documents with source citations",
"input_content_types": ["text/plain", "application/pdf"],
"output_content_types": ["text/plain", "application/json"],
"metadata": {
"tags": ["summarization", "RAG"],
"framework": "BeeAI",
"capabilities": [
{
"name": "Document Summarization",
"description": "Condenses long documents into key points"
}
],
"recommended_models": ["llama3.3:70b-instruct-fp16"],
"license": "Apache-2.0",
"programming_language": "Python"
}
}
Ciclo de Vida da Execução (Run)
O ACP usa "Runs" (Execuções) em vez de "Tasks" (Tarefas). Uma Run é uma execução do agente com três modos:
| Modo | Comportamento |
|---|---|
sync |
Bloqueante. A resposta contém o resultado completo. |
async |
Retorna 202 imediatamente. Faça polling em GET /runs/{id} para obter o status. |
stream |
Stream SSE. Os eventos são disparados conforme o agente trabalha. |
stateDiagram-v2
[*] --> created
created --> in_progress
in_progress --> completed: sucesso
in_progress --> failed: erro
in_progress --> awaiting: precisa de entrada
awaiting --> in_progress: cliente retoma
in_progress --> cancelling: cancelar requisição
cancelling --> cancelled
completed --> [*]
failed --> [*]
cancelled --> [*]
TrajectoryMetadata (A Trilha de Auditoria)
Este é o principal diferencial do ACP. Cada parte da mensagem pode incluir metadados que mostram exatamente o que o agente fez:
{
"role": "agent/researcher",
"parts": [
{
"content_type": "text/plain",
"content": "The weather in San Francisco is 72F and sunny.",
"metadata": {
"kind": "trajectory",
"message": "I need to check the weather for this location",
"tool_name": "weather_api",
"tool_input": { "location": "San Francisco, CA" },
"tool_output": { "temperature": 72, "condition": "sunny" }
}
}
]
}
Para indústrias regulamentadas, isso vale ouro. Cada resposta vem com uma cadeia de raciocínio comprovável: quais ferramentas foram chamadas, quais entradas foram usadas, quais saídas foram recebidas. Sem caixa preta.
O ACP também suporta CitationMetadata para atribuição de fontes:
{
"kind": "citation",
"start_index": 0,
"end_index": 47,
"url": "https://weather.gov/sf",
"title": "NWS San Francisco Forecast"
}
ANP (Agent Network Protocol)
Criado por: Comunidade de código aberto (fundado por GaoWei Chang) Repositório: github.com/agent-network-protocol/AgentNetworkProtocol Problema: Como agentes de diferentes organizações confiam uns nos outros sem uma autoridade central?
O ANP é o protocolo de identidade descentralizada. Ele constrói confiança usando W3C Decentralized Identifiers (DIDs) e criptografia de ponta a ponta (E2EE). Ao contrário do A2A, onde você descobre agentes por meio de endpoints conhecidos, o ANP permite que os agentes provem sua identidade criptograficamente.
O ANP possui três camadas:
graph TB
subgraph Layer3["Camada 3: Protocolo de Aplicação"]
AD[Documentos de Descrição de Agentes]
DISC[Endpoints de descoberta]
end
subgraph Layer2["Camada 2: Meta-Protocolo"]
NEG[Negociação de protocolo baseada em IA]
CODE[Geração dinâmica de código]
end
subgraph Layer1["Camada 1: Identidade e Comunicação Segura"]
DID["did:wba (W3C DID)"]
HPKE[HPKE E2EE - RFC 9180]
SIG[Verificação de assinatura]
end
Layer3 --> Layer2
Layer2 --> Layer1
style Layer1 fill:#d1fae5,stroke:#059669
style Layer2 fill:#dbeafe,stroke:#2563eb
style Layer3 fill:#f3e8ff,stroke:#7c3aed
Documentos DID (Estrutura Real)
O ANP usa um método DID personalizado chamado did:wba (Web-Based Agent). O DID did:wba:example.com:user:alice é resolvido para https://example.com/user/alice/did.json:
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://w3id.org/security/suites/secp256k1-2019/v1"
],
"id": "did:wba:example.com:user:alice",
"verificationMethod": [
{
"id": "did:wba:example.com:user:alice#key-1",
"type": "EcdsaSecp256k1VerificationKey2019",
"controller": "did:wba:example.com:user:alice",
"publicKeyJwk": {
"crv": "secp256k1",
"x": "NtngWpJUr-rlNNbs0u-Aa8e16OwSJu6UiFf0Rdo1oJ4",
"y": "qN1jKupJlFsPFc1UkWinqljv4YE0mq_Ickwnjgasvmo",
"kty": "EC"
}
},
{
"id": "did:wba:example.com:user:alice#key-x25519-1",
"type": "X25519KeyAgreementKey2019",
"controller": "did:wba:example.com:user:alice",
"publicKeyMultibase": "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE"
}
],
"authentication": [
"did:wba:example.com:user:alice#key-1"
],
"keyAgreement": [
"did:wba:example.com:user:alice#key-x25519-1"
],
"humanAuthorization": [
"did:wba:example.com:user:alice#key-1"
],
"service": [
{
"id": "did:wba:example.com:user:alice#agent-description",
"type": "AgentDescription",
"serviceEndpoint": "https://example.com/agents/alice/ad.json"
}
]
}
Pontos importantes a observar:
- A separação de chaves é obrigatória. As chaves de assinatura (secp256k1) são separadas das chaves de criptografia (X25519).
humanAuthorizationé exclusivo do ANP. Essas chaves exigem aprovação humana explícita (biométrica, senha, HSM) antes do uso. Operações de alto risco, como transferências de fundos, passam por este caminho.- As chaves
keyAgreementsão usadas para criptografia de ponta a ponta HPKE (RFC 9180). - A seção service aponta para o documento de Descrição do Agente.
Como a Confiança Funciona no ANP
O ANP não usa uma teia de confiança (web-of-trust) ou gráfico de endosso. A confiança é bilateral e verificada por interação:
sequenceDiagram
participant A as Agente A
participant Domain as Domínio do Agente A
participant B as Agente B
A->>B: Requisição HTTP + DID + assinatura
B->>Domain: Buscar documento DID (HTTPS)
Domain-->>B: Documento DID + chave pública
B->>B: Verificar assinatura com chave pública
B-->>A: Emitir token de acesso
A->>B: Requisições subsequentes usam o token
Note over A,B: Confiança = Verificação de domínio TLS<br/>+ Verificação de assinatura DID<br/>+ Princípio do menor privilégio
A confiança vem de três fontes:
- TLS em nível de domínio verifica o host do documento DID
- Assinaturas criptográficas do DID verificam a identidade do agente
- Princípio do menor privilégio concede apenas as permissões mínimas
Não há propagação de confiança baseada em fofocas ou pontuação PageRank. Você verifica cada agente diretamente por meio do seu DID.
Negociação de Meta-Protocolo
Este é o recurso mais inovador do ANP. Quando dois agentes de ecossistemas diferentes se encontram, eles não precisam de formatos de dados pré-acordados. Eles negociam em linguagem natural:
{
"action": "protocolNegotiation",
"sequenceId": 0,
"candidateProtocols": "I can communicate using:\n1. JSON-RPC with hotel booking schema\n2. REST with OpenAPI 3.1 spec\n3. Natural language over HTTP",
"modificationSummary": "Initial proposal",
"status": "negotiating"
}
sequenceDiagram
participant A as Agente A
participant B as Agente B
A->>B: protocolNegotiation (candidateProtocols)
B->>A: protocolNegotiation (contraproposta)
A->>B: protocolNegotiation (aceito)
Note over A,B: Os agentes geram código dinamicamente<br/>para lidar com o formato acordado.<br/>Máximo de 10 rodadas, depois timeout.
Os agentes vão e voltam (no máximo 10 rodadas) até concordarem em um formato e, em seguida, geram dinamicamente o código para lidar com ele. Valores de status: negotiating, rejected, accepted, timeout.
Isso significa que dois agentes que nunca se viram antes podem descobrir como se comunicar sem que ninguém pré-defina um esquema compartilhado.
Comparação (Corrigida)
| MCP | A2A | ACP | ANP | |
|---|---|---|---|---|
| Criado por | Anthropic | Google / Linux Foundation | IBM / BeeAI | Comunidade |
| Formato da especificação | JSON-RPC | JSON-RPC / REST / gRPC | OpenAPI 3.1 (REST) | JSON-RPC |
| Uso principal | Agente para Ferramenta | Agente para Agente | Agente para Agente | Agente para Agente |
| Descoberta | Listagem de ferramentas | /.well-known/agent-card.json |
GET /agents, /.well-known/agent.yml |
/.well-known/agent-descriptions, endpoints de serviço DID |
| Identidade | Implícita (local) | Esquemas de segurança (OAuth, mTLS) | Nível de servidor | W3C DID (did:wba) com E2EE |
| Trilha de auditoria | N/A | Básica (histórico de tarefas) | TrajectoryMetadata (chamadas de ferramentas, raciocínio) | Em desenvolvimento (não especificado formalmente) |
| Máquina de estados | N/A | 9 estados de tarefa | 7 estados de execução (run) | N/A |
| Streaming | N/A | SSE | SSE | Agnóstico de transporte |
| Recurso exclusivo | Esquemas de ferramentas | Agent Cards + Skills | Trilha de auditoria de trajetória | Negociação de meta-protocolo |
| Melhor para | Ferramentas e dados | Colaboração dinâmica | Indústrias regulamentadas | Confiança entre organizações |
| Status | Estável | Estável (v1.0) | Sendo fundido ao A2A | Desenvolvimento ativo |
Como Eles Funcionam Juntos
Esses protocolos não são mutuamente exclusivos. Um sistema corporativo realista usa múltiplos:
graph TB
subgraph org["Sua Organização"]
RA[Research Agent] <-->|A2A| CA[Coding Agent]
RA -->|MCP| SS[Search Server]
CA -->|MCP| GS[GitHub Server]
AUDIT["Todas as respostas dos agentes carregam<br/>ACP TrajectoryMetadata"]
end
subgraph ext["Externo (DID verificado via ANP)"]
EA[External Agent]
PA[Partner Agent]
end
RA <-->|ANP + A2A| EA
CA <-->|ANP + A2A| PA
style org fill:#f8fafc,stroke:#334155
style ext fill:#fef2f2,stroke:#991b1b
style AUDIT fill:#fef3c7,stroke:#d97706
- MCP conecta cada agente às suas ferramentas
- A2A gerencia a colaboração entre agentes (internos e externos)
- ACP envolve as respostas em metadados de trajetória para auditabilidade
- ANP fornece verificação de identidade para agentes que você não controla
Build It
Passo 1: Tipos de Mensagens Principais
Todo sistema multiagente começa com um formato de mensagem. Definimos tipos que mapeiam o que os protocolos reais usam:
import crypto from "node:crypto";
type MessageRole = "user" | "agent";
type MessagePart =
| { kind: "text"; text: string }
| { kind: "data"; data: unknown; mediaType: string }
| { kind: "file"; name: string; url: string; mediaType: string };
type TrajectoryEntry = {
reasoning: string;
toolName?: string;
toolInput?: unknown;
toolOutput?: unknown;
timestamp: number;
};
type AgentMessage = {
id: string;
role: MessageRole;
parts: MessagePart[];
trajectory?: TrajectoryEntry[];
replyTo?: string;
timestamp: number;
};
function createMessage(
role: MessageRole,
parts: MessagePart[],
replyTo?: string
): AgentMessage {
return {
id: crypto.randomUUID(),
role,
parts,
replyTo,
timestamp: Date.now(),
};
}
function textMessage(role: MessageRole, text: string): AgentMessage {
return createMessage(role, [{ kind: "text", text }]);
}
Observe: MessagePart é multimodal (texto, dados estruturados, arquivos) exatamente como as especificações reais do A2A e ACP. TrajectoryEntry captura a cadeia de raciocínio, correspondendo ao TrajectoryMetadata do ACP.
Passo 2: A2A Agent Card e Registro
Construa a descoberta de agentes que corresponda à especificação real do A2A:
type Skill = {
id: string;
name: string;
description: string;
tags: string[];
inputModes: string[];
outputModes: string[];
};
type AgentCard = {
name: string;
description: string;
version: string;
url: string;
capabilities: {
streaming: boolean;
pushNotifications: boolean;
};
defaultInputModes: string[];
defaultOutputModes: string[];
skills: Skill[];
};
class AgentRegistry {
private cards: Map<string, AgentCard> = new Map();
register(card: AgentCard) {
this.cards.set(card.name, card);
}
discoverBySkillTag(tag: string): AgentCard[] {
return [...this.cards.values()].filter((card) =>
card.skills.some((skill) => skill.tags.includes(tag))
);
}
discoverByInputMode(mimeType: string): AgentCard[] {
return [...this.cards.values()].filter(
(card) =>
card.defaultInputModes.includes(mimeType) ||
card.skills.some((skill) => skill.inputModes.includes(mimeType))
);
}
resolve(name: string): AgentCard | undefined {
return this.cards.get(name);
}
listAll(): AgentCard[] {
return [...this.cards.values()];
}
}
Isso é substancialmente mais rico do que um mapa simples de nome para capacidade. Você pode descobrir agentes por tags de habilidade, por tipos MIME de entrada ou por nome, exatamente como a especificação A2A real suporta.
Passo 3: Ciclo de Vida da Tarefa A2A
Construa a máquina de estados completa da tarefa:
type TaskState =
| "submitted"
| "working"
| "input-required"
| "auth-required"
| "completed"
| "failed"
| "canceled"
| "rejected";
const TERMINAL_STATES: TaskState[] = [
"completed",
"failed",
"canceled",
"rejected",
];
type TaskStatus = {
state: TaskState;
message?: AgentMessage;
timestamp: number;
};
type Artifact = {
id: string;
name: string;
parts: MessagePart[];
};
type Task = {
id: string;
contextId: string;
status: TaskStatus;
artifacts: Artifact[];
history: AgentMessage[];
};
type TaskEvent =
| { kind: "statusUpdate"; taskId: string; status: TaskStatus }
| {
kind: "artifactUpdate";
taskId: string;
artifact: Artifact;
append: boolean;
lastChunk: boolean;
};
type TaskHandler = (
task: Task,
message: AgentMessage
) => AsyncGenerator<TaskEvent>;
class TaskManager {
private tasks: Map<string, Task> = new Map();
private handlers: Map<string, TaskHandler> = new Map();
private listeners: Map<string, ((event: TaskEvent) => void)[]> = new Map();
registerHandler(agentName: string, handler: TaskHandler) {
this.handlers.set(agentName, handler);
}
subscribe(taskId: string, listener: (event: TaskEvent) => void) {
const existing = this.listeners.get(taskId) ?? [];
existing.push(listener);
this.listeners.set(taskId, existing);
}
async sendMessage(
agentName: string,
message: AgentMessage,
contextId?: string
): Promise<Task> {
const handler = this.handlers.get(agentName);
if (!handler) {
const task = this.createTask(contextId);
task.status = {
state: "rejected",
timestamp: Date.now(),
message: textMessage("agent", `No handler for ${agentName}`),
};
return task;
}
const task = this.createTask(contextId);
task.history.push(message);
task.status = { state: "submitted", timestamp: Date.now() };
this.processTask(task, handler, message).catch((err) => {
task.status = {
state: "failed",
timestamp: Date.now(),
message: textMessage("agent", String(err)),
};
});
return task;
}
getTask(taskId: string): Task | undefined {
return this.tasks.get(taskId);
}
cancelTask(taskId: string): boolean {
const task = this.tasks.get(taskId);
if (!task || TERMINAL_STATES.includes(task.status.state)) return false;
task.status = { state: "canceled", timestamp: Date.now() };
this.emit(taskId, {
kind: "statusUpdate",
taskId,
status: task.status,
});
return true;
}
private createTask(contextId?: string): Task {
const task: Task = {
id: crypto.randomUUID(),
contextId: contextId ?? crypto.randomUUID(),
status: { state: "submitted", timestamp: Date.now() },
artifacts: [],
history: [],
};
this.tasks.set(task.id, task);
return task;
}
private async processTask(
task: Task,
handler: TaskHandler,
message: AgentMessage
) {
task.status = { state: "working", timestamp: Date.now() };
this.emit(task.id, {
kind: "statusUpdate",
taskId: task.id,
status: task.status,
});
try {
for await (const event of handler(task, message)) {
if (TERMINAL_STATES.includes(task.status.state)) break;
if (event.kind === "statusUpdate") {
task.status = event.status;
}
if (event.kind === "artifactUpdate") {
const existing = task.artifacts.find(
(a) => a.id === event.artifact.id
);
if (existing && event.append) {
existing.parts.push(...event.artifact.parts);
} else {
task.artifacts.push(event.artifact);
}
}
this.emit(task.id, event);
}
} catch (err) {
task.status = {
state: "failed",
timestamp: Date.now(),
message: textMessage("agent", String(err)),
};
this.emit(task.id, {
kind: "statusUpdate",
taskId: task.id,
status: task.status,
});
}
}
private emit(taskId: string, event: TaskEvent) {
for (const listener of this.listeners.get(taskId) ?? []) {
listener(event);
}
}
}
Isso implementa o ciclo de vida real da tarefa A2A: submetida, em execução, entrada necessária, estados terminais. Os manipuladores (handlers) são geradores assíncronos que produzem eventos (atualizações de status e partes de artefatos) correspondentes ao modelo de streaming SSE.
Passo 4: Trilha de Auditoria Estilo ACP
Envolva a comunicação com o rastreamento de trajetória:
type AuditEntry = {
runId: string;
agentName: string;
input: AgentMessage[];
output: AgentMessage[];
trajectory: TrajectoryEntry[];
status: "created" | "in-progress" | "completed" | "failed" | "awaiting";
startedAt: number;
completedAt?: number;
sessionId?: string;
};
class AuditableRunner {
private log: AuditEntry[] = [];
private handlers: Map<
string,
(input: AgentMessage[]) => Promise<{
output: AgentMessage[];
trajectory: TrajectoryEntry[];
}>
> = new Map();
registerAgent(
name: string,
handler: (input: AgentMessage[]) => Promise<{
output: AgentMessage[];
trajectory: TrajectoryEntry[];
}>
) {
this.handlers.set(name, handler);
}
async run(
agentName: string,
input: AgentMessage[],
sessionId?: string
): Promise<AuditEntry> {
const entry: AuditEntry = {
runId: crypto.randomUUID(),
agentName,
input: structuredClone(input),
output: [],
trajectory: [],
status: "created",
startedAt: Date.now(),
sessionId,
};
this.log.push(entry);
const handler = this.handlers.get(agentName);
if (!handler) {
entry.status = "failed";
return entry;
}
entry.status = "in-progress";
try {
const result = await handler(input);
entry.output = structuredClone(result.output);
entry.trajectory = structuredClone(result.trajectory);
entry.status = "completed";
entry.completedAt = Date.now();
} catch (err) {
entry.status = "failed";
entry.trajectory.push({
reasoning: `Error: ${String(err)}`,
timestamp: Date.now(),
});
entry.completedAt = Date.now();
}
return entry;
}
getFullAuditLog(): AuditEntry[] {
return structuredClone(this.log);
}
getAuditLogForAgent(agentName: string): AuditEntry[] {
return structuredClone(
this.log.filter((e) => e.agentName === agentName)
);
}
getAuditLogForSession(sessionId: string): AuditEntry[] {
return structuredClone(
this.log.filter((e) => e.sessionId === sessionId)
);
}
getTrajectoryForRun(runId: string): TrajectoryEntry[] {
const entry = this.log.find((e) => e.runId === runId);
return entry ? structuredClone(entry.trajectory) : [];
}
}
Cada execução do agente produz uma entrada de auditoria completa: o que entrou, o que saiu e a trajetória completa de chamadas de ferramentas e etapas de raciocínio intermediárias. Você pode consultar por agente, por sessão ou por execução individual.
Passo 5: Verificação de Identidade Estilo ANP
Construa a identidade baseada em DID e verificação:
type VerificationMethod = {
id: string;
type: string;
controller: string;
publicKeyDer: string;
};
type DIDDocument = {
id: string;
verificationMethod: VerificationMethod[];
authentication: string[];
keyAgreement: string[];
humanAuthorization: string[];
service: { id: string; type: string; serviceEndpoint: string }[];
};
type AgentIdentity = {
did: string;
document: DIDDocument;
privateKey: crypto.KeyObject;
publicKey: crypto.KeyObject;
};
class IdentityRegistry {
private documents: Map<string, DIDDocument> = new Map();
publish(doc: DIDDocument) {
this.documents.set(doc.id, doc);
}
resolve(did: string): DIDDocument | undefined {
return this.documents.get(did);
}
verify(did: string, signature: string, payload: string): boolean {
const doc = this.documents.get(did);
if (!doc) return false;
const authKeyIds = doc.authentication;
const authKeys = doc.verificationMethod.filter((vm) =>
authKeyIds.includes(vm.id)
);
for (const key of authKeys) {
const publicKey = crypto.createPublicKey({
key: Buffer.from(key.publicKeyDer, "base64"),
format: "der",
type: "spki",
});
const isValid = crypto.verify(
null,
Buffer.from(payload),
publicKey,
Buffer.from(signature, "hex")
);
if (isValid) return true;
}
return false;
}
requiresHumanAuth(did: string, operationKeyId: string): boolean {
const doc = this.documents.get(did);
if (!doc) return false;
return doc.humanAuthorization.includes(operationKeyId);
}
}
function createIdentity(domain: string, agentName: string): AgentIdentity {
const did = `did:wba:${domain}:agent:${agentName}`;
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
const publicKeyDer = publicKey
.export({ format: "der", type: "spki" })
.toString("base64");
const keyId = `${did}#key-1`;
const encKeyId = `${did}#key-x25519-1`;
const document: DIDDocument = {
id: did,
verificationMethod: [
{
id: keyId,
type: "Ed25519VerificationKey2020",
controller: did,
publicKeyDer,
},
{
id: encKeyId,
type: "X25519KeyAgreementKey2019",
controller: did,
publicKeyDer,
},
],
authentication: [keyId],
keyAgreement: [encKeyId],
humanAuthorization: [],
service: [
{
id: `${did}#agent-description`,
type: "AgentDescription",
serviceEndpoint: `https://${domain}/agents/${agentName}/ad.json`,
},
],
};
return { did, document, privateKey, publicKey };
}
function signPayload(identity: AgentIdentity, payload: string): string {
return crypto
.sign(null, Buffer.from(payload), identity.privateKey)
.toString("hex");
}
Isso reflete o modelo real de identidade ANP: os agentes possuem documentos DID com chaves separadas para autenticação, acordo de chave (key agreement) e autorização humana. O IdentityRegistry simula a resolução DID (em produção, seriam requisições HTTP para o domínio do agente).
Passo 6: Protocol Gateway
Conecte todos os quatro protocolos em um sistema unificado:
graph LR
REQ[Requisição de Entrada] --> ANP_V{ANP: Verificar DID}
ANP_V -->|Válido| A2A_D{A2A: Descobrir Agente}
ANP_V -->|Inválido| REJECT[Rejeitar]
A2A_D -->|Encontrado| ACP_A[ACP: Auditar Execução]
A2A_D -->|Não Encontrado| REJECT
ACP_A --> A2A_T[A2A: Criar Tarefa]
A2A_T --> RESULT[Tarefa + Entrada de Auditoria]
style ANP_V fill:#d1fae5,stroke:#059669
style A2A_D fill:#dbeafe,stroke:#2563eb
style ACP_A fill:#fef3c7,stroke:#d97706
style A2A_T fill:#dbeafe,stroke:#2563eb
class ProtocolGateway {
private registry: AgentRegistry;
private taskManager: TaskManager;
private auditRunner: AuditableRunner;
private identityRegistry: IdentityRegistry;
constructor(
registry: AgentRegistry,
taskManager: TaskManager,
auditRunner: AuditableRunner,
identityRegistry: IdentityRegistry
) {
this.registry = registry;
this.taskManager = taskManager;
this.auditRunner = auditRunner;
this.identityRegistry = identityRegistry;
}
async delegateTask(
fromDid: string,
signature: string,
targetAgent: string,
message: AgentMessage,
sessionId?: string
): Promise<{ task: Task; audit: AuditEntry } | { error: string }> {
if (!this.identityRegistry.verify(fromDid, signature, message.id)) {
return { error: "Identity verification failed" };
}
const card = this.registry.resolve(targetAgent);
if (!card) {
return { error: `Agent ${targetAgent} not found in registry` };
}
const audit = await this.auditRunner.run(
targetAgent,
[message],
sessionId
);
const task = await this.taskManager.sendMessage(targetAgent, message);
return { task, audit };
}
discoverAndDelegate(
fromDid: string,
signature: string,
skillTag: string,
message: AgentMessage
): Promise<{ task: Task; audit: AuditEntry } | { error: string }> {
const candidates = this.registry.discoverBySkillTag(skillTag);
if (candidates.length === 0) {
return Promise.resolve({
error: `No agents found with skill tag: ${skillTag}`,
});
}
return this.delegateTask(
fromDid,
signature,
candidates[0].name,
message
);
}
}
O gateway faz quatro coisas em uma única chamada:
- ANP: Verifica a identidade do chamador via assinatura DID
- A2A: Descobre o agente de destino e verifica as capacidades
- ACP: Envolve a execução em uma trilha de auditoria com trajetória
- A2A: Cria uma tarefa com rastreamento completo do ciclo de vida
Passo 7: Conectando Tudo
async function protocolDemo() {
const registry = new AgentRegistry();
registry.register({
name: "researcher",
description: "Searches and summarizes findings",
version: "1.0.0",
url: "https://researcher.local/a2a/v1",
capabilities: { streaming: true, pushNotifications: false },
defaultInputModes: ["text/plain"],
defaultOutputModes: ["text/plain", "application/json"],
skills: [
{
id: "web-research",
name: "Web Research",
description: "Searches the web",
tags: ["research", "search", "summarization"],
inputModes: ["text/plain"],
outputModes: ["application/json"],
},
],
});
registry.register({
name: "coder",
description: "Writes code from specs",
version: "1.0.0",
url: "https://coder.local/a2a/v1",
capabilities: { streaming: false, pushNotifications: false },
defaultInputModes: ["text/plain", "application/json"],
defaultOutputModes: ["text/plain"],
skills: [
{
id: "code-gen",
name: "Code Generation",
description: "Generates code",
tags: ["coding", "generation"],
inputModes: ["text/plain", "application/json"],
outputModes: ["text/plain"],
},
],
});
const taskManager = new TaskManager();
const auditRunner = new AuditableRunner();
const researchTrajectory: TrajectoryEntry[] = [];
taskManager.registerHandler(
"researcher",
async function* (task, message) {
yield {
kind: "statusUpdate" as const,
taskId: task.id,
status: { state: "working" as const, timestamp: Date.now() },
};
researchTrajectory.push({
reasoning: "Searching for React 19 documentation",
toolName: "web_search",
toolInput: { query: "React 19 compiler features" },
toolOutput: {
results: ["react.dev/blog/react-19", "github.com/react/react"],
},
timestamp: Date.now(),
});
researchTrajectory.push({
reasoning: "Extracting key findings from search results",
toolName: "doc_analysis",
toolInput: { url: "react.dev/blog/react-19" },
toolOutput: {
summary:
"React 19 compiler auto-memoizes, no manual useMemo needed",
},
timestamp: Date.now(),
});
yield {
kind: "artifactUpdate" as const,
taskId: task.id,
artifact: {
id: crypto.randomUUID(),
name: "research-results",
parts: [
{
kind: "data" as const,
data: {
findings: [
"React 19 compiler auto-memoizes components",
"No more manual useMemo/useCallback needed",
"Compiler runs at build time, not runtime",
],
sources: ["react.dev/blog/react-19"],
},
mediaType: "application/json",
},
],
},
append: false,
lastChunk: true,
};
yield {
kind: "statusUpdate" as const,
taskId: task.id,
status: { state: "completed" as const, timestamp: Date.now() },
};
}
);
auditRunner.registerAgent("researcher", async () => ({
output: [
textMessage("agent", "React 19 compiler auto-memoizes components"),
],
trajectory: researchTrajectory,
}));
const identityRegistry = new IdentityRegistry();
const coderIdentity = createIdentity("coder.local", "coder");
const researcherIdentity = createIdentity("researcher.local", "researcher");
identityRegistry.publish(coderIdentity.document);
identityRegistry.publish(researcherIdentity.document);
const gateway = new ProtocolGateway(
registry,
taskManager,
auditRunner,
identityRegistry
);
console.log("=== Protocol Demo ===\n");
console.log("1. Agent Discovery (A2A)");
const researchAgents = registry.discoverBySkillTag("research");
console.log(
` Found ${researchAgents.length} agent(s):`,
researchAgents.map((a) => a.name)
);
console.log("\n2. Identity Verification (ANP)");
const message = textMessage("user", "Research React 19 compiler features");
const signature = signPayload(coderIdentity, message.id);
const verified = identityRegistry.verify(
coderIdentity.did,
signature,
message.id
);
console.log(` Coder DID: ${coderIdentity.did}`);
console.log(` Signature verified: ${verified}`);
console.log("\n3. Task Delegation (A2A + ACP + ANP)");
const result = await gateway.delegateTask(
coderIdentity.did,
signature,
"researcher",
message,
"session-001"
);
if ("error" in result) {
console.log(` Error: ${result.error}`);
return;
}
console.log(` Task ID: ${result.task.id}`);
console.log(` Task state: ${result.task.status.state}`);
console.log(` Artifacts: ${result.task.artifacts.length}`);
console.log("\n4. Audit Trail (ACP)");
console.log(` Run ID: ${result.audit.runId}`);
console.log(` Status: ${result.audit.status}`);
console.log(` Trajectory steps: ${result.audit.trajectory.length}`);
for (const step of result.audit.trajectory) {
console.log(` - ${step.reasoning}`);
if (step.toolName) {
console.log(` Tool: ${step.toolName}`);
}
}
console.log("\n5. Full Audit Log");
const fullLog = auditRunner.getFullAuditLog();
console.log(` Total runs: ${fullLog.length}`);
for (const entry of fullLog) {
const duration = entry.completedAt
? `${entry.completedAt - entry.startedAt}ms`
: "in-progress";
console.log(` ${entry.agentName}: ${entry.status} (${duration})`);
}
}
protocolDemo().catch((err) => {
console.error("Protocol demo failed:", err);
process.exitCode = 1;
});
O Que Pode Dar Errado
Os protocolos resolvem o caminho feliz (happy path). Veja o que quebra em produção:
Desvio de esquema (Schema drift). O Agente A publica um Agent Card anunciando uma saída application/json. Mas o esquema JSON muda entre as versões. O Agente B analisa o formato antigo e obtém lixo. Solução: versione suas habilidades e esquemas de saída. A especificação A2A suporta version nos Agent Cards por esse motivo.
Violações da máquina de estados. Um manipulador de agente produz um evento completed e, em seguida, tenta produzir mais artefatos. A tarefa é imutável. Seu código descarta silenciosamente as atualizações ou gera um erro. Solução: verifique o estado terminal antes de produzir novos eventos. O TaskManager acima impõe isso com a instrução break após os estados terminais.
Falhas na resolução de confiança. O Agente A tenta verificar o DID do Agente B, mas o domínio do Agente B está fora do ar. O documento DID não pode ser obtido. Você falha permitindo o acesso (aceita agentes não verificados) ou falha bloqueando (rejeita tudo)? O ANP recomenda falhar bloqueando (fail closed) com o princípio do menor privilégio.
Inchaço da trajetória (Trajectory bloat). O registro de trajetória do ACP é poderoso, mas caro. Um agente complexo que faz 200 chamadas de ferramentas por execução produz entradas de auditoria massivas. Solução: registre a trajetória em níveis de detalhe configuráveis. Registre os nomes das ferramentas e as entradas/saídas para conformidade, pule as etapas de raciocínio para cargas de trabalho não regulamentadas.
Avalanche de descoberta (Thundering herd). 50 agentes consultam GET /agents simultaneamente na inicialização. Solução: armazene os Agent Cards em cache com TTL, escalone os intervalos de descoberta ou use registro baseado em push em vez de polling.
Use It
Implementações Reais
A2A é o mais maduro. A especificação oficial do Google é de código aberto sob a Linux Foundation. Existem SDKs para Python e TypeScript. Se seus agentes precisam de descoberta dinâmica e colaboração, comece aqui.
ACP está sendo fundido ao A2A. O projeto BeeAI da IBM criou o ACP como uma alternativa focada primeiro em REST, mas o conceito de metadados de trajetória está sendo absorvido pelo ecossistema A2A. Use padrões ACP (registro de trajetória, ciclo de vida de execução) mesmo se usar A2A como transporte.
ANP é o mais experimental. O repositório da comunidade possui um SDK Python (AgentConnect). O conceito de negociação de meta-protocolo é genuinamente inovador. Vale a pena acompanhar para implantações de agentes entre organizações.
MCP já foi abordado na Fase 13. Se você deseja que os agentes usem ferramentas, o MCP é o padrão.
Escolhendo o Protocolo Correto
graph TD
START{Os agentes precisam<br/>usar ferramentas?}
START -->|Sim| MCP_R[Use MCP]
START -->|Não| TALK{Os agentes precisam<br/>conversar entre si?}
TALK -->|Não| NONE[Você não precisa<br/>de um protocolo]
TALK -->|Sim| AUDIT{Precisa de trilhas de auditoria<br/>para conformidade?}
AUDIT -->|Sim| ACP_R[A2A + ACP<br/>padrões de trajetória]
AUDIT -->|Não| ORG{Todos os agentes<br/>estão na sua org?}
ORG -->|Sim| A2A_R[A2A<br/>Agent Cards + Tarefas]
ORG -->|Não| INFRA{Compartilham<br/>infraestrutura?}
INFRA -->|Sim| BROKER[A2A + message broker]
INFRA -->|Não| ANP_R[ANP + A2A<br/>verificação de DID]
style MCP_R fill:#d1fae5,stroke:#059669
style A2A_R fill:#dbeafe,stroke:#2563eb
style ACP_R fill:#fef3c7,stroke:#d97706
style ANP_R fill:#f3e8ff,stroke:#7c3aed
style BROKER fill:#e0e7ff,stroke:#4338ca
Ship It
Esta lição produz:
code/main.ts-- implementação completa de todos os os quatro padrões de protocolooutputs/prompt-protocol-selector.md-- um prompt que ajuda você a escolher os protocolos para o seu sistema
Exercícios
Delegação de tarefas em múltiplas etapas (Multi-hop). Estenda o
TaskManagerpara que um manipulador de agente possa delegar subtarefas a outros agentes. O pesquisador recebe uma tarefa, delega as subtarefas "pesquisar" e "resumir" a dois agentes especialistas, aguarda a conclusão de ambas e, em seguida, mescla os resultados em seus próprios artefatos.Trilha de auditoria em tempo real (Streaming). Modifique o
AuditableRunnerpara suportar o modo streaming. Em vez de esperar pelo resultado completo, produza atualizações deAuditEntryem tempo real à medida que novas entradas de trajetória forem adicionadas. Use um gerador assíncrono que produza snapshots da auditoria.Rotação de DID. Adicione rotação de chaves ao
IdentityRegistry. Um agente deve ser capaz de publicar um novo documento DID com chaves atualizadas, mantendo uma referênciapreviousDid. Os verificadores devem aceitar assinaturas tanto da chave atual quanto da anterior durante um período de carência.Negociação de protocolo. Implemente o conceito de meta-protocolo do ANP. Dois agentes trocam mensagens
protocolNegotiationcom formatos candidatos (por exemplo, "Eu posso falar JSON-RPC" vs "Eu prefiro REST"). Após no máximo 3 rodadas, eles concordam em um formato ou ocorre um timeout. O formato acordado determina qualTaskManagerouAuditableRunnereles usarão.Descoberta com limite de taxa (Rate-limiting). Adicione um wrapper
RateLimitedRegistryque armazena em cache as consultas de Agent Cards com um TTL configurável e limita as consultas de descoberta por agente por segundo. Simule uma avalanche (thundering herd) de 100 agentes descobrindo uns aos outros na inicialização e meça a diferença.
Termos-Chave
| Termo | O que dizem | O que realmente significa |
|---|---|---|
| MCP | "O protocolo para ferramentas de IA" | Um protocolo cliente-servidor para agentes descobrirem e usarem ferramentas. Agente para ferramenta, não agente para agente. |
| A2A | "Protocolo de agente do Google" | Um protocolo ponto a ponto para colaboração de agentes sob a Linux Foundation. Descoberta via Agent Cards, ciclo de vida de tarefa de 9 estados, streaming via SSE. Suporta vinculações JSON-RPC, REST e gRPC. |
| ACP | "Mensagens corporativas de agentes" | API REST da IBM/BeeAI para execuções (runs) de agentes com TrajectoryMetadata: cada resposta carrega a cadeia completa de raciocínio e chamadas de ferramentas. Está sendo fundido ao A2A. |
| ANP | "Identidade descentralizada de agentes" | Um protocolo comunitário que usa did:wba (DID) para identidade criptográfica, HPKE para E2EE e negociação de meta-protocolo baseada em IA para agentes que nunca se viram antes. |
| Agent Card | "O cartão de visita do agente" | Um documento JSON em /.well-known/agent-card.json que descreve habilidades, tipos MIME suportados, esquemas de segurança e vinculações de protocolo. |
| DID | "ID descentralizado" | Padrão W3C para identidades criptograficamente verificáveis hospedadas no próprio domínio do agente. O ANP usa o método did:wba. |
| TrajectoryMetadata | "O recibo da auditoria" | Mecanismo do ACP para anexar etapas de raciocínio, chamadas de ferramentas e suas entradas/saídas a cada resposta do agente. |
| Meta-protocolo | "Agentes negociando como conversar" | Abordagem do ANP onde os agentes usam linguagem natural para concordar dinamicamente sobre formatos de dados e, em seguida, geram código para lidar com eles. |
| Tarefa | "Uma unidade de trabalho" | O objeto com estado do A2A que rastreia o trabalho desde a submissão até a conclusão. Imutável após se tornar terminal. |
Leituras Adicionais
- Especificação do Google A2A -- especificação oficial e SDKs (v1.0.0, Linux Foundation)
- Especificação do IBM/BeeAI ACP -- especificação OpenAPI 3.1 para execuções de agentes e metadados de trajetória
- Agent Network Protocol -- identidade baseada em DID, E2EE, negociação de meta-protocolo
- Documentação do Model Context Protocol -- especificação do MCP da Anthropic (abordado na Fase 13)
- W3C Decentralized Identifiers -- o padrão de identidade que fundamenta o ANP
- RFC 9180 (HPKE) -- o esquema de criptografia que o ANP usa para E2EE
- FIPA Agent Communication Language -- o precursor acadêmico dos protocolos modernos de agentes