Exemplos de Integração A2A¶
Os exemplos abaixo seguem o schema real do a2a-sdk (
kindcomo discriminador de parts,messageIdobrigatório, resposta como objetoTask). Para uma referência viva e testada, vejaexamples/a2a_test_cli.py(login + agent card + envio) eexamples/a2a_echo_agent.py+examples/a2a_outbound_roundtrip_test.py(servidor de teste A2A independente + script que valida o roundtrip completo) no repositório.
Python (requests)¶
import requests
import uuid
A2A_BASE_URL = "https://agents.theifriend.com/trip/a2a"
A2A_JWT_TOKEN = "seu_token_aqui" # obtido via POST /authentication_token
def send_message(message: str, context_id: str | None = None):
payload = {
"jsonrpc": "2.0",
"id": str(uuid.uuid4()),
"method": "message/send",
"params": {
"message": {
"role": "user",
"messageId": str(uuid.uuid4()),
"parts": [{"kind": "text", "text": message}],
**({"contextId": context_id} if context_id else {}),
}
},
}
headers = {"Authorization": f"Bearer {A2A_JWT_TOKEN}"}
resp = requests.post(f"{A2A_BASE_URL}/", json=payload, headers=headers)
resp.raise_for_status()
return resp.json()["result"]
def extract_text(task: dict) -> str:
"""Task.status.message.parts (resposta síncrona) é onde o texto do
agente normalmente aparece; artifacts é o fallback para resultados
"finais" de tasks mais longas."""
status_message = (task.get("status") or {}).get("message") or {}
for part in status_message.get("parts", []):
if part.get("kind") == "text":
return part["text"]
for artifact in task.get("artifacts") or []:
for part in artifact.get("parts", []):
if part.get("kind") == "text":
return part["text"]
return ""
task = send_message("Quero experiências em São Paulo")
print(extract_text(task))
print("task id:", task["id"], "| context id:", task.get("contextId"))
JavaScript/Node.js¶
const { v4: uuidv4 } = require('uuid');
const A2A_BASE_URL = 'https://agents.theifriend.com/trip/a2a';
const A2A_JWT_TOKEN = 'seu_token_aqui'; // obtido via POST /authentication_token
async function sendMessage(message, contextId) {
const messagePayload = {
role: 'user',
messageId: uuidv4(),
parts: [{ kind: 'text', text: message }],
};
if (contextId) messagePayload.contextId = contextId;
const response = await fetch(`${A2A_BASE_URL}/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${A2A_JWT_TOKEN}`,
},
body: JSON.stringify({
jsonrpc: '2.0',
id: uuidv4(),
method: 'message/send',
params: { message: messagePayload },
}),
});
const body = await response.json();
return body.result; // objeto Task — ver status.message.parts / artifacts
}
const task = await sendMessage('Quero experiências em São Paulo');
console.log(task);
cURL¶
curl -X POST https://agents.theifriend.com/trip/a2a/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "message/send",
"params": {
"message": {
"role": "user",
"messageId": "msg-001",
"parts": [{"kind": "text", "text": "Quero experiências em São Paulo"}]
}
}
}'
Consultando e cancelando uma task¶
# tasks/get — note "id", não "taskId"
curl -X POST https://agents.theifriend.com/trip/a2a/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN" \
-d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"id":"<task_id_da_resposta_anterior>"}}'
# tasks/cancel — cooperativo: nunca falha, mas não interrompe uma geração já em andamento
curl -X POST https://agents.theifriend.com/trip/a2a/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN" \
-d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"id":"<task_id_da_resposta_anterior>"}}'