23 Distribuzione agente

La distribuzione di un agente trasforma l'agente in un'applicazione hosted.

Puoi distribuire un agente nella stessa computazione AI collegata al suo ambiente di gioco o a un'altra computazione AI. Quando distribuisci le modifiche più recenti all'agente nella computazione AI collegata, l'agente distribuito rappresenta uno snapshot dell'agente al momento della distribuzione. Per aggiornare l'agente distribuito alla versione più recente, è necessario ridistribuire l'agente.

Ogni agente dispone di un URL di distribuzione stabile che dipende dalla chiave agente univoca. La ridistribuzione dell'agente più volte sovrascrive l'agente dietro l'URL di distribuzione.

La distribuzione degli agenti ha le seguenti limitazioni:
  • Un agente può essere distribuito solo in un cluster di computazione AI in qualsiasi momento.
  • La distribuzione dello stesso agente più volte nello stesso cluster di computazione AI sovrascrive l'iterazione distribuita in precedenza dell'agente.

Dopo aver distribuito un agente, è possibile recuperare l'URI della chat per emettere query a livello di programmazione e recuperare le risposte dall'agente dalla scheda Dettagli dell'agente.


Pagina dell'agente aperta con scheda Dettagli aperta ed evidenziata. Distribuito in computazione AI e URL endpoint sono evidenziati

L'URL dell'endpoint è stabile ed è collegato a ciascun agente. L'URL include l'ID agente univoco assegnato a ciascun agente. In altre parole, se si annulla la distribuzione di un agente e lo si distribuisce di nuovo, l'URL rimane invariato. Il vantaggio è che non è necessario modificare il codice client che richiama l'endpoint, lo svantaggio è che è possibile sovrascrivere un agente in produzione.

L'URL ha la seguente struttura:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/{protocol}
dove:
  • oci-region corrisponde all'area dell'istanza di AI Data Platform;
  • agentId è l'ID univoco associato all'agente
  • protocol è il protocollo di comunicazione: chat che segue il formato OpenAI Responses API e a2a che segue il protocollo di comunicazione agente-agente. Entrambi i protocolli sono disponibili per ogni endpoint dell'agente. Per ulteriori informazioni, vedere Distribuzione agente A2A.

Nota

Nella scheda Dettagli sono elencati due calcoli AI. Il comando Collegato a AI Compute viene utilizzato per eseguire il test dell'agente nell'area di esecuzione. L'agente distribuito Distribuito in AI Compute ospita l'agente distribuito.

Il campo URL endpoint viene popolato dopo la distribuzione dell'agente. È possibile chiamare questo URL endpoint dall'applicazione di produzione.

Distribuisci un agente

È possibile distribuire gli agenti creati e configurati in modo che altri utenti siano in grado di visualizzarli e utilizzarli nell'istanza di AI Data Platform.

  1. Nella home page, andare alla cartella contenente l'agente che si desidera distribuire.
  2. Accanto all'agente, fare clic su Icona a tre punti Azioni Azioni e fare clic su Distribuisci. È inoltre possibile fare clic sul nome dell'agente e fare clic su Distribuisci in alto a destra.

    Agente aperto con il pulsante Distribuisci in alto a destra della schermata evidenziato

  3. Selezionare la computazione AI da collegare all'agente distribuito.
  4. Selezionare Workbench AIDP per il tipo di autorizzazione.
  5. Selezionare un criterio di conservazione dei dati della sessione.
    • Per Periodo di conservazione, specificare per quanti giorni verranno conservati i dati della sessione.
    • Per Limite dimensione sessione, fornire la dimensione massima che una sessione può raggiungere.
    • Per Limite di conteggio thread, fornire il numero massimo di thread di sessione conservati.
  6. Fare clic su Distribuisci.

Distribuire un agente con OAuth2

È possibile distribuire gli agenti creati e configurati per utilizzare l'autenticazione OAuth2 per connettersi ai provider di identità esterni.

  1. Nella home page, andare alla cartella contenente l'agente che si desidera distribuire.
  2. Accanto all'agente, fare clic su Icona a tre punti Azioni Azioni e fare clic su Distribuisci. È inoltre possibile fare clic sul nome dell'agente e fare clic su Distribuisci in alto a destra.

    Agente aperto con il pulsante Distribuisci in alto a destra della schermata evidenziato

  3. Selezionare la computazione AI da collegare all'agente distribuito.
  4. Selezionare OAuth2 per il tipo di autorizzazione.
  5. Fornire la richiesta di audience. Il workbench di AI Data Platform popola automaticamente questo campo, ma è possibile sostituirlo con una richiesta di audience del provider di identità.
  6. Fornire la richiesta dell'emittente e l'URI per recuperare JWKS. Queste informazioni derivano dal provider di identità in uso.
  7. Selezionare un criterio di conservazione dei dati della sessione.
  8. Fare clic su Distribuisci.

Annulla distribuzione di un agente

È possibile scegliere di annullare la distribuzione degli agenti per i quali si dispone delle autorizzazioni di gestione, rendendoli non disponibili per l'uso.

  1. Nella home page andare alla cartella contenente l'agente che si desidera annullare la distribuzione.
  2. Accanto all'agente, fare clic su Icona a tre punti Azioni Azioni e fare clic su Annulla distribuzione.

    Immagine ritagliata della parte superiore dell'agente con il pulsante Annulla distribuzione evidenziato

  3. Fare clic su Annulla distribuzione.

Distribuzione agente A2A

Il protocollo A2A (Agent2Agent) è uno standard aperto per la comunicazione tra agenti AI indipendenti, inclusi agenti creati con framework diversi, ospitati da fornitori diversi o eseguiti come sistemi remoti opachi.

Il suo scopo è quello di fornire a questi agenti un modello di interazione condivisa in modo che possano scoprire le rispettive capacità, negoziare formati di input/output supportati, delegare o collaborare alle attività e scambiare informazioni in modo sicuro senza esporre memoria interna, strumenti o dettagli di implementazione. Per ulteriori informazioni, vedere il protocollo Agent2Agent (A2A).

A2A ha lo scopo di risolvere l'interoperabilità dell'agente: invece di personalizzare ogni integrazione dell'agente, un client o un altro agente può interagire con qualsiasi agente remoto conforme ad A2A utilizzando un set comune di concetti e operazioni. La specifica è incentrata su messaggi, attività, parti, artefatti, aggiornamenti in streaming e notifiche push; supporta risposte sincrone, lavoro asincrono a lungo termine, streaming e pattern di autenticazione/sicurezza in stile enterprise.

In Oracle AI Data Platform, a tutti gli agenti distribuiti viene fornito un percorso di richiamo /A2A che può essere richiamato dalle applicazioni client A2A.

Cos'è una scheda agente?

Una scheda agente è un documento di metadati JSON pubblicato da un server A2A. In AIDP, il server A2A è la computazione AI che ospita la distribuzione dell'agente.

La scheda descrive l'identità dell'agente, l'endpoint del servizio, i protocolli/trasport supportati, le capacità, le competenze, le modalità di input/output supportate e i requisiti di autenticazione; i client la utilizzano per scoprire se l'agente è adatto e come chiamarlo. Una scheda agente correttamente documentata è un requisito del protocollo A2A.

Le schede agente in AI Data Platform Workbench sono in stato Bozza, ovvero l'agente non è stato distribuito o Pubblicato, il che significa che la scheda è stata distribuita insieme all'agente.

Azioni carta agente

Durante lo sviluppo di un agente, la scheda è disponibile nel menu Azioni dell'agente.

Sono accessibili due schede agente:
  • La bozza di carta riflette lo stato corrente dell'agente in fase di sviluppo.
  • La scheda pubblicata corrisponde a un'istantanea della scheda acquisita al momento della distribuzione dell'agente. La scheda pubblicata riflette lo stato dell'agente distribuito.

Campi scheda agente

AI Data Platform Workbench supporta un subset dei campi della scheda agente del protocollo A2A correnti, disponibili qui: Protocollo A2A - scheda agente.

Campo Obbligatorio. Descrizione
name Nome leggibile dall'utente per l'agente. Esempio: "Agente ricetta"
description Una descrizione leggibile dall'uomo dell'agente, che assiste gli utenti e altri agenti nella comprensione del suo scopo. Esempio: "Agente che aiuta gli utenti con ricette e cucina".
Agent Version La versione dell'agente. Esempio: "1.0.0"
Documentation URL N. URL che fornisce documentazione aggiuntiva sull'agente.
Provider - Organization N. Il provider di servizi dell'agente.
Provider - URL N. L'URL del provider di servizi.
Capabilities Capacità A2A impostata supportata dall'agente.

È possibile configurare solo streaming (True/False)

Skills Le competenze rappresentano le capacità di un agente. È in gran parte un concetto descrittivo, ma rappresenta un insieme più focalizzato di comportamenti che l'agente è probabile che abbia successo. Le competenze rappresentano un array di AgentSkill.

Ogni AgentSkill è composto da diversi campi che documentano le capacità dell'agente. La definizione delle competenze dell'agente nella scheda agente è l'operazione che richiede più tempo ed è un processo iterativo. Le competenze possono essere modificate (insieme al resto della scheda agente) nella bozza della scheda agente prima della distribuzione.

Nota

inputModes, outputModes e securityRequirements sono forniti da AI Data Platform Workbench e non possono essere modificati.
Campo Obbligatorio. Descrizione
Skill ID Identificativo univoco per lo skill dell'agente.
Skill Name Nome leggibile dall'utente per la competenza.
Description Una descrizione dettagliata dello skill.
Tags Insieme di parole chiave che descrivono le capacità dell'abilità.
Examples N. Prompt di esempio o scenari che questa skill può gestire.

Percorso A2A endpoint distribuzione agente

Un percorso /a2a è esposto nell'URL di un agente distribuito oltre a /chat.

Ad esempio, un agente esporrà questi percorsi ai client esterni:

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

Entrambi i percorsi (/chat e /a2a) possono essere utilizzati da client separati.

Variabili di sessione in A2A

I valori delle variabili di sessione possono essere passati a un agente A2A nel campo del messaggio metadata. Lo snippet JSON riportato di seguito mostra il payload di un messaggio utente inviato all'agente a2a con tre variabili di sessione: userName, geoLocation e 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"
}

Esempio: richiamo di un agente A2A con OCI CLI (non in 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>"

Esempio: richiamo di un agente A2A con OCI CLI (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>"

Esempio: 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)}"

Modifica una bozza di scheda agente

È possibile modificare la scheda agente per un agente non ancora distribuito.

  1. Passare all'agente.
  2. Fare clic su Azioni, quindi su Visualizza scheda agente e Bozza scheda agente.

    Viene visualizzato il visual builder del flusso agente. Vengono selezionati il menu Azioni e l'opzione secondaria Visualizza scheda agente. La bozza della scheda agente è evidenziata.

  3. Fare clic Modifica.

    Viene visualizzata la finestra di dialogo Bozza carta agente. Il pulsante Modifica è evidenziato.

  4. È possibile cambiare vista facendo clic su Modulo o JSON in alto a destra. La vista JSON è più completa, ma di sola lettura. È possibile modificare solo i campi nella vista Form.

    Viene visualizzata la finestra di dialogo Modifica scheda agente. Le icone della vista JSON e form sono evidenziate. Vista JSON selezionata.

  5. Modificare i campi in base alle esigenze.
  6. Fare clic su Aggiungi una competenza per aggiungere le competenze che si desidera esporre ai client A2A.

    Viene visualizzata la finestra di dialogo Modifica scheda agente. Il pulsante Aggiungi uno skill viene evidenziato.

  7. Fare clic su Salva.

Modifica una scheda agente pubblicata

È possibile modificare una scheda agente pubblicata senza annullare la distribuzione o ridistribuire un agente.

La scheda pubblicata corrisponde a un'istantanea della bozza di scheda al momento della distribuzione.

Nota

Le modifiche apportate a una scheda pubblicata si riflettono immediatamente nel file agent-card.json accessibile ai client A2A.
  1. Passare all'agente.
  2. Fare clic su Azioni, quindi su Visualizza scheda agente e Scheda agente pubblicata.

    Viene visualizzato lo sfondo di Visual Builder. Vengono selezionati il menu Azioni e l'opzione secondaria Visualizza scheda agente. La scheda agente pubblicata è evidenziata.

  3. È possibile cambiare vista facendo clic su Modulo o JSON in alto a destra. La vista JSON è più completa, ma di sola lettura. È possibile modificare solo i campi nella vista Form.
  4. Fare clic Modifica.

    Viene visualizzata la finestra di dialogo della scheda agente pubblicata. Il pulsante Modifica è evidenziato.

  5. Modificare i campi in base alle esigenze.
  6. Fare clic su Aggiungi una competenza per aggiungere le competenze che si desidera esporre ai client A2A.

    Finestra di dialogo Modifica scheda agente. Avvertenza: questa scheda è collegata a un agente reale. Gli aggiornamenti influiranno sulla scheda agente distribuita. Vengono evidenziati i pulsanti Pubblica modifiche.

  7. Fare clic su Pubblica modifiche.
Le schede agente pubblicate non sono disponibili pubblicamente. Un utente deve essere autenticato e avere la giusta autorizzazione (READ) per ispezionare il contenuto di agent-card.json. Altri agenti possono trovare le funzionalità e i metadati degli agenti tramite una richiesta GET HTTP nel percorso standard:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a/agent-card.json