

# Implemente servidores A2A en tiempo de ejecución AgentCore
<a name="runtime-a2a"></a>

Amazon Bedrock AgentCore AgentCore Runtime le permite implementar y ejecutar servidores Agent-to-Agent (A2A) en Runtime. AgentCore Esta guía explica cómo crear, probar e implementar su primer servidor A2A.

En esta sección, aprenderá lo siguiente:
+ Cómo Amazon Bedrock AgentCore apoya el A2A
+ ¿Cómo crear un servidor A2A con funciones de agente
+ ¿Cómo probar su servidor localmente
+ Cómo implementar su servidor en AWS 
+ ¿Cómo invocar el servidor desplegado
+ ¿Cómo recuperar las tarjetas de agente para su detección

Para obtener más información sobre la A2A, consulte el contrato de [protocolo A2A](runtime-a2a-protocol-contract.md).

**Topics**
+ [Cómo Amazon Bedrock AgentCore apoya el A2A](#runtime-a2a-how-agentcore-supports)
+ [Uso de A2A con Runtime AgentCore](#runtime-a2a-steps)
+ [Apéndice](#runtime-a2a-appendix)

## Cómo Amazon Bedrock AgentCore apoya el A2A
<a name="runtime-a2a-how-agentcore-supports"></a>

La compatibilidad con el protocolo A2A AgentCore de Amazon Bedrock permite una integración perfecta con los servidores A2A al actuar como una capa de proxy transparente. Cuando se configura para A2A, Amazon Bedrock AgentCore espera que los contenedores ejecuten servidores HTTP sin estado y con capacidad de transmisión en el puerto de la ruta raíz (`0.0.0.0:9000/`), lo que se `9000` alinea con la configuración predeterminada del servidor A2A.

El servicio proporciona un aislamiento de sesiones de nivel empresarial y, al mismo tiempo, mantiene la transparencia del protocolo: JSON-RPC las cargas útiles de la [InvokeAgentRuntime](https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_InvokeAgentRuntime.html)API se transfieren directamente al contenedor A2A sin modificaciones. Esta arquitectura conserva las funciones estándar del protocolo A2A, como la detección de agentes integrada mediante tarjetas de agente `/.well-known/agent-card.json` y la JSON-RPC comunicación, al tiempo que añade la autenticación empresarial (SigV4/OAuth 2.0) y la escalabilidad.

Los principales diferenciadores de otros protocolos son el puerto (9000 frente a 8080 para HTTP), la ruta de montaje y el mecanismo estandarizado de descubrimiento de agentes, lo que convierte a Amazon Bedrock en AgentCore una plataforma de implementación ideal para los agentes de A2A en entornos de producción. `/` `/invocations`

Principales diferencias con respecto a otros protocolos:

 **Puerto**   
Los servidores A2A se ejecutan en el puerto 9000 (frente al 8080 para HTTP y el 8000 para el MCP)

 **Ruta**   
Los servidores A2A se montan en `/` (frente a los de HTTP y `/invocations` MCP) `/mcp`

 **Tarjetas de agente**   
El A2A ofrece una función integrada de detección de agentes mediante tarjetas de agente en `/.well-known/agent-card.json` 

 **Protocolo**   
Se utiliza JSON-RPC para la comunicación entre agentes

 **Autenticación**   
Admite los esquemas de autenticación SigV4 y OAuth 2.0

Para obtener más información, consulte [https://a2a-protocol.org/](https://a2a-protocol.org/).

## Uso de A2A con Runtime AgentCore
<a name="runtime-a2a-steps"></a>

En este tutorial, creará, probará e implementará un servidor A2A.

**Topics**
+ [Requisitos previos](#runtime-a2a-prerequisites)
+ [Paso 1: Crea tu proyecto A2A](#runtime-a2a-create-server)
+ [Paso 2: Pruebe su servidor A2A localmente](#runtime-a2a-test-locally)
+ [Paso 3: Implemente su servidor A2A en Bedrock Runtime AgentCore](#runtime-a2a-deploy)
+ [Paso 4: Obtenga la tarjeta de agente](#runtime-a2a-step-4)
+ [Paso 5: invoque el servidor A2A desplegado](#runtime-a2a-step-5)

### Requisitos previos
<a name="runtime-a2a-prerequisites"></a>
+ Python 3.10 o superior instalado y conocimientos básicos de Python
+ Node.js 18 o más instalados (necesarios para la AgentCore CLI)
+ La AgentCore CLI instalada: `npm install -g @aws/agentcore` 
+ Una AWS cuenta con los permisos y las credenciales locales adecuados configurados
+ Comprensión del protocolo A2A y de los conceptos de comunicación entre agentes

### Paso 1: Crea tu proyecto A2A
<a name="runtime-a2a-create-server"></a>

Este ejemplo usa Strands Agents, pero la AgentCore CLI también admite proyectos A2A con LangChain/LangGraph Google ADK.

#### Organiza el proyecto
<a name="runtime-a2a-scaffold-project"></a>

Ejecuta el siguiente comando y selecciona *Strands* como marco cuando se te pida:

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

La CLI estructura un proyecto completo con todas las dependencias y configuraciones requeridas. El generado `main.py` contiene su servidor 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))
```

#### Entendiendo el código
<a name="runtime-a2a-understanding-code"></a>

 **Agente de Strands**   
Crea un agente con herramientas y capacidades específicas

 **Strand SA2A Executor**   
Envuelve el agente Strands para proporcionar compatibilidad con el protocolo A2A

 **serve\_a2a**   
El asistente del AgentCore SDK de Amazon Bedrock que inicia un servidor Bedrock-compatible A2A. Gestiona el punto final de `/ping` salud, el servicio de tarjetas de agente, la variable de `AGENTCORE_RUNTIME_URL` entorno y la propagación del encabezado de Bedrock y, de forma predeterminada, se ejecuta en el puerto 9000.

 **Puerto 9000**   
Los servidores A2A se ejecutan en el puerto 9000 de forma predeterminada en Runtime AgentCore 

Para personalizar este agente, sustituya la `add_numbers` herramienta por las suyas propias y actualice el indicador del sistema.

### Paso 2: Pruebe su servidor A2A localmente
<a name="runtime-a2a-test-locally"></a>

Ejecute y pruebe su servidor A2A en un entorno de desarrollo local.

#### Inicie su servidor A2A
<a name="runtime-a2a-start-server"></a>

Inicie su servidor A2A localmente mediante la AgentCore CLI:

```
agentcore dev
```

Esto abre el inspector de AgentCore agentes en su navegador web. Para utilizar en su lugar la TUI basada en el terminal, utilice. `agentcore dev --no-browser`

Como alternativa, puede ejecutar el servidor directamente:

```
python main.py
```

Debería ver un resultado que indica que el servidor se está ejecutando en el puerto`9000`.

#### Invoca al agente
<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 .
```

#### Pruebe la recuperación de la tarjeta del agente
<a name="runtime-a2a-test-agent-card"></a>

Puede probar el punto final de la tarjeta de agente de forma local:

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

También puede probar el servidor desplegado con el Inspector A2A, tal y como se describe en [Pruebas remotas con el inspector A2A](https://github.com/a2aproject/a2a-inspector).

### Paso 3: Implemente su servidor A2A en Bedrock Runtime AgentCore
<a name="runtime-a2a-deploy"></a>

#### Configurar el grupo de usuarios de Cognito para la autenticación
<a name="runtime-a2a-setup-cognito"></a>

Antes de la implementación, configure la autenticación para un acceso seguro al servidor implementado. Para obtener instrucciones detalladas de configuración de Cognito, consulte [Configurar el grupo de usuarios de Cognito para la autenticación](runtime-mcp.md#runtime-mcp-appendix-a). Esto proporciona los tokens de OAuth necesarios para un acceso seguro al servidor implementado.

#### Implemente en AWS
<a name="runtime-a2a-deploy-aws"></a>

Despliegue a su agente:

```
agentcore deploy
```

Este comando hará lo siguiente:

1. Package su código de agente y sus dependencias

1. Cargue el artefacto de implementación en Amazon S3

1. Cree un entorno de ejecución de Amazon Bedrock AgentCore 

1. Despliegue a su agente en AWS 

Tras la implementación, recibirá un ARN de tiempo de ejecución del agente con el siguiente aspecto:

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

### Paso 4: Obtenga la tarjeta de agente
<a name="runtime-a2a-step-4"></a>

Las tarjetas de agente son documentos de metadatos JSON que describen la identidad, las capacidades, las habilidades, el punto final del servicio y los requisitos de autenticación de un servidor A2A. Permiten la detección automática de agentes en el ecosistema A2A.

#### Configure las variables de entorno
<a name="runtime-a2a-step-4-setup-environment-variables"></a>

Configure las variables de entorno

1. Exporta el token portador como variable de entorno. Para ver la configuración del token de portador, consulte Configuración del token [de portador](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-mcp.html#runtime-mcp-appendix).

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

1. Exporte el ARN del agente.

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

#### Recupera la tarjeta de agente
<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()
```

Después de obtener la URL de la tarjeta de agente, expórtela `AGENTCORE_RUNTIME_URL` como una variable de entorno:

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

### Paso 5: invoque el servidor A2A desplegado
<a name="runtime-a2a-step-5"></a>

Cree un código de cliente para invocar el servidor Amazon Bedrock AgentCore A2A implementado y envíe mensajes para probar la funcionalidad.

Cree un archivo nuevo `my_a2a_client_remote.py` para invocar el servidor A2A implementado:

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

## Apéndice
<a name="runtime-a2a-appendix"></a>

**Topics**
+ [Configurar el grupo de usuarios de Cognito para la autenticación](#runtime-a2a-setup-cognito-appendix)
+ [Pruebas remotas con el inspector A2A](#runtime-a2a-remote-testing)
+ [Resolución de problemas](#runtime-a2a-troubleshooting)

### Configurar el grupo de usuarios de Cognito para la autenticación
<a name="runtime-a2a-setup-cognito-appendix"></a>

Para obtener instrucciones detalladas de configuración de Cognito, consulte Configurar el grupo de [usuarios de Cognito para la autenticación en la documentación](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-mcp.html#set-up-cognito-user-pool-for-authentication) de MCP.

### Pruebas remotas con el inspector A2A
<a name="runtime-a2a-remote-testing"></a>

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

### Resolución de problemas
<a name="runtime-a2a-troubleshooting"></a>

 **Problemas comunes A2A-specific ** 

Los siguientes son problemas comunes que pueden surgir:

Conflictos portuarios  
Los servidores A2A deben ejecutarse en el puerto 9000 en el AgentCore entorno de ejecución

JSON-RPC errores  
Compruebe que su cliente envía mensajes JSON-RPC 2.0 con el formato correcto

El método de autorización no coincide  
Asegúrese de que la solicitud utilice el mismo método de autenticación (OAuth o SigV4) con el que se configuró el agente

 **Gestión de excepciones** 

Especificaciones A2A para el manejo de errores: [https://a2a-protocol.org/latest/specification/#81-standard-json-rpc-errors](https://a2a-protocol.org/latest/specification/#81-standard-json-rpc-errors) 

Los servidores A2A devuelven los errores como respuestas de JSON-RPC error estándar con códigos de estado HTTP 200. Los errores de tiempo de ejecución internos se traducen automáticamente en errores JSON-RPC internos para mantener el cumplimiento del protocolo.

El servicio ahora proporciona respuestas de A2A-compliant error adecuadas con códigos de JSON-RPC error estandarizados:


| JSON-RPC Código de error | Excepción de ejecución | Código de error HTTP | JSON-RPC Mensaje de error | 
| --- | --- | --- | --- | 
| N/A |  `AccessDeniedException`  | 403 | N/A | 
| -32501 |  `ResourceNotFoundException`  | 404 | Recurso no encontrado: el recurso solicitado no existe | 
| -32502 |  `ValidationException`  | 400 | Error de validación: datos de solicitud no válidos | 
| -32503 |  `ThrottlingException`  | 429 | Se ha superado el límite de frecuencia: demasiadas solicitudes | 
| -32503 |  `ServiceQuotaExceededException`  | 429 | Se ha superado el límite de frecuencia: demasiadas solicitudes | 
| -32504 |  `ResourceConflictException`  | 409 | Conflicto de recursos: el recurso ya existe | 
| -32505 |  `RuntimeClientError`  | 424 | Error del cliente en tiempo de ejecución: consulta tus CloudWatch registros para obtener más información. | 