23 Despliegue de Agente

Al desplegar un agente, éste se convierte en una aplicación alojada.

Puede desplegar un agente en el mismo recurso informático de IA conectado a su patio de recreo o a otro recurso informático de IA. Al desplegar los últimos cambios en el agente en los recursos informáticos de AI asociados, el agente desplegado representa una instantánea del agente en el momento del despliegue. Para actualizar el agente desplegado a la última versión, debe volver a desplegar el agente.

Cada agente tiene una URL de despliegue estable que depende de la clave de agente única. El nuevo despliegue del agente varias veces sobrescribe al agente detrás de la URL de despliegue.

El despliegue de los agentes tiene las siguientes limitaciones:
  • Un agente solo se puede desplegar en un cluster de recursos informáticos de AI en un momento determinado.
  • Al desplegar el mismo agente varias veces en el mismo cluster de recursos informáticos de AI, se sobrescribe la iteración desplegada anteriormente del agente.

Una vez desplegado un agente, puede recuperar el URI de chat para emitir consultas mediante programación y recuperar respuestas del agente desde el separador Detalles de su agente.


Se abre la página Agente con el separador Detalle abierto y resaltado. Se resaltan el despliegue en AI Compute y la URL de punto final

La URL de punto final es estable y está vinculada a cada agente. La URL incluye el ID de agente único asignado a cada agente. Es decir, si anula el despliegue de un agente y lo vuelve a desplegar, la URL sigue siendo la misma. La ventaja es que no tiene que modificar el código de cliente que llama al punto final, la desventaja es que puede sobrescribir un agente en producción.

La URL tiene la siguiente estructura:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/{protocol}
donde:
  • oci-region corresponde a la región de instancia de AI Data Platform;
  • agentId es el ID único asociado al agente
  • protocol es el protocolo de comunicación: chat, que sigue el formato de API de respuestas de OpenAI y a2a, que sigue el protocolo de comunicación de agente a agente. Ambos protocolos están disponibles para cada punto final de agente. Para obtener más información, consulte Despliegue de agente A2A.

Note:

En el separador Details se muestran dos cálculos de AI. El comando Asociado a AI Compute se utiliza para probar el agente en el patio de recreo. Desplegado en AI Compute aloja el agente desplegado.

El campo URL de punto final se rellena después de desplegar el agente. Puede llamar a esta URL de punto final desde la aplicación de producción.

Despliegue de un agente

Despliega los agentes que ha creado y configurado para que otros usuarios puedan verlos y utilizarlos en su instancia de AI Data Platform.

  1. En la página inicial, vaya a la carpeta que contiene el agente que desea desplegar.
  2. Junto al agente, haga clic en Icono de tres puntos de acciones Acciones y en Desplegar. También puede hacer clic en el nombre del agente y en Desplegar en la parte superior derecha.

    El agente se abre con el botón Desplegar en la parte superior derecha de la pantalla resaltado

  3. Seleccione los recursos informáticos de AI que desea asociar al agente desplegado.
  4. Seleccione AIDP Workbench para el tipo de autorización.
  5. Seleccione una política de retención de datos de sesión.
    • Para el período de retención, indique el número de días que se conservan los datos de la sesión.
    • Para Límite de tamaño de sesión, proporcione el tamaño máximo que puede alcanzar una sesión.
    • Para Límite de recuento de threads, proporcione el número máximo de threads de sesión que se retienen.
  6. Haga clic en Desplegar.

Despliegue de un agente con OAuth2

Puede desplegar los agentes que ha creado y configurado para utilizar la autenticación de OAuth2 para conectarse a proveedores de identidad externos.

  1. En la página inicial, vaya a la carpeta que contiene el agente que desea desplegar.
  2. Junto al agente, haga clic en Icono de tres puntos de acciones Acciones y en Desplegar. También puede hacer clic en el nombre del agente y en Desplegar en la parte superior derecha.

    El agente se abre con el botón Desplegar en la parte superior derecha de la pantalla resaltado

  3. Seleccione los recursos informáticos de AI que desea asociar al agente desplegado.
  4. Seleccione OAuth2 para el tipo de autorización.
  5. Proporcione la reclamación de público. AI Data Platform Workbench rellena automáticamente este campo, pero puede sustituirlo por una reclamación de público de su proveedor de identidad.
  6. Proporcione la reclamación de emisor y la URI para recuperar JWKS. Esta información se deriva del proveedor de identidad.
  7. Seleccione una política de retención de datos de sesión.
  8. Haga clic en Desplegar.

Anulación del despliegue de un agente

Puede anular el despliegue de los agentes para los que tiene permisos MANAGE, lo que hace que no estén disponibles para su uso.

  1. En la página de inicio, desplácese a la carpeta que contiene el agente que desea anular el despliegue.
  2. Junto al agente, haga clic en Icono de tres puntos de acciones Acciones y en Anular despliegue.

    Imagen recortada de la parte superior del agente con el botón Anular despliegue resaltado

  3. Hga clic en Anular Despliegue.

Despliegue de agente A2A

El protocolo Agent2Agent (A2A) es un estándar abierto para la comunicación entre agentes de IA independientes, incluidos los agentes creados con diferentes marcos, alojados por diferentes proveedores o que se ejecutan como sistemas remotos opacos.

Su objetivo es dar a esos agentes un modelo de interacción compartida para que puedan descubrir las capacidades de los demás, negociar formatos de entrada/salida soportados, delegar o colaborar en tareas e intercambiar información de forma segura sin exponer la memoria interna, las herramientas o los detalles de implementación. Para obtener más información, consulte Agent2Agent (A2A) Protocol.

A2A está diseñado para resolver la interoperabilidad de los agentes: en lugar de que cada integración de agentes sea personalizada, un cliente u otro agente pueden interactuar con cualquier agente remoto compatible con A2A mediante un conjunto común de conceptos y operaciones. La especificación se centra en mensajes, tareas, piezas, artefactos, actualizaciones de transmisión y notificaciones push; admite respuestas síncronas, trabajo asíncrono de larga ejecución, transmisión y patrones de seguridad y autenticación de estilo empresarial.

En Oracle AI Data Platform, todos los agentes desplegados reciben una ruta de acceso de llamada /A2A que pueden llamar las aplicaciones cliente A2A.

¿Qué es una tarjeta de agente?

Una tarjeta de agente es un documento de metadatos JSON publicado por un servidor A2A. En AIDP, el servidor A2A es el recurso informático AI que aloja el despliegue de su agente.

La tarjeta describe la identidad del agente, el punto final de servicio, los protocolos/transportes soportados, las capacidades, las aptitudes, los modos de entrada/salida soportados y los requisitos de autenticación; los clientes la utilizan para detectar si el agente es adecuado y cómo llamarlo. Una tarjeta de agente debidamente documentada es un requisito del protocolo A2A.

Las tarjetas de agente en AI Data Platform Workbench están en estado Borrador, lo que significa que el agente no se ha desplegado o Publicado, lo que significa que la tarjeta se ha desplegado junto con el agente.

Acciones de tarjeta de agente

Durante el desarrollo de un agente, la tarjeta está disponible en el menú Actions del agente.

Se puede acceder a dos tarjetas de agente:
  • El borrador de la tarjeta refleja el estado actual del agente en desarrollo.
  • La tarjeta publicada corresponde a una instantánea de la tarjeta tomada cuando se desplegó el agente. La tarjeta publicada refleja el estado del agente desplegado.

Campos de tarjeta de agente

AI Data Platform Workbench soporta un subjuego de los campos de tarjeta de agente de protocolo A2A actuales, disponibles aquí: A2A Protocol - Agent Card.

Campo Obligatorio Descripción
name Nombre legible por el usuario para el agente. Ejemplo: "Recipe Agent"
description Descripción del agente en lenguaje natural, que ayuda a los usuarios y otros agentes a entender su propósito. Ejemplo: "Agente que ayuda a los usuarios con recetas y cocina".
Agent Version Versión del agente. Ejemplo: "1.0.0"
Documentation URL N.º URL que proporciona documentación adicional sobre el agente.
Provider - Organization N.º Proveedor de servicios del agente.
Provider - URL N.º URL del proveedor de servicios.
Capabilities Juego de capacidades A2A soportado por el agente.

Solo se puede configurar streaming (Verdadero/Falso)

Skills Las habilidades representan las habilidades de un agente. Es en gran medida un concepto descriptivo, pero representa un conjunto más centrado de comportamientos en los que es probable que el agente tenga éxito. Las aptitudes representan una matriz de AgentSkill.

Cada AgentSkill está formado por varios campos que documentan las capacidades del agente. La definición de las aptitudes del agente en la tarjeta de agente es la operación que más tiempo requiere y es un proceso iterativo. Las aptitudes se pueden editar (junto con el resto de la tarjeta de agente) en la tarjeta de agente provisional antes del despliegue.

Note:

AI Data Platform Workbench proporciona inputModes, outputModes y securityRequirements y no se puede modificar.
Campo Obligatorio Descripción
Skill ID Identificador único de la aptitud del agente.
Skill Name Nombre legible por el usuario para la aptitud.
Description Descripción detallada de la aptitud.
Tags Conjunto de palabras clave que describen las capacidades de la aptitud.
Examples N.º Ejemplo de peticiones de datos o escenarios que puede manejar esta aptitud.

Ruta de punto final de despliegue de agente A2A

Una ruta /a2a se expone en la URL de un agente desplegado además de /chat.

Por ejemplo, un agente expondrá estas rutas a clientes externos:

  • https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/chat
  • https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a

Ambas rutas (/chat, /a2a) pueden ser consumidas por clientes independientes.

Variables de sesión en A2A

Los valores de las variables de sesión se pueden transferir a un agente A2A en el campo metadata del mensaje. El siguiente fragmento de JSON muestra la carga útil de un mensaje de usuario emitido al agente a2a con tres variables de sesión: userName, geoLocation y os:

{
  "jsonrpc": "2.0",
  "method": "message/send",
  "params": {
    "contextId": "session_12345",
    "taskId": "task_67890",
    "message": {
      "role": "user",
      "parts": [
        {
          "text": "What is the current status of my order?",
        }
      ],
      "metadata": {
        "sessionvariables.userName": "George",
        "sessionvariables.geoLocation": “Dallas, TX”,
        "sessionvariables.os": "mobile_ios"
      }
    }
  },
  "id": "rpc-99821"
}

Ejemplo: llamada a un agente A2A con la CLI de OCI (no streaming)

oci raw-request \
  --http-method POST \
  --auth security_token \
  --request-body '{
    "id": "<your-request-id>",
    "jsonrpc": "2.0",
    "method": "message/send",
    "params": {
      "configuration": {
        "acceptedOutputModes": [
          "text/plain",
          "text"
        ]
      },
      "message": {
        "contextId": "<your-context-id>",
        "kind": "message",
        "messageId": "<your-message-id>",
        "parts": [
          {
            "kind": "text",
            "text": "What is the capital of India?"
          }
        ],
        "role": "user"
      }
    }
  }' \
  --request-headers '{
    "x-session-id": "<your-session-id>",
    "dh-user-principal": "<your-user-principal>"
  }' \
  --target-uri " <your-a2a-agent-endpoint-url>"

Ejemplo: llamada a un agente A2A con la CLI de OCI (streaming)

oci raw-request \
  --http-method POST \
  --auth security_token \
  --request-body '{
    "id": "<your-request-id>",
    "jsonrpc": "2.0",
    "method": "message/stream",
    "params": {
      "configuration": {
        "acceptedOutputModes": [
          "text/plain",
          "text"
        ]
      },
      "message": {
        "contextId": "<your-context-id>",
        "kind": "message",
        "messageId": " <your-message-id>",
        "parts": [
          {
            "kind": "text",
            "text": "What is the capital of India?"
          }
        ],
        "role": "user"
      }
    }
  }' \
  --request-headers '{
    "x-session-id": "<your-session-id>",
    "dh-user-principal": "<user-principal>"
  }' \
  --target-uri "<your-a2a-agent-endpoint-url>"

Ejemplo: SDK de cliente A2A

import asyncio
import json
import logging
import typing
from collections.abc import Iterator
import uuid
import httpx
import oci
from a2a.client import A2AClient, ClientFactory
from a2a.types import (
    AgentCard,
    Message,
    Part,
    Role,
    TextPart,
    SendMessageRequest,
    MessageSendParams,
    MessageSendConfiguration,
    Task, SendMessageSuccessResponse, SendStreamingMessageRequest,
)

class OCIAuth(httpx.Auth):
    """httpx auth implementation using OCI signer via requests auth adapter."""

    def __init__(self, signer: oci.signer.AbstractBaseSigner):
        self._requests_auth = _OCIRequestsAuth(signer)

    def auth_flow(self, request: httpx.Request) -> Iterator[httpx.Request]:
        req = RequestsRequest(
            method=request.method,
            url=str(request.url),
            headers=dict(request.headers),
            data=request.content,
        )
        prepared: RequestsPreparedRequest = req.prepare()
        prepared = self._requests_auth(prepared)
        request.headers.update(dict(prepared.headers))
        yield request



def getOCIAuth():
    conf = oci.config.from_file(profile_name="DEFAULT")
    token_file = conf['security_token_file']
    token = None
    with open(token_file, 'r') as f:
        token = f.read()
    private_key = oci.signer.load_private_key_from_file(conf['key_file'])
    signer = oci.auth.signers.SecurityTokenSigner(token, private_key)
    auth = OCIAuth(signer=signer)
    return auth


async def _call_agent_with_a2a(agent_url: str, query: str, context_id: str,auth:OCIAuth) -> str:
    """Call an agent using the A2A protocol."""
    try:
        # Initialize OCI signer
        #headers = {"dh-user-principal": "dh-user"}
        headers = {"Accept": "*/*",
                   "dh-user-principal": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}

        async with httpx.AsyncClient(timeout=60.0, auth=auth,headers=headers) as hc:
            agent_card = await _get_agent_card(agent_url,auth)
            print(f"Agent card is {agent_card}")

            client =  A2AClient(httpx_client=hc, agent_card=agent_card)
            # Create message
            message = Message(
                message_id=str(uuid.uuid4()),
                context_id=context_id,
                role=Role.user,
                parts=[Part(root=TextPart(text=query))],
                metadata={"sessionvariables.cred.mcp.weatherReportMCP.bearer": "valid-123"}
            )
            request = SendMessageRequest(
                id=str(uuid.uuid4()),  # Add the required id field
                params=MessageSendParams(
                    message=message,
                    configuration=MessageSendConfiguration(acceptedOutputModes=["text/plain", "text"]),
                ),
            )
            #json_string = json.dumps(message, indent=4)
            print(f"Send request : {request}")

            response = await client.send_message(request)

            logging.info("Received response from A2A server: %s", response.root.result)
            # Extract response
            result = response.root.result
            # Handle different response types


            if isinstance(result, Task):
                # Task response
                if result.artifacts:
                    # Extract text from artifacts
                    texts = []
                    for artifact in result.artifacts:
                        for part in artifact.parts:
                            if hasattr(part, "root") and hasattr(part.root, "text"):
                                texts.append(part.root.text)
                    return "\n".join(texts) if texts else "Task completed with no text response"
                elif result.status and result.status.message:
                    logging.info(f"Received Task status {result.status.state} from A2A server and status message is {result.status.message}", result.status.message)
                    if  result.status.state== "failed":
                        print("Failure observed in Task invocation")
                        for m_part in result.status.message.parts:
                           print(f"Error message  { m_part.root.text}")

                    return get_message_text(result.status.message)
                else:
                    return f"Task {result.id} status: {result.status.state if result.status else 'unknown'}"

            elif isinstance(result, Message):
                return get_message_text(result)
            else:
                logging.warning(f"Unexpected response type: {type(result)}")
                return "Received response but unable to extract text"
    except Exception as ex:
        logging.error(f"Error calling agent at {agent_url}: {ex}", exc_info=True)
        return f"Error communicating with agent: {str(ex)}"


async def _call_agent_with_a2a_with_stream(agent_url: str, query: str, context_id: str, auth: OCIAuth) -> str:
    """Call an agent using the A2A protocol with streaming (SSE) and return the final artifact text."""
    try:
        async with httpx.AsyncClient(timeout=60.0, auth=auth) as hc:
            agent_card = await _get_agent_card(agent_url)
            if not agent_card:
                return "No Agent Card Found"
            print(f"Agent card is {agent_card}")

            client = A2AClient(httpx_client=hc, agent_card=agent_card)
            message = Message(
                message_id=str(uuid.uuid4()),
                context_id=context_id,
                role=Role.user,
                parts=[Part(root=TextPart(text=query))],
            )
            request = SendStreamingMessageRequest(
                id=str(uuid.uuid4()),
                params=MessageSendParams(
                    message=message,
                    configuration=MessageSendConfiguration(acceptedOutputModes=["text/plain", "text"]),
                ),
            )
            print("Invoking Remote Agent request (beautified JSON):")
            print(json.dumps(request.model_dump(), indent=2, ensure_ascii=False))
            # Expected event types:
            # - TaskStatusUpdateEvent (working/in-progress)
            # - TaskArtifactUpdateEvent (contains Artifact.parts[].root.text) -> final output
            final_artifact_text_parts: list[str] = []

            async for event in client.send_message_streaming(request):
                # Print each SSE event as-is (SDK object)
                print(f"[A2A stream event] {event}")

                try:
                    result = getattr(event.root, "result", None)
                    if not result:
                        continue

                    # TaskArtifactUpdateEvent and TaskStatusUpdateEvent are SDK types; to avoid tight coupling,
                    # extract by attribute presence.
                    artifact = getattr(result, "artifact", None)
                    if artifact and getattr(artifact, "parts", None):
                        for part in artifact.parts:
                            root = getattr(part, "root", None)
                            txt = getattr(root, "text", None)
                            if txt:
                                final_artifact_text_parts.append(txt)
                except Exception:
                    # Keep streaming even if an event can't be parsed
                    continue

            return "\n".join([t for t in final_artifact_text_parts if t]).strip() or "Stream completed (no artifact text)."
    except Exception as ex:
        logging.error(f"Error calling agent at {agent_url}: {ex}", exc_info=True)
        return f"Error communicating with agent: {str(ex)}"

Editar tarjeta de agente provisional

Puede editar la tarjeta de agente para un agente que aún no se ha desplegado.

  1. Vaya a su agente.
  2. Haga clic en Acciones y, a continuación, en Ver tarjeta de agente y Borrador de tarjeta de agente.

    Se muestra el creador visual de flujo de agente. Se seleccionan el menú Acciones y la subopción Ver tarjeta de agente. La tarjeta de agente provisional está resaltada.

  3. Haga clic en Editar.

    Aparece el cuadro de diálogo Borrador de tarjeta de agente. El botón Editar está resaltado.

  4. Puede cambiar la vista haciendo clic en Formulario o JSON en la parte superior derecha. La vista JSON es más completa, pero de solo lectura. Solo puede editar campos en la vista Formulario.

    Aparece el cuadro de diálogo Editar tarjeta de agente. Los iconos de vista de formulario y JSON están resaltados. Se ha seleccionado la vista JSON.

  5. Modifique los campos según sea necesario.
  6. Haga clic en Agregar una aptitud para agregar las aptitudes que desea exponer a los clientes A2A.

    Aparece el cuadro de diálogo Editar tarjeta de agente. El botón Agregar una aptitud está resaltado.

  7. Haga clic en Guardar.

Editar una tarjeta de agente publicada

Puede modificar una tarjeta de agente publicada sin tener que anular el despliegue o volver a desplegar un agente.

La tarjeta publicada corresponde a una instantánea de la tarjeta de borrador en el momento del despliegue.

Note:

Los cambios que realice en una tarjeta publicada se reflejan inmediatamente en el archivo agent-card.json accesible para los clientes A2A.
  1. Vaya a su agente.
  2. Haga clic en Acciones y, a continuación, en Ver tarjeta de agente y Tarjeta de agente publicada.

    Se muestra el lienzo del creador visual. Se seleccionan el menú Acciones y la subopción Ver tarjeta de agente. La tarjeta de agente publicada está resaltada.

  3. Puede cambiar la vista haciendo clic en Formulario o JSON en la parte superior derecha. La vista JSON es más completa, pero de solo lectura. Solo puede editar campos en la vista Formulario.
  4. Haga clic en Editar.

    Se muestra el cuadro de diálogo Tarjeta de agente publicada. El botón Editar está resaltado.

  5. Modifique los campos según sea necesario.
  6. Haga clic en Agregar una aptitud para agregar las aptitudes que desea exponer a los clientes A2A.

    Cuadro de diálogo Editar tarjeta de agente. Advertencia que indica "Esta tarjeta está conectada a un agente activo; las actualizaciones afectarán a la tarjeta de agente desplegada." y los botones Publicar cambios están resaltados.

  7. Haga clic en Publicar cambios.
Las tarjetas de agente publicadas no están disponibles públicamente. Un usuario debe estar autenticado y tener el permiso adecuado (READ) para inspeccionar el contenido de agent-card.json. Otros agentes pueden detectar las capacidades y los metadatos de sus agentes mediante una solicitud HTTP GET en la ruta de acceso estándar:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a/agent-card.json