Implementazione di server A2A in Runtime AgentCore
Amazon Bedrock AgentCore AgentCore Runtime consente di distribuire ed eseguire server Agent-to-Agent (A2A) nel Runtime. AgentCore Questa guida ti guida nella creazione, nel test e nella distribuzione del tuo primo server A2A.
In questa sezione, imparerai:
-
In che modo Amazon Bedrock AgentCore supporta A2A
-
Come creare un server A2A con funzionalità di agente
-
Come testare il server localmente
-
Come installare il server su AWS
-
Come richiamare il server distribuito
-
Come recuperare le carte degli agenti per scoprirle
Per ulteriori informazioni su A2A, vedere Contratto di protocollo A2A.
Argomenti
In che modo Amazon Bedrock AgentCore supporta A2A
Il supporto AgentCore del protocollo A2A di Amazon Bedrock consente una perfetta integrazione con i server A2A fungendo da livello proxy trasparente. Una volta configurato per A2A, Amazon Bedrock AgentCore prevede che i container eseguano server HTTP stateless e in streaming sulla porta nel percorso principale (0.0.0.0:9000/), 9000 in linea con la configurazione predefinita del server A2A.
Il servizio offre un isolamento delle sessioni di livello aziendale mantenendo al contempo la trasparenza del protocollo: i JSON-RPC payload dell'API vengono trasferiti direttamente al contenitore A2A senza modifiche. InvokeAgentRuntime Questa architettura preserva le funzionalità standard del protocollo A2A, come il rilevamento integrato degli agenti tramite Agent Cards at /.well-known/agent-card.json and JSON-RPC communication, aggiungendo al contempo l'autenticazione aziendale (2.0) e la scalabilità. SigV4/OAuth
I principali fattori di differenziazione dagli altri protocolli sono la porta (9000 vs 8080 per HTTP), il mount path (/vs/invocations) e il meccanismo standardizzato di rilevamento degli agenti, che rendono Amazon Bedrock AgentCore una piattaforma di distribuzione ideale per gli agenti A2A negli ambienti di produzione.
Principali differenze rispetto ad altri protocolli:
- Porta
-
I server A2A funzionano sulla porta 9000 (contro 8080 per HTTP, 8000 per MCP)
- Path
-
I server A2A sono montati su (rispetto a HTTP, a MCP
/)/invocations/mcp - Agent Cards
-
A2A offre un servizio integrato di rilevamento degli agenti tramite Agent Cards all'indirizzo
/.well-known/agent-card.json - Protocollo
-
Usi JSON-RPC per la comunicazione tra agenti
- Autenticazione
-
Supporta schemi di autenticazione SigV4 e OAuth 2.0
Per ulteriori informazioni, consulta https://a2a-protocol.org/
Utilizzo di A2A con Runtime AgentCore
In questo tutorial creerai, testerai e distribuirai un server A2A.
Argomenti
Prerequisiti
-
Python 3.10 o superiore installato e conoscenza di base di Python
-
Node.js 18 o versioni successive installate (richiesta per la AgentCore CLI)
-
La AgentCore CLI installata:
npm install -g @aws/agentcore -
Un AWS account con le autorizzazioni appropriate e le credenziali locali configurate
-
Comprensione del protocollo A2A e dei concetti di comunicazione agente-agente
Fase 1: Crea il tuo progetto A2A
Questo esempio utilizza Strands Agents, ma la AgentCore CLI supporta anche progetti LangChain/LangGraph A2A con Google ADK.
Scaffold: il progetto
Esegui il seguente comando e seleziona Strands come framework quando richiesto:
agentcore create --protocol A2A
La CLI supporta un progetto completo con tutte le dipendenze e le configurazioni richieste. Il file generato main.py contiene il tuo server A2A:
from strands import Agent, tool from strands.multiagent.a2a.executor import StrandsA2AExecutor from bedrock_agentcore.runtime import serve_a2a from model.load import load_model @tool def add_numbers(a: int, b: int) -> int: """Return the sum of two numbers.""" return a + b tools = [add_numbers] agent = Agent( model=load_model(), system_prompt="You are a helpful assistant. Use tools when appropriate.", tools=tools, ) if __name__ == "__main__": serve_a2a(StrandsA2AExecutor(agent))
Comprendere il codice
- Agente Strands
-
Crea un agente con strumenti e funzionalità specifici
- Strands A2A Executor
-
Avvolge l'agente Strands per fornire la compatibilità del protocollo A2A
- serve_a2a
-
L'helper Amazon Bedrock AgentCore SDK che avvia un Bedrock-compatible server A2A. Gestisce l'endpoint
/pingsanitario, il servizio Agent Card, la variabile diAGENTCORE_RUNTIME_URLambiente, la propagazione dell'intestazione Bedrock e, per impostazione predefinita, viene eseguito sulla porta 9000. - Porta 9000
-
Per impostazione predefinita, i server A2A funzionano sulla porta 9000 in Runtime AgentCore
Per personalizzare questo agente, sostituite add_numbers lo strumento con i vostri strumenti e aggiornate il prompt di sistema.
Fase 2: Esegui il test del server A2A a livello locale
Esegui e testa il tuo server A2A in un ambiente di sviluppo locale.
Avvia il tuo server A2A
Avvia il tuo server A2A localmente utilizzando la CLI: AgentCore
agentcore dev
Questo apre l' AgentCore Agent Inspector nel tuo browser web. Per utilizzare invece la TUI basata su terminale, usa. agentcore dev --no-browser
In alternativa, puoi eseguire direttamente il server:
python main.py
Dovresti vedere un output che indica che il server è in esecuzione sulla porta9000.
Invoca l'agente
curl -X POST http://localhost:9000/ \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "req-001", "method": "message/send", "params": { "message": { "role": "user", "parts": [ { "kind": "text", "text": "what is 101 * 11?" } ], "messageId": "12345678-1234-1234-1234-123456789012" } } }' | jq .
Recupero della carta dell'agente di test
Puoi testare localmente l'endpoint della carta agente:
curl http://localhost:9000/.well-known/agent-card.json | jq.
È inoltre possibile testare il server distribuito utilizzando A2A Inspector come descritto in Test remoti con A2A
Fase 3: Implementa il server A2A su Bedrock Runtime AgentCore
Configura il pool di utenti di Cognito per l'autenticazione
Prima della distribuzione, configura l'autenticazione per un accesso sicuro al server distribuito. Per istruzioni dettagliate sulla configurazione di Cognito, consulta Configurare il pool di utenti di Cognito per l'autenticazione. Ciò fornisce i token OAuth necessari per un accesso sicuro al server distribuito.
Esegui la distribuzione su AWS
Implementa il tuo agente:
agentcore deploy
Questo comando consentirà di:
-
Package del codice dell'agente e delle dipendenze
-
Carica l'artefatto di distribuzione su Amazon S3
-
Crea un runtime Amazon Bedrock AgentCore
-
Implementa il tuo agente su AWS
Dopo la distribuzione, riceverai un ARN di runtime dell'agente simile a:
arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/my_a2a_server-xyz123
Fase 4: Ottieni la carta dell'agente
Le Agent Card sono documenti di metadati JSON che descrivono l'identità, le capacità, le competenze, l'endpoint di servizio e i requisiti di autenticazione di un server A2A. Consentono l'individuazione automatica degli agenti nell'ecosistema A2A.
Impostazione delle variabili di ambiente
Impostazione delle variabili di ambiente
-
Esporta il token bearer come variabile di ambiente. Per la configurazione del token Bearer, vedere Configurazione del token Bearer.
export BEARER_TOKEN="<BEARER_TOKEN>" -
Esporta l'ARN dell'agente.
export AGENT_ARN="arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/my_a2a_server-xyz123"
Recupera la carta dell'agente
import os import json import requests from uuid import uuid4 from urllib.parse import quote def fetch_agent_card(): # Get environment variables agent_arn = os.environ.get('AGENT_ARN') bearer_token = os.environ.get('BEARER_TOKEN') if not agent_arn: print("Error: AGENT_ARN environment variable not set") return if not bearer_token: print("Error: BEARER_TOKEN environment variable not set") return # URL encode the agent ARN escaped_agent_arn = quote(agent_arn, safe='') # Construct the URL url = f"https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/{escaped_agent_arn}/invocations/.well-known/agent-card.json" # Generate a unique session ID session_id = str(uuid4()) print(f"Generated session ID: {session_id}") # Set headers headers = { 'Accept': '*/*', 'Authorization': f'Bearer {bearer_token}', 'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id': session_id } try: # Make the request response = requests.get(url, headers=headers) response.raise_for_status() # Parse and pretty print JSON agent_card = response.json() print(json.dumps(agent_card, indent=2)) return agent_card except requests.exceptions.RequestException as e: print(f"Error fetching agent card: {e}") return None if __name__ == "__main__": fetch_agent_card()
Dopo aver ottenuto l'URL dalla Agent Card, esporta AGENTCORE_RUNTIME_URL come variabile di ambiente:
export AGENTCORE_RUNTIME_URL="https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/<ARN>/invocations/"
Fase 5: richiama il server A2A distribuito
Crea codice client per richiamare il server Amazon Bedrock AgentCore A2A distribuito e invia messaggi per testarne la funzionalità.
Crea un nuovo file per richiamare il server my_a2a_client_remote.py A2A distribuito:
import asyncio import logging import os from uuid import uuid4 import httpx from a2a.client import A2ACardResolver, ClientConfig, ClientFactory from a2a.types import Message, Part, Role, TextPart logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) DEFAULT_TIMEOUT = 300 # set request timeout to 5 minutes def create_message(*, role: Role = Role.user, text: str) -> Message: return Message( kind="message", role=role, parts=[Part(TextPart(kind="text", text=text))], message_id=uuid4().hex, ) async def send_sync_message(message: str): # Get runtime URL from environment variable runtime_url = os.environ.get('AGENTCORE_RUNTIME_URL') # Generate a unique session ID session_id = str(uuid4()) print(f"Generated session ID: {session_id}") # Add authentication headers for Amazon Bedrock AgentCore headers = {"Authorization": f"Bearer {os.environ.get('BEARER_TOKEN')}", 'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id': session_id} async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT, headers=headers) as httpx_client: # Get agent card from the runtime URL resolver = A2ACardResolver(httpx_client=httpx_client, base_url=runtime_url) agent_card = await resolver.get_agent_card() # Agent card contains the correct URL (same as runtime_url in this case) # No manual override needed - this is the path-based mounting pattern # Create client using factory config = ClientConfig( httpx_client=httpx_client, streaming=False, # Use non-streaming mode for sync response ) factory = ClientFactory(config) client = factory.create(agent_card) # Create and send message msg = create_message(text=message) # With streaming=False, this will yield exactly one result async for event in client.send_message(msg): if isinstance(event, Message): logger.info(event.model_dump_json(exclude_none=True, indent=2)) return event elif isinstance(event, tuple) and len(event) == 2: # (Task, UpdateEvent) tuple task, update_event = event logger.info(f"Task: {task.model_dump_json(exclude_none=True, indent=2)}") if update_event: logger.info(f"Update: {update_event.model_dump_json(exclude_none=True, indent=2)}") return task else: # Fallback for other response types logger.info(f"Response: {str(event)}") return event # Usage - Uses AGENTCORE_RUNTIME_URL environment variable asyncio.run(send_sync_message("what is 101 * 11"))
Appendice
Argomenti
Configura il pool di utenti di Cognito per l'autenticazione
Per istruzioni dettagliate sulla configurazione di Cognito, consulta Configurare il pool di utenti Cognito per l'autenticazione nella documentazione MCP.
Test a distanza con A2A Inspector
Per informazioni, consulta https://github.com/a2aproject/a2a-inspector
Risoluzione dei problemi
Problemi comuni A2A-specific
Di seguito sono riportati i problemi più comuni che potresti riscontrare:
- Conflitti tra porte
-
I server A2A devono essere eseguiti sulla porta 9000 nell'ambiente Runtime AgentCore
- JSON-RPC errori
-
Verifica che il tuo client stia inviando messaggi JSON-RPC 2.0 formattati correttamente
- Mancata corrispondenza del metodo di autorizzazione
-
Assicurati che la richiesta utilizzi lo stesso metodo di autenticazione (OAuth o SigV4) con cui è stato configurato l'agente
Gestione delle eccezioni
Specifiche A2A per la gestione degli errori: https://a2a-protocol.org/latest/specification/#81-standard-json-rpc-errors
I server A2A restituiscono gli errori come risposte di JSON-RPC errore standard con codici di stato HTTP 200. Gli errori interni di runtime vengono automaticamente tradotti in errori JSON-RPC interni per mantenere la conformità del protocollo.
Il servizio ora fornisce risposte di A2A-compliant errore corrette con codici di JSON-RPC errore standardizzati:
| JSON-RPC Codice di errore | Eccezione di runtime | Codice di errore HTTP | JSON-RPC Messaggio di errore |
|---|---|---|---|
|
N/A |
|
403 |
N/A |
|
-32501 |
|
404 |
Risorsa non trovata: la risorsa richiesta non esiste |
|
-32502 |
|
400 |
Errore di convalida: dati di richiesta non validi |
|
-32503 |
|
429 |
Limite di frequenza superato: troppe richieste |
|
-32503 |
|
429 |
Limite di frequenza superato: troppe richieste |
|
-32504 |
|
409 |
Conflitto di risorse: la risorsa esiste già |
|
-32505 |
|
424 |
Errore del client di runtime: controlla i CloudWatch log per ulteriori informazioni. |