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

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.
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/{protocol}oci-regioncorrisponde all'area dell'istanza di AI Data Platform;agentIdè l'ID univoco associato all'agenteprotocolè il protocollo di comunicazione:chatche segue il formato OpenAI Responses API ea2ache 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.
Distribuire un agente con OAuth2
È possibile distribuire gli agenti creati e configurati per utilizzare l'autenticazione OAuth2 per connettersi ai provider di identità esterni.
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.
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.
- 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 |
Sì | Nome leggibile dall'utente per l'agente. Esempio: "Agente ricetta" |
description |
Sì | 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 |
Sì | 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 |
Sì | Capacità A2A impostata supportata dall'agente.
È possibile configurare solo |
Skills
|
Sì | 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 |
Sì | Identificativo univoco per lo skill dell'agente. |
Skill Name |
Sì | Nome leggibile dall'utente per la competenza. |
Description |
Sì | Una descrizione dettagliata dello skill. |
Tags |
Sì | 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}/chathttps://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.
Modifica una scheda agente pubblicata
È possibile modificare una scheda agente pubblicata senza annullare la distribuzione o ridistribuire un agente.
Nota
Le modifiche apportate a una scheda pubblicata si riflettono immediatamente nel file agent-card.json accessibile ai client A2A.https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a/agent-card.json







