

# Déployer des serveurs A2A dans Runtime AgentCore
<a name="runtime-a2a"></a>

Amazon Bedrock AgentCore AgentCore Runtime vous permet de déployer et d'exécuter des serveurs Agent-to-Agent (A2A) dans le AgentCore Runtime. Ce guide vous explique comment créer, tester et déployer votre premier serveur A2A.

Dans cette section, vous allez apprendre :
+ Comment Amazon Bedrock AgentCore prend en charge l'A2A
+ Comment créer un serveur A2A doté de fonctionnalités d'agent
+ Comment tester votre serveur en local
+ Comment déployer votre serveur sur AWS 
+ Comment appeler votre serveur déployé
+ Comment récupérer des cartes d'agent à des fins de découverte

Pour plus d'informations sur l'A2A, consultez le contrat de [protocole A2A](runtime-a2a-protocol-contract.md).

**Topics**
+ [Comment Amazon Bedrock AgentCore prend en charge l'A2A](#runtime-a2a-how-agentcore-supports)
+ [Utilisation d'A2A avec Runtime AgentCore](#runtime-a2a-steps)
+ [Annexe](#runtime-a2a-appendix)

## Comment Amazon Bedrock AgentCore prend en charge l'A2A
<a name="runtime-a2a-how-agentcore-supports"></a>

La prise en charge AgentCore du protocole A2A d'Amazon Bedrock permet une intégration parfaite avec les serveurs A2A en agissant comme une couche proxy transparente. Lorsqu'ils sont configurés pour A2A, Amazon Bedrock AgentCore s'attend à ce que les conteneurs exécutent des serveurs HTTP apatrides et streamables sur le port situé sur le chemin racine (`0.0.0.0:9000/`), ce qui correspond `9000` à la configuration du serveur A2A par défaut.

Le service permet d'isoler les sessions de niveau professionnel tout en préservant la transparence du protocole : les JSON-RPC charges utiles de l'[InvokeAgentRuntime](https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_InvokeAgentRuntime.html)API sont transmises directement au conteneur A2A sans modification. Cette architecture préserve les fonctionnalités standard du protocole A2A, telles que la découverte intégrée des agents par le biais de cartes d'agent `/.well-known/agent-card.json` et de JSON-RPC communication, tout en ajoutant l'authentification d'entreprise (SigV4/OAuth 2.0) et l'évolutivité.

Les principaux facteurs de différenciation par rapport aux autres protocoles sont le port (9000 contre 8080 pour HTTP), le chemin de montage (`/`vs`/invocations`) et le mécanisme standardisé de découverte des agents, faisant d'Amazon Bedrock AgentCore une plate-forme de déploiement idéale pour les agents A2A dans les environnements de production.

Principales différences par rapport aux autres protocoles :

 **Port**   
Les serveurs A2A fonctionnent sur le port 9000 (contre 8080 pour HTTP, 8000 pour MCP)

 **Chemin**   
Les serveurs A2A sont montés sur `/` (contre HTTP, `/invocations` `/mcp` pour MCP)

 **Cartes d'agent**   
L'A2A fournit une fonction intégrée de découverte des agents via des cartes d'agent sur `/.well-known/agent-card.json` 

 **Protocole**   
Utilisations JSON-RPC de la communication agent-agent

 **Authentification**   
Supporte les schémas d'authentification Sigv4 et OAuth 2.0

Pour de plus amples informations, veuillez consulter [https://a2a-protocol.org/](https://a2a-protocol.org/).

## Utilisation d'A2A avec Runtime AgentCore
<a name="runtime-a2a-steps"></a>

Dans ce didacticiel, vous allez créer, tester et déployer un serveur A2A.

**Topics**
+ [Conditions préalables](#runtime-a2a-prerequisites)
+ [Étape 1 : Créez votre projet A2A](#runtime-a2a-create-server)
+ [Étape 2 : Testez votre serveur A2A localement](#runtime-a2a-test-locally)
+ [Étape 3 : Déployez votre serveur A2A sur Bedrock Runtime AgentCore](#runtime-a2a-deploy)
+ [Étape 4 : Obtenir la carte d'agent](#runtime-a2a-step-4)
+ [Étape 5 : Invoquez votre serveur A2A déployé](#runtime-a2a-step-5)

### Conditions préalables
<a name="runtime-a2a-prerequisites"></a>
+ Python 3.10 ou supérieur installé et compréhension de base de Python
+ Node.js 18 ou version supérieure installée (obligatoire pour la AgentCore CLI)
+ La AgentCore CLI installée : `npm install -g @aws/agentcore` 
+ Un AWS compte avec les autorisations appropriées et les informations d'identification locales configurées
+ Compréhension du protocole A2A et des concepts de communication agent-agent

### Étape 1 : Créez votre projet A2A
<a name="runtime-a2a-create-server"></a>

Cet exemple utilise des agents Strands, mais la AgentCore CLI prend également en charge les projets A2A avec LangChain/LangGraph Google ADK.

#### Échafaudage du projet
<a name="runtime-a2a-scaffold-project"></a>

Exécutez la commande suivante et sélectionnez *Strands* comme framework lorsque vous y êtes invité :

```
agentcore create --protocol A2A
```

La CLI échafaude un projet complet avec toutes les dépendances et configurations requises. Le fichier généré `main.py` contient votre serveur 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))
```

#### Comprendre le code
<a name="runtime-a2a-understanding-code"></a>

 **Agent Strands**   
Crée un agent doté d'outils et de capacités spécifiques

 **Exécuteur Strands A2a**   
Enveloppe l'agent Strands pour assurer la compatibilité du protocole A2A

 **serve\_a2a**   
L'assistant du AgentCore SDK Amazon Bedrock qui démarre un Bedrock-compatible serveur A2A. Il gère le point de terminaison de `/ping` santé, le service de carte agent, la variable d'`AGENTCORE_RUNTIME_URL`environnement, la propagation de l'en-tête Bedrock et s'exécute sur le port 9000 par défaut.

 **Port 9000**   
Les serveurs A2A s'exécutent sur le port 9000 par défaut dans Runtime AgentCore 

Pour personnaliser cet agent, remplacez l'`add_numbers`outil par vos propres outils et mettez à jour l'invite du système.

### Étape 2 : Testez votre serveur A2A localement
<a name="runtime-a2a-test-locally"></a>

Exécutez et testez votre serveur A2A dans un environnement de développement local.

#### Démarrez votre serveur A2A
<a name="runtime-a2a-start-server"></a>

Démarrez votre serveur A2A localement à l'aide de la AgentCore CLI :

```
agentcore dev
```

L'inspecteur des AgentCore agents s'ouvre alors dans votre navigateur Web. Pour utiliser le TUI basé sur un terminal à la place, utilisez. `agentcore dev --no-browser`

Vous pouvez également exécuter le serveur directement :

```
python main.py
```

Vous devriez voir une sortie indiquant que le serveur fonctionne sur le port`9000`.

#### Invoquer l'agent
<a name="runtime-a2a-invoke-agent"></a>

```
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 .
```

#### Récupération de la carte d'agent de test
<a name="runtime-a2a-test-agent-card"></a>

Vous pouvez tester le point de terminaison de la carte agent localement :

```
curl http://localhost:9000/.well-known/agent-card.json | jq.
```

Vous pouvez également tester votre serveur déployé à l'aide de l'inspecteur A2A, comme décrit dans [Tests à distance avec l'inspecteur A2A](https://github.com/a2aproject/a2a-inspector).

### Étape 3 : Déployez votre serveur A2A sur Bedrock Runtime AgentCore
<a name="runtime-a2a-deploy"></a>

#### Configuration du groupe d'utilisateurs Cognito pour l'authentification
<a name="runtime-a2a-setup-cognito"></a>

Avant le déploiement, configurez l'authentification pour un accès sécurisé à votre serveur déployé. Pour obtenir des instructions détaillées sur la configuration de Cognito, voir [Configurer le groupe d'utilisateurs de Cognito](runtime-mcp.md#runtime-mcp-appendix-a) pour l'authentification. Cela fournit les jetons OAuth nécessaires pour un accès sécurisé à votre serveur déployé.

#### Déployer vers AWS
<a name="runtime-a2a-deploy-aws"></a>

Déployez votre agent :

```
agentcore deploy
```

Cette commande permettra de :

1. Package du code de votre agent et de ses dépendances

1. Téléchargez l'artefact de déploiement sur Amazon S3

1. Création d'un environnement d'exécution Amazon Bedrock AgentCore 

1. Déployez votre agent sur AWS 

Après le déploiement, vous recevrez un ARN d'exécution de l'agent qui ressemble à ce qui suit :

```
arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/my_a2a_server-xyz123
```

### Étape 4 : Obtenir la carte d'agent
<a name="runtime-a2a-step-4"></a>

Les cartes d'agent sont des documents de métadonnées JSON qui décrivent l'identité, les capacités, les compétences, le point de terminaison du service et les exigences d'authentification d'un serveur A2A. Ils permettent la découverte automatique des agents dans l'écosystème A2A.

#### Configurer les variables d’environnement
<a name="runtime-a2a-step-4-setup-environment-variables"></a>

Configurer les variables d’environnement

1. Exportez le jeton porteur en tant que variable d'environnement. Pour la configuration du jeton porteur, voir Configuration du [jeton porteur](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-mcp.html#runtime-mcp-appendix).

   ```
   export BEARER_TOKEN="<BEARER_TOKEN>"
   ```

1. Exportez l'ARN de l'agent.

   ```
   export AGENT_ARN="arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/my_a2a_server-xyz123"
   ```

#### Récupérez la carte d'agent
<a name="retrieve-agent-card"></a>

```
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()
```

Une fois que vous avez obtenu l'URL depuis la carte d'agent, exportez-la `AGENTCORE_RUNTIME_URL` en tant que variable d'environnement :

```
export AGENTCORE_RUNTIME_URL="https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/<ARN>/invocations/"
```

### Étape 5 : Invoquez votre serveur A2A déployé
<a name="runtime-a2a-step-5"></a>

Créez un code client pour appeler votre serveur Amazon Bedrock AgentCore A2A déployé et envoyez des messages pour tester les fonctionnalités.

Créez un nouveau fichier `my_a2a_client_remote.py` pour appeler votre serveur A2A déployé :

```
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"))
```

## Annexe
<a name="runtime-a2a-appendix"></a>

**Topics**
+ [Configuration du groupe d'utilisateurs Cognito pour l'authentification](#runtime-a2a-setup-cognito-appendix)
+ [Tests à distance avec l'inspecteur A2A](#runtime-a2a-remote-testing)
+ [Résolution des problèmes](#runtime-a2a-troubleshooting)

### Configuration du groupe d'utilisateurs Cognito pour l'authentification
<a name="runtime-a2a-setup-cognito-appendix"></a>

Pour obtenir des instructions détaillées sur la configuration de Cognito, consultez la section Configurer le groupe [d'utilisateurs Cognito pour l'authentification](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-mcp.html#set-up-cognito-user-pool-for-authentication) dans la documentation MCP.

### Tests à distance avec l'inspecteur A2A
<a name="runtime-a2a-remote-testing"></a>

Consultez [https://github.com/a2aproject/a2a-inspector](https://github.com/a2aproject/a2a-inspector).

### Résolution des problèmes
<a name="runtime-a2a-troubleshooting"></a>

 ** A2A-specific Problèmes courants** 

Les problèmes courants que vous pouvez rencontrer sont les suivants :

Conflits portuaires  
Les serveurs A2A doivent fonctionner sur le port 9000 dans l' AgentCore environnement d'exécution

JSON-RPC erreurs  
Vérifiez que votre client envoie des messages JSON-RPC 2.0 correctement formatés

Incompatibilité entre les méthodes d'autorisation  
Assurez-vous que votre demande utilise la même méthode d'authentification (OAuth ou Sigv4) que celle avec laquelle l'agent a été configuré

 **Gestion des exceptions** 

Spécifications A2A pour la gestion des erreurs : [https://a2a-protocol.org/latest/specification/#81-standard-json-rpc-errors](https://a2a-protocol.org/latest/specification/#81-standard-json-rpc-errors) 

Les serveurs A2A renvoient les erreurs sous forme de réponses JSON-RPC d'erreur standard avec des codes d'état HTTP 200. Les erreurs d'exécution internes sont automatiquement converties en erreurs JSON-RPC internes afin de garantir la conformité au protocole.

Le service fournit désormais des réponses aux A2A-compliant erreurs appropriées avec des codes JSON-RPC d'erreur standardisés :


| JSON-RPC Code d'erreur | Exception d'exécution | Code d'erreur HTTP | JSON-RPC Message d'erreur | 
| --- | --- | --- | --- | 
| N/A |  `AccessDeniedException`  | 403 | N/A | 
| -32501 |  `ResourceNotFoundException`  | 404 | Ressource introuvable — La ressource demandée n'existe pas | 
| -32502 |  `ValidationException`  | 400 | Erreur de validation — Données de demande non valides | 
| -32503 |  `ThrottlingException`  | 429 | Limite de débit dépassée — Trop de demandes | 
| -32503 |  `ServiceQuotaExceededException`  | 429 | Limite de débit dépassée — Trop de demandes | 
| -32504 |  `ResourceConflictException`  | 409 | Conflit de ressources — La ressource existe déjà | 
| -32505 |  `RuntimeClientError`  | 424 | Erreur du client d'exécution : consultez vos CloudWatch journaux pour plus d'informations. | 