Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.
See how MongoDB 9.0 delivers up to 2x higher throughput.
MongoDB Branding Shape
Register now >
Menu Docs

Usar comunicação de agente para agente

A comunicação agente para agente (A2A) permite que um agente descobrir e invocar outros agentes no mesmo projeto no tempo de execução. O Mecanismo de Orquestração (OE) intermediários cada chamada executando as seguintes ações:

  • Valida o acesso

  • Cria uma execução secundária

  • Despacha a solicitação para o agente de destino

  • Retorna o resultado

As garantias humanos no loop (HITL) se aplicam de ponta a ponta. Um agente de destino que suspende a revisão humana pausa a chamada em vez de retornar uma falha.

A2A segue esta sequência quando você a ativa:

  1. Você adiciona um bloco a2a: ao seu arquivo agent.yaml. Em sua primeira execução, a plataforma registra a configuração do agente com o OE, tornando o agente detectável e chamado por outros agentes no mesmo projeto.

  2. Quando a OE despacha uma execução para seu agente, ela injeta um token de curta duração no contexto de execução. Seu agente usa esse token de forma transparente ao ligar para outros agentes.

  3. No código do agente , você expõe o A2A como ferramentas LLM com app.a2a_tools() (recomendado) ou chama o cliente A2A diretamente por meio de app._runtime.a2a para roteamento determinístico.

  4. A OE impõe o controle de acesso, vincula a execução do filho ao pai, despacha para o destino e retorna o resultado.

Adicione uma seção a2a: ao seu arquivo agent.yaml para tornar seu agente detectável e chamável. Se você omitir essa seção ou definir a2a.enabled como false, seu agente permanecerá invisível para os chamadores A2A e será totalmente compatível com versões anteriores dos sistemas existentes.

Observação

Para testar o A2A localmente, defina a variável de ambiente A2A_JWT_SECRET com o mesmo valor no arquivo .env de cada agente que chama ou é chamado por meio do A2A.

O exemplo a seguir mostra uma seção a2a: totalmente configurada:

name: insurance-agent
entrypoint: insurance_agent.main:app
a2a:
enabled: true
allowed_callers:
- "ws-router-002"
skills:
- name: policy-lookup
description: Look up insurance policy details
example_input: '{"policy_id": "POL-123"}'
example_output: '{"status": "active", "premium": 240}'
- name: get-quote
description: Generate an insurance quote
input_modes:
- "text/plain"
output_modes:
- "text/plain"

A tabela a seguir descreve os campos na seção a2a: do arquivo agent.yaml:

Campo
Tipo
Default
Descrição

a2a.enabled

bool

false

Torna o agente detectável e consultável por meio da A2A. Quando false, todos os outros campos a2a são ignorados.

a2a.allowed_callers

list[str]

[]

IDs de espaço de trabalho permitidas para invocar este agente. Uma lista vazia permite qualquer agente habilitado para A2A no mesmo projeto. Uma lista não vazia atua como uma lista de permissões.

a2a.skills

list[object]

[]

Qualificações que o agente anuncia para descoberta. Cada entrada exige um name e um description. Os campos example_input e example_output são opcionais. Descrições claras e específicas ajudam outros agentes a decidir se esse agente corresponde às suas necessidades.

a2a.input_modes

list[str]

[]

Tipos de extensões multifuncionais de correio da Internet (MIME) que o agente aceita, por exemplo text/plain ou application/json. Usado como filtro de descoberta.

a2a.output_modes

list[str]

[]

Tipos de MIME que o agente produz. Usado como filtro de descoberta.

Observação

Os name, skills, input_modes, output_modes e allowed_callers do agente são automaticamente enviados para o OE na inicialização. A descrição de texto livre e as marcações de recursos que aparecem nos resultados da descoberta vêm do AgentCard do espaço de trabalho que você configura por meio dos pontos de extremidade do espaço de trabalho do API Gateway, não do agent.yaml.

Você pode chamar outros agentes a partir do código do agente de duas maneiras: expondo o A2A como ferramentas LLM (recomendadas) ou usando o cliente A2A diretamente. Ambos usam o mesmo cliente subjacente . Escolha sua abordagem com base no fato de desejar que o LLM conduza a decisão de roteamento ou se você precisa de um controle determinístico.

O método app.a2a_tools() retorna dois objetos LangChain StructuredTool: discover_available_agents e invoke_a2a_agent. Esses objetos permitem que o LLM descobrir e chamar outros agentes de forma autônoma. Vincule-os às suas ferramentas existentes para que o modelo possa rotear para outros agentes por conta própria.

O método app.a2a_tools() retorna uma lista vazia quando a2a.enabled está false em seu arquivo agent.yaml, portanto é seguro incluir em todos os agentes.

O exemplo a seguir vincula as ferramentas A2A às ferramentas existentes:

from agent_engine_sdk_langgraph import App
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph
from langgraph.prebuilt import ToolNode
app = App(app_name="router-agent")
@app.entrypoint
def build_agent():
llm = app.llm(ChatOpenAI(model="gpt-5.4"))
a2a = app.a2a_tools()
llm_with_tools = llm.bind_tools(
app.get_tool_schemas() + a2a
)
tool_node = ToolNode(app.get_tools() + a2a)
graph = StateGraph(...)
return graph.compile(checkpointer=app.checkpointer())

Quando vinculado ao LLM, o modelo chama as duas ferramentas pelo nome. As ferramentas expõem as seguintes assinaturas de função:

  • discover_available_agents() retorna uma lista JSON de agentes visíveis para o agente de chamada. Cada entrada inclui agent_id, name, description, skills e capabilities. O agente de chamada é filtrado a partir de seus próprios resultados.

  • invoke_a2a_agent(agent_id, message, custom_headers="") invoca o agente de destino e retorna o resultado como JSON. Se você fornecer custom_headers, passe-a como uma string JSON, por exemplo '{"x-tenant": "acme"}'.

When you want to use deterministic routing, you can access the AgentToAgent client directly through runtime.a2a, an attribute that exposes the client.

O exemplo a seguir descobre os agentes por habilidade e invoca a primeira correspondência:

agents = app._runtime.a2a.discover_agents(
skills=["policy-lookup"],
limit=10,
)
if agents:
resp = app._runtime.a2a.invoke_agent(
agent_id=agents[0].agent_id,
message="Look up policy POL-123",
skill="policy-lookup",
timeout=120,
)
if resp.status == "completed":
print(resp.result)

O atributo runtime.a2a retorna None quando A2A não está disponível. Para saber quando isso ocorre, consulte Considerações. Sempre verifique esse caso antes de chamar os métodos do cliente , como mostrado no exemplo a seguir:

a2a = app._runtime.a2a
if a2a is None:
...

Observação

Acesse runtime.a2a no código do agente por meio de app._runtime.a2a. Não existe nenhum acessador app.a2a ou app.runtime público. Para a maioria dos casos de uso, app.a2a_tools() é a alternativa recomendada porque não depende de um atributo privado.

Nesta seção, você pode aprender sobre o SDK do cliente A2A, que fornece métodos para descobrir e invocar agentes programaticamente a partir do código do agente .

Para usar o SDK do cliente , importe os tipos A2A de agent_engine_runner_shared.a2a, conforme mostrado no exemplo a seguir:

from agent_engine_runner_shared.a2a import (
AgentToAgent,
DiscoveredAgent,
AgentSkill,
AgentResponse,
)

AgentToAgent é um cliente HTTP que se comunica com os endpoints OE /a2a/discover e /a2a/invoke. No código do agente , use a instância pré-autenticada de runtime.a2a em vez de construir essa classe diretamente.

O exemplo a seguir mostra o construtor e seus parâmetros:

AgentToAgent(oe_url: str, auth_token: str = "")

A tabela a seguir descreve os parâmetros do construtor AgentToAgent:

Argument
Descrição

oe_url

URL base HTTP do OE, por exemplo http://localhost:8000.

auth_token

A2A JSON Web Token (JWT) enviado como Authorization: Bearer <token>. Fornecido automaticamente quando você usa runtime.a2a.

O método discover_agents() retorna agentes que o chamador tem permissão para ver. Quando você passa vários valores em um único parâmetro de filtro, um agente corresponde se satisfizer qualquer um desses valores. Por exemplo, skills=["a", "b"] retorna agentes anunciando qualquer habilidade. Quando você passa vários parâmetros de filtro, um agente deve satisfazer todos eles. Os agentes que não são habilitados para A2A e excluem o chamador por meio de allowed_callers nunca são retornados.

O exemplo a seguir mostra este método e seus parâmetros:

discover_agents(
project_id: str = "",
skills: list[str] | None = None,
capabilities: list[str] | None = None,
input_modes: list[str] | None = None,
limit: int = 50,
) -> list[DiscoveredAgent]

A tabela seguinte descreve os parâmetros para o método discover_agents():

Parâmetro
Tipo
Descrição

project_id

str

Projeto para pesquisar. Uma string vazia usa o projeto do chamador.

skills

list[str]

Filtrar por nome da habilidade. Retorna agentes que tenham qualquer uma das habilidades listadas.

capabilities

list[str]

Filtrar por marcação de capacidade. Retorna agentes que têm qualquer um dos recursos listados.

input_modes

list[str]

Filtre por tipo de MIME aceito. Retorna agentes que aceitam qualquer um dos tipos de MIME listados.

limit

int

Número máximo de resultados a retornar. O padrão é 50.

O método invoke_agent() invoca um agente de destino e espera o resultado. O OE valida o token, verifica o controle de acesso, cria uma execução secundária e pesquisa até que o agente termine, suspenda para revisão humana ou expire.

O exemplo a seguir mostra este método e seus parâmetros:

invoke_agent(
agent_id: str,
message: str,
skill: str = "",
timeout: float | None = None,
custom_headers: dict[str, str] | None = None,
) -> AgentResponse

A tabela seguinte descreve os parâmetros para o método invoke_agent():

Parâmetro
Tipo
Descrição

agent_id

str

ID do espaço de trabalho de destino. Obtenha a partir de discover_agents().

message

str

Solicitação ou mensagem a ser enviada ao agente de destino.

skill

str

Dica de habilidade opcional para agentes que anunciam muitas habilidades.

timeout

flutuar | none

Segundos para esperar antes de atingir o tempo limite. None usa o padrão OE de 300 segundos. 300 segundos é o tempo limite máximo.

custom_headers

dict[str, str] | None

Cabeçalhos de valor-chave encaminhados para o contexto de execução do agente de destino. As chaves não devem usar o prefixo a2a- reservado. Para saber mais, consulte Encaminhar cabeçalhos personalizados.

A tabela a seguir lista os tipos de resposta, que são todas classes de dados imutáveis:

classe
Campos

DiscoveredAgent

agent_id, name, description, project_id, skills: list[AgentSkill], capabilities: list[str], input_modes: list[str], output_modes: list[str]

AgentSkill

name, description, example_input (opcional), example_output (opcional)

AgentResponse

status, result (opcional), error (opcional), execution_id

A tabela a seguir descreve cada valor possível para o campoAgentResponse.status :

Status
Significado
O que fazer

completed

O agente de destino concluiu com sucesso.

Leia result.

failed

O agente de destino retornou um erro.

Leia error.

input-required

O agente alvo suspenso para revisão humana.

Apresentar a pausa para seu usuário ou fluxo. Não trate isso como um fracasso.

Erros de nível de rede e HTTP, como tempos limite ou 4xx e respostas 5xx do OE, elevam um httpx.HTTPError dos métodos discover_agents() e invoke_agent(). Um AgentResponse que tem um valor status de failed indica que a chamada atingiu o OE, mas o próprio agente de destino falhou. Para lidar com erros de rede e falhas de agente , envolva as chamadas em blocos try/except e verifique o valor status.

O exemplo a seguir lida com todos os três valores de status:

resp = app._runtime.a2a.invoke_agent(
agent_id="ws-billing-001",
message="Process the payment",
)
if resp.status == "completed":
handle(resp.result)
elif resp.status == "input-required":
notify_user(
"The billing agent needs human approval before continuing."
)
else:
log.error("A2A call failed: %s", resp.error)

Você pode usar o A2A para anexar cabeçalhos de valor-chave arbitrários a uma invocação de agente para propagar o contexto do escopo da solicitação, como um ID de locatário, uma tag de rastreamento ou um token OAuth delegado.

Para anexar cabeçalhos a um agente chamado, passe um dict usando o parâmetro custom_headers de invoke_agent(). Ao utilizar a ferramenta LLM invoke_a2a_agent, passe cabeçalhos como uma string JSON.

O exemplo a seguir passa cabeçalhos personalizados usando o cliente direto :

app._runtime.a2a.invoke_agent(
agent_id="ws-billing-001",
message="Charge the customer",
custom_headers={
"x-tenant": "acme",
"oauth-token": "<delegated-token>",
},
)

O exemplo a seguir passa cabeçalhos personalizados usando a ferramenta LLM:

invoke_a2a_agent(
agent_id="ws-billing-001",
message="Charge the customer",
custom_headers='{"x-tenant": "acme"}',
)

As chaves de cabeçalho não devem usar o prefixo reservado a2a- insensível a maiúsculas e minúsculas. A OE rejeita solicitações com uma resposta 400 Bad Request se alguma chave começar com a2a-. O prefixo a2a- é reservado para roteamento de plataforma e cabeçalhos de identidade como a2a-token e a2a-caller-workspace.

Para ler cabeçalhos personalizados encaminhados por um agente de chamada, use o método get_current_custom_headers() da classeagent_engine_runner_shared.context. O exemplo a seguir chama este método:

from agent_engine_runner_shared.context import get_current_custom_headers
headers = get_current_custom_headers()
tenant = headers.get("x-tenant")

get_current_custom_headers() retorna um dict[str, str]. O método remove todos os cabeçalhos de plataforma a2a- antes de retornar, para que o código do agente nunca veja tokens A2A ou metadados de roteamento. Se o chamador não enviar cabeçalhos personalizados, o método retornará um dicionário vazio.

O campo a2a.allowed_callers em seu arquivo agent.yaml controla quais agentes podem descobrir seu por meio do seguinte comportamento:

  • Lista vazia (padrão): qualquer agente habilitado para A2A no mesmo projeto pode invocar seu agente e vê-lo nos resultados da descoberta.

  • Lista não vazia: somente os IDs de workspace listados podem invocar seu agente. Todos os outros agentes recebem uma resposta 403 e não podem ver seu agente nos resultados da descoberta.

O OE verifica a identidade do agente de chamada em sua lista allowed_callers antes de enviar. Nenhuma alteração de código é necessária em seu agente. O exemplo a seguir restringe a invocação a um único agente roteador:

a2a:
enabled: true
allowed_callers:
- "ws-router-002"

Cada chamada A2A aparece automaticamente no painel de rastreamento da sessão. Nenhuma instrumentação é necessária. A atividade do agente de destino aparece aninhada no mesmo rastreamento de sessão, para que você possa seguir a árvore de chamadas completa entre agentes em um só lugar.

Cada invocação é renderizada como um nó de subagente rotulado A2A: <target agent name>, retornando ao ID do espaço de trabalho do destino quando não tem nome de exibição. O nó mostra o status e a duração da chamada. O status começa como running e, em seguida, muda para done em caso de sucesso ou error em caso de falha. A seleção de um nó abre um painel de detalhes mostrando o nome, status, duração, descrição de despacho, saída transmitida e quaisquer erros.

As chamadas de ferramentas do agente de destino, as etapas do LLM e as operações de memória aparecem aninhadas no nó do subagente, reconstruindo a árvore de chamadas completa entre os agentes.

runtime.a2a retorna um cliente somente quando todas as seguintes condições forem verdadeiras:

  1. O código do agente está sendo executado na sandbox do agente . A2A não está disponível para código executado na sandbox da ferramenta.

  2. Uma URL OE está presente no contexto de execução.

  3. Um a2a-token está presente nos cabeçalhos recebidos. O OE injeta esse token automaticamente em cada despacho quando o A2A é configurado.

Quando qualquer condição não é atendida, runtime.a2a retorna None. Ao usar app.a2a_tools(), as ferramentas retornam um JSON de erro estruturado em vez de gerar uma exceção.

Por padrão, o token A2A expira após 5 minutos. Para fluxos típicos de solicitação e resposta, isso é suficiente. Os agentes que funcionam por mais tempo do que a vida útil do token podem receber uma resposta 401 nas chamadas A2A. A atualização automática do token ainda não foi implementada. Trate uma resposta 401 de uma chamada de longa duração como uma falha transitória.

A ferramenta LLM discover_available_agents filtra o espaço de trabalho do próprio agente de chamada dos resultados para que o modelo não chame a si mesmo. Se você usar o método bruto do cliente discover_agents(), o OE poderá incluir seu próprio agente nos resultados. Filtre você mesmo, se necessário.

Na versão atual, a descoberta e a invocação de A2A são limitadas aos agentes no mesmo projeto. O roteamento entre projetos ainda não foi implementado.

A plataforma registra e vincula todas as chamadas A2A automaticamente. Você não precisa adicionar instrumentação. O destino é executado como uma execução filho vinculada ao chamador por meio de parent_execution_id. Um root_session_id compartilhado agrupa a árvore completa de chamadas entre agentes na sessão do usuário de origem.

O exemplo a seguir mostra um agente roteador que usa o LLM para localizar e delegar a um agente especialista. O arquivo agent.yaml habilita A2A e declara uma habilidade route:

agent.yaml
name: router-agent
entrypoint: router_agent.main:app
a2a:
enabled: true
skills:
- name: route
description: Route a user request to the best specialist agent

O código do agente a seguir vincula as ferramentas A2A às suas próprias ferramentas e permite que o LLM cuide do roteamento:

main.py
from agent_engine_sdk_langgraph import App
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode
app = App(app_name="router-agent")
@app.entrypoint
def build_agent():
llm = app.llm(ChatOpenAI(model="gpt-5.4"))
a2a = app.a2a_tools()
llm_with_tools = llm.bind_tools(
app.get_tool_schemas() + a2a
)
def call_model(state: MessagesState):
return {
"messages": [llm_with_tools.invoke(state["messages"])]
}
graph = StateGraph(MessagesState)
graph.add_node("model", call_model)
graph.add_node("tools", ToolNode(app.get_tools() + a2a))
graph.set_entry_point("model")
graph.add_conditional_edges(
"model",
lambda s: (
"tools"
if s["messages"][-1].tool_calls
else "__end__"
),
)
graph.add_edge("tools", "model")
return graph.compile(checkpointer=app.checkpointer())

No tempo de execução, o LLM descobre um agente especialista que anuncia uma habilidade correspondente, chama-o por meio de invoke_a2a_agent, e o OE agencia a chamada enquanto impõe o controle de acesso e registra ambos os lados da invocação.

Para rotear deterministicamente em vez de depender do LLM, chame o cliente diretamente dentro de um nó do grafo:

def delegate(state):
a2a = app._runtime.a2a
if a2a is None:
return {"messages": [("ai", "A2A is unavailable.")]}
resp = a2a.invoke_agent(
agent_id="ws-insurance-001",
message=state["messages"][-1].content,
skill="policy-lookup",
custom_headers={"x-request-source": "router-agent"},
)
text = (
resp.result
if resp.status == "completed"
else f"({resp.status}) {resp.error}"
)
return {"messages": [("ai", text)]}

Depois de ativar a comunicação de agente para agente, você pode explorar os seguintes guias para saber mais sobre tarefas relacionadas: