23 Déploiement de l'agent

Le déploiement d'un agent transforme l'agent en application hébergée.

Vous pouvez déployer un agent dans le même calcul d'IA attaché à son terrain de jeu ou à un autre calcul d'IA. Lorsque vous déployez les dernières modifications apportées à votre agent sur le calcul AI attaché, l'agent déployé représente un cliché de l'agent au moment du déploiement. Pour mettre à jour l'agent déployé vers la dernière version, vous devez redéployer l'agent.

Chaque agent dispose d'une URL de déploiement stable qui dépend de la clé d'agent unique. Le redéploiement multiple de l'agent écrase l'agent derrière l'URL de déploiement.

Le déploiement de vos agents présente les limites suivantes :
  • Un agent ne peut être déployé que sur un seul cluster de calcul AI à un moment donné.
  • Le déploiement du même agent plusieurs fois sur le même cluster de calcul AI écrase l'itération précédemment déployée de l'agent.

Une fois que vous avez déployé un agent, vous pouvez extraire l'URI de discussion pour émettre des requêtes par programmation et extraire les réponses de l'agent à partir de l'onglet Détails de l'agent.


Page Agent ouverte avec l'onglet Détails ouvert et mis en surbrillance. Déployé vers AI Compute et l'URL d'adresse sont mis en évidence

L'URL endpoint est stable et est liée à chaque agent. L'URL inclut l'ID d'agent unique affecté à chaque agent. En d'autres termes, si vous annulez le déploiement d'un agent et que vous le déployez à nouveau, l'URL reste identique. L'avantage est que vous n'avez pas à modifier le code client appelant l'adresse, l'inconvénient est que vous pouvez écraser un agent en production.

L'URL présente la structure suivante :
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/{protocol}
où :
  • oci-region correspond à la région d'instance AI Data Platform ;
  • agentId est l'ID unique associé à l'agent.
  • protocol est le protocole de communication : chat qui suit le format de l'API des réponses OpenAI et a2a qui suit le protocole de communication agent-agent. Les deux protocoles sont disponibles pour chaque adresse d'agent. Pour plus d'informations, reportez-vous à Déploiement d'agent A2A.

Remarques :

Deux calculs AI sont répertoriés dans l'onglet Détails. L'option Attaché à AI Compute permet de tester l'agent dans le playground de test. L'option Déployé sur AI Compute héberge l'agent déployé.

Le champ URL endpoint est renseigné après le déploiement de l'agent. Vous pouvez appeler cette URL d'adresse à partir de l'application de production.

Déployer un agent

Vous déployez les agents que vous avez créés et configurés afin que les autres utilisateurs puissent les voir et les utiliser dans votre instance AI Data Platform.

  1. Sur la page d'accueil, accédez au dossier contenant l'agent à déployer.
  2. En regard de l'agent, cliquez sur Icône Actions à trois points Actions, puis sur Déployer. Vous pouvez également cliquer sur le nom de l'agent, puis sur Déployer en haut à droite.

    Agent ouvert avec le bouton Déployer en haut à droite de l'écran en surbrillance

  3. Sélectionnez le calcul AI à attacher à l'agent déployé.
  4. Sélectionnez Pupitre AIDP pour le type d'autorisation.
  5. Sélectionnez une stratégie de conservation des données de session.
    • Pour la période de conservation, indiquez le nombre de jours pendant lesquels les données de session sont conservées.
    • Pour Limite de taille de session, indiquez la taille maximale qu'une session peut atteindre.
    • Pour Limite de nombre de threads, indiquez le nombre maximal de threads de session conservés.
  6. Cliquez sur Déployer.

Déployer un agent avec OAuth2

Vous pouvez déployer des agents que vous avez créés et configurés pour utiliser l'authentification OAuth2 afin de vous connecter à des fournisseurs d'identités externes.

  1. Sur la page d'accueil, accédez au dossier contenant l'agent à déployer.
  2. En regard de l'agent, cliquez sur Icône Actions à trois points Actions, puis sur Déployer. Vous pouvez également cliquer sur le nom de l'agent, puis sur Déployer en haut à droite.

    Agent ouvert avec le bouton Déployer en haut à droite de l'écran en surbrillance

  3. Sélectionnez le calcul AI à attacher à l'agent déployé.
  4. Sélectionnez OAuth2 pour le type d'autorisation.
  5. Fournissez la demande d'audience. AI Data Platform Workbench renseigne automatiquement ce champ, mais vous pouvez le remplacer par une demande d'audience de votre fournisseur d'identités.
  6. Fournissez la demande émetteur et l'URI d'extraction de JWKS. Ces informations proviennent de votre fournisseur d'identités.
  7. Sélectionnez une stratégie de conservation des données de session.
  8. Cliquez sur Déployer.

Annuler le déploiement d'un agent

Vous pouvez choisir d'annuler le déploiement des agents pour lesquels vous disposez des droits d'accès MANAGE, ce qui les rend indisponibles.

  1. Dans la page d'accueil, accédez au dossier contenant l'agent dont vous souhaitez annuler le déploiement.
  2. En regard de l'agent, cliquez sur Icône Actions à trois points Actions, puis sur Annuler le déploiement.

    Image recadrée du haut de l'agent avec le bouton Annuler le déploiement en surbrillance

  3. Cliquez sur Annuler le déploiement.

Déploiement d'agent A2A

Le protocole Agent2Agent (A2A) est une norme ouverte pour la communication entre les agents d'IA indépendants, y compris les agents construits avec différentes structures, hébergés par différents fournisseurs ou exécutés en tant que systèmes distants opaques.

Son but est de donner à ces agents un modèle d'interaction partagé afin qu'ils puissent découvrir les capacités de l'autre, négocier les formats d'entrée/sortie pris en charge, déléguer ou collaborer sur des tâches et échanger des informations en toute sécurité sans exposer la mémoire interne, les outils ou les détails d'implémentation. Pour plus d'informations, reportez-vous à la section Agent2Agent (A2A) Protocol.

A2A est destiné à résoudre l'interopérabilité des agents : au lieu que chaque intégration d'agent soit personnalisée, un client ou un autre agent peut interagir avec n'importe quel agent distant compatible A2A en utilisant un ensemble commun de concepts et d'opérations. La spécification se concentre sur les messages, les tâches, les pièces, les artefacts, les mises à jour en continu et les notifications push. Elle prend en charge les réponses synchrones, le travail asynchrone à longue durée d'exécution, la diffusion en continu et les modèles d'authentification/sécurité de type entreprise.

Dans Oracle AI Data Platform, tous les agents déployés disposent d'un chemin d'appel /A2A qui peut être appelé par les applications client A2A.

Qu'est-ce qu'une carte agent ?

Une carte d'agent est un document de métadonnées JSON publié par un serveur A2A. Dans AIDP, le serveur A2A est le calcul AI qui héberge votre déploiement d'agent.

La carte décrit l'identité de l'agent, l'adresse de service, les protocoles/transports pris en charge, les capacités, les compétences, les modes d'entrée/sortie pris en charge et les exigences d'authentification. Les clients l'utilisent pour déterminer si l'agent convient et comment l'appeler. Une carte d'agent correctement documentée est une exigence du protocole A2A.

Les cartes d'agent dans AI Data Platform Workbench sont à l'état Brouillon, ce qui signifie que l'agent n'a pas été déployé ou Publié, ce qui signifie que la carte a été déployée avec l'agent.

Actions de carte d'agent

Pendant le développement d'un agent, la carte est disponible dans le menu Actions de l'agent.

Deux cartes d'agent sont accessibles :
  • Le projet de carte reflète l'état actuel de l'agent en développement.
  • La carte publiée correspond à un instantané de la carte prise lors du déploiement de l'agent. La carte publiée reflète l'état de l'agent déployé.

Champs de carte d'agent

AI Data Platform Workbench prend en charge un sous-ensemble des champs de carte d'agent de protocole A2A actuels, disponibles ici : Protocole A2A - Carte d'agent.

Champ Obligatoire Description
name Oui Nom lisible par l'utilisateur pour l'agent. Exemple : "Agent recette"
description Oui Description lisible par l'homme de l'agent, qui aide les utilisateurs et autres agents à comprendre son but. Exemple : "Agent qui aide les utilisateurs avec des recettes et de la cuisine."
Agent Version Oui Version de l'agent. Exemple : "1.0.0"
Documentation URL No URL fournissant une documentation supplémentaire sur l'agent.
Provider - Organization No Fournisseur de services de l'agent.
Provider - URL No URL du fournisseur de services.
Capabilities Oui Jeu de fonctionnalités A2A pris en charge par l'agent.

Seul streaming peut être configuré (Vrai/Faux)

Skills Oui Les compétences représentent les capacités d'un agent. Il s'agit en grande partie d'un concept descriptif, mais il représente un ensemble de comportements plus ciblés que l'agent est susceptible de réussir. Les compétences représentent un éventail de compétences d'agent.

Chaque AgentSkill est constitué de plusieurs champs documentant les capacités de l'agent. La définition des compétences de l'agent dans la carte d'agent est l'opération la plus longue et un processus itératif. Les compétences peuvent être modifiées (ainsi que le reste de la carte d'agent) dans la carte d'agent provisoire avant le déploiement.

Remarques :

inputModes, outputModes et securityRequirements sont fournis par AI Data Platform Workbench et ne peuvent pas être modifiés.
Champ Obligatoire Description
Skill ID Oui Identificateur unique de la brique de l'agent.
Skill Name Oui Nom lisible par l'utilisateur pour la brique.
Description Oui Description détaillée de la brique.
Tags Oui Ensemble de mots-clés décrivant les capacités de la brique.
Examples No Exemples d'invites ou de scénarios que cette brique peut gérer.

Chemin A2A de l'adresse de déploiement d'agent

Un chemin /a2a est exposé dans l'URL d'un agent déployé en plus de /chat.

Par exemple, un agent exposera ces chemins aux clients externes :

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

Les deux chemins (/chat, /a2a) peuvent être utilisés par des clients distincts.

Variables de session dans A2A

Les valeurs des variables de session peuvent être transmises à un agent A2A dans le champ de message metadata. Le fragment de code JSON ci-dessous affiche la charge utile d'un message utilisateur envoyé à l'agent a2a avec trois variables de session : userName, geoLocation et 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"
}

Exemple : appel d'un agent A2A avec l'interface de ligne de commande OCI (non-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>"

Exemple : appel d'un agent A2A avec l'interface de ligne de commande 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>"

Exemple : SDK client 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)}"

Modifier une carte d'agent provisoire

Vous pouvez modifier la carte d'agent d'un agent qui n'est pas encore déployé.

  1. Accédez à votre agent.
  2. Cliquez sur Actions, puis sur Visualiser la carte d'agent et Provisionner la carte d'agent.

    Le générateur visuel de flux d'agents s'affiche. Le menu Actions et la sous-option Afficher la carte de l'agent sont sélectionnés. La carte d'agent provisoire est mise en surbrillance.

  3. Cliquez sur Modifier.

    La boîte de dialogue Brouillon de carte d'agent s'affiche. Le bouton Modifier est mis en évidence.

  4. Vous pouvez changer de vue en cliquant sur Formulaire ou JSON en haut à droite. La vue JSON est plus complète, mais en lecture seule. Vous pouvez uniquement modifier les champs de la vue Formulaire.

    La boîte de dialogue Modifier la carte d'agent s'affiche. Les icônes de vue JSON et de formulaire sont mises en surbrillance. La vue JSON est sélectionnée.

  5. Modifiez les champs selon vos besoins.
  6. Cliquez sur Ajouter une brique pour ajouter les briques à exposer aux clients A2A.

    La boîte de dialogue Modifier la carte d'agent s'affiche. Le bouton Ajouter une brique est mis en surbrillance.

  7. Cliquez sur Enregistrer.

Modifier une carte d'agent publiée

Vous pouvez modifier une carte d'agent publiée sans avoir à annuler le déploiement ou à redéployer un agent.

La carte publiée correspond à un instantané de la carte provisoire au moment du déploiement.

Remarques :

Les modifications apportées à une carte publiée sont immédiatement répercutées dans le fichier agent-card.json accessible aux clients A2A.
  1. Accédez à votre agent.
  2. Cliquez sur Actions, puis sur Visualiser la carte d'agent et sur Carte d'agent publiée.

    Le canevas du générateur visuel est affiché. Le menu Actions et la sous-option Afficher la carte de l'agent sont sélectionnés. La carte d'agent publiée est mise en surbrillance.

  3. Vous pouvez changer de vue en cliquant sur Formulaire ou JSON en haut à droite. La vue JSON est plus complète, mais en lecture seule. Vous pouvez uniquement modifier les champs de la vue Formulaire.
  4. Cliquez sur Modifier.

    La boîte de dialogue Carte d'agent publiée s'affiche. Le bouton Modifier est mis en évidence.

  5. Modifiez les champs selon vos besoins.
  6. Cliquez sur Ajouter une brique pour ajouter les briques à exposer aux clients A2A.

    Boîte de dialogue Modifier la carte d'agent. Avertissement indiquant "Cette carte est attachée à un agent physique ; les mises à jour auront un impact sur la carte d'agent déployée." et le bouton Publier les modifications sont mis en surbrillance.

  7. Cliquez sur Publier les modifications.
Les cartes d'agent publiées ne sont pas accessibles au public. Un utilisateur doit être authentifié et disposer du droit d'accès (READ) pour inspecter le contenu de agent-card.json. D'autres agents peuvent repérer les fonctionnalités et les métadonnées de vos agents via une demande HTTP GET sur le chemin standard :
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a/agent-card.json