23 Implantação do Agente

A implantação de um agente transforma seu agente em um aplicativo hospedado.

Você pode implantar um agente na mesma computação de IA anexada ao playground ou a outra computação de IA. Quando você implanta as alterações mais recentes no seu agente na computação de IA anexada, o agente implantado representa um snapshot do agente no momento da implantação. Para atualizar o agente implantado para a versão mais recente, você precisa reimplantar o agente.

Cada agente tem um URL de implantação estável que depende da chave de agente exclusiva. A reimplantação do agente várias vezes substitui o agente por trás do URL de implantação.

A implantação de seus agentes tem as seguintes limitações:
  • Um agente só pode ser implantado em um cluster de computação de IA a qualquer momento.
  • A implantação do mesmo agente várias vezes no mesmo cluster de computação AI substitui a iteração implantada anteriormente do agente.

Depois de implantar um agente, você poderá recuperar o URI do chat para emitir consultas de forma programática e recuperar respostas do agente na guia Detalhes do seu agente.


A página Agente é aberta com a guia Detalhes aberta e destacada. Implantado no AI Compute e no URL do Ponto Final estão destacados

O URL do ponto final é estável e está vinculado a cada agente. O URL inclui o agentID exclusivo designado a cada agente. Em outras palavras, se você cancelar a implantação de um agente e implantá-lo novamente, o URL permanecerá o mesmo. O benefício é que você não precisa modificar o código do cliente que está chamando o ponto final. A desvantagem é que você pode substituir um agente na produção.

O URL tem a seguinte estrutura:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/{protocol}
em que:
  • oci-region corresponde à região da instância da AI Data Platform;
  • agentId é o id exclusivo associado ao agente
  • protocol é o protocolo de comunicação: chat que segue o formato da API de Respostas do OpenAI e a2a que segue o protocolo de comunicação entre agentes. Ambos os protocolos estão disponíveis para cada ponto final do agente. Para obter mais informações, consulte Implantação do Agente A2A.

Observação:

Dois cálculos de IA são listados na guia Detalhes. O Anexado ao AI Compute é usado para testar o agente no playground. O serviço Implantado no AI Compute hospeda o agente implantado.

O campo URL do ponto final é preenchido depois que você implanta seu agente. Você pode chamar esse URL de ponto final do seu aplicativo de produção.

Implantar um Agente

Você implanta agentes que criou e configurou para que outros usuários possam vê-los e usá-los em sua instância da AI Data Platform.

  1. Na Home page, navegue até a pasta que contém o agente que você deseja implantar.
  2. Ao lado do agente, clique em Ícone de três pontos de ações Ações e clique em Implantar. Você também pode clicar no nome do agente e clicar em Implantar no canto superior direito.

    Agente aberto com o botão Implantar no canto superior direito da tela destacado

  3. Selecione a computação AI a ser anexada ao agente implantado.
  4. Selecione Bancada AIDP para o tipo de autorização.
  5. Selecione uma política de retenção de dados da sessão.
    • Para Período de retenção, forneça o número de dias durante os quais os dados da sessão são retidos.
    • Para Limite de tamanho de sessão, forneça o tamanho máximo que uma sessão pode atingir.
    • Para Limite de contagem de threads, forneça o número máximo de threads de sessão retidos.
  6. Clique em Disponibilizar.

Implantar um Agente com o OAuth2

Você pode implantar agentes que criou e configurou para usar a autenticação OAuth2 para estabelecer conexão com provedores de identidades externos.

  1. Na Home page, navegue até a pasta que contém o agente que você deseja implantar.
  2. Ao lado do agente, clique em Ícone de três pontos de ações Ações e clique em Implantar. Você também pode clicar no nome do agente e clicar em Implantar no canto superior direito.

    Agente aberto com o botão Implantar no canto superior direito da tela destacado

  3. Selecione a computação AI a ser anexada ao agente implantado.
  4. Selecione OAuth2 para o tipo de autorização.
  5. Forneça a reivindicação do público. O AI Data Platform Workbench preenche automaticamente esse campo, mas você pode substituí-lo por uma reivindicação de público do seu provedor de Identidade.
  6. Forneça a reivindicação do emissor e o URI para recuperar JWKS. Essas informações são derivadas do seu provedor de Identidades.
  7. Selecione uma política de retenção de dados da sessão.
  8. Clique em Disponibilizar.

Cancelar Implantação de um Agente

Você pode optar por cancelar a implantação dos agentes para os quais tem permissões de GERENCIAMENTO, tornando-os indisponíveis para uso.

  1. Na Home page, navegue até a pasta que contém o agente que você deseja cancelar a implantação.
  2. Ao lado do agente, clique em Ícone de três pontos de ações Ações e clique em Cancelar Implantação.

    Imagem cortada da parte superior do agente com o botão Cancelar Implantação destacado

  3. Clique em Cancelar disponibilização.

Implantação do Agente A2A

O protocolo Agent2Agent (A2A) é um padrão aberto para comunicação entre agentes independentes de IA, incluindo agentes criados com diferentes estruturas, hospedados por diferentes fornecedores ou executados como sistemas remotos opacos.

Seu objetivo é dar a esses agentes um modelo de interação compartilhada para que eles possam descobrir os recursos uns dos outros, negociar formatos de entrada/saída suportados, delegar ou colaborar em tarefas e trocar informações com segurança sem expor memória interna, ferramentas ou detalhes de implementação. Para obter mais informações, consulte Protocolo A2A (Agent2Agent).

A2A destina-se a resolver a interoperabilidade do agente: em vez de cada integração de agente ser personalizada, um cliente ou outro agente pode interagir com qualquer agente remoto compatível com A2A usando um conjunto comum de conceitos e operações. As especificações se concentram em mensagens, tarefas, peças, artefatos, atualizações de streaming e notificações push; ele oferece suporte a respostas síncronas, trabalho assíncrono de longa execução, streaming e padrões de segurança/autorização de estilo empresarial.

Na Oracle AI Data Platform, todos os agentes implantados recebem um caminho de chamada /A2A que pode ser chamado por aplicativos clientes A2A.

O que é um cartão de agente?

Um Cartão de Agente é um documento de metadados JSON publicado por um servidor A2A. No AIDP, o servidor A2A é a computação AI que hospeda a implantação do seu agente.

O cartão descreve a identidade do agente, o ponto final de serviço, protocolos/transportes suportados, recursos, habilidades, modos de entrada/saída suportados e requisitos de autenticação; os clientes o usam para descobrir se o agente é adequado e como chamá-lo. Um cartão de agente devidamente documentado é um requisito do protocolo A2A.

Os cartões de agente no AI Data Platform Workbench estão no estado Preliminar, o que significa que o agente não foi implantado ou Publicado, o que significa que o cartão foi implantado ao lado do agente.

Ações do Cartão do Agente

Durante o desenvolvimento de um agente, o cartão está disponível no menu Ações do agente.

Dois cartões de agente estão acessíveis:
  • O rascunho do cartão reflete o estado atual do agente em desenvolvimento.
  • O cartão publicado corresponde a um snapshot do cartão obtido quando o agente foi implantado. O cartão publicado reflete o estado do agente implantado.

Campos do cartão do agente

O AI Data Platform Workbench suporta um subconjunto dos campos atuais de cartão do agente de protocolo A2A, disponíveis aqui: Protocolo A2A - Cartão do Agente.

Campo Obrigatório Descrição
name Sim Um nome legível para o agente. Exemplo: "Agente de Receita"
description Sim Uma descrição legível do agente, auxiliando os usuários e outros agentes na compreensão de seu propósito. Exemplo: "Agente que ajuda os usuários com receitas e culinária".
Agent Version Sim A versão do agente. Exemplo: "1.0.0" de
Documentation URL No Um URL que fornece documentação adicional sobre o agente.
Provider - Organization No O provedor de serviços do agente.
Provider - URL No O URL do provedor de serviços.
Capabilities Sim Conjunto de recursos A2A suportado pelo agente.

Somente streaming pode ser configurado (Verdadeiro/Falso)

Skills Sim Habilidades representam as habilidades de um agente. É em grande parte um conceito descritivo, mas representa um conjunto mais focado de comportamentos que o agente provavelmente terá sucesso. As habilidades representam uma matriz de AgentSkill.

Cada AgentSkill é feito de vários campos que documentam os recursos do agente. Definir as habilidades do agente no cartão do agente é a operação mais demorada e é um processo iterativo. As habilidades podem ser editadas (juntamente com o restante do cartão de agente) no cartão de agente preliminar antes da implantação.

Observação:

inputModes, outputModes e securityRequirements são fornecidos pelo AI Data Platform Workbench e não podem ser modificados.
Campo Obrigatório Descrição
Skill ID Sim Um identificador exclusivo para a habilidade do agente.
Skill Name Sim Um nome legível para a habilidade.
Description Sim Uma descrição detalhada da habilidade.
Tags Sim Um conjunto de palavras-chave que descreve os recursos da habilidade.
Examples No Exemplos de prompts ou cenários que essa habilidade pode tratar.

Caminho A2A do Ponto Final de Implantação do Agente

Um caminho /a2a é exposto no URL de um agente implantado, além de /chat.

Por exemplo, um agente exporá esses caminhos para clientes externos:

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

Ambos os caminhos (/chat, /a2a) podem ser consumidos por clientes separados.

Variáveis de Sessão no A2A

Os valores de variáveis de sessão podem ser passados para um agente A2A no campo metadata da mensagem. O trecho de código JSON abaixo mostra o payload de uma mensagem do usuário emitida para o agente a2a com três variáveis de sessão: 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"
}

Exemplo: Chamando um Agente A2A com a CLI do OCI (Não 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>"

Exemplo: Chamando um Agente A2A com a CLI do 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>"

Exemplo: A2A Client SDK

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 um Rascunho de Cartão de Agente

Você pode editar o cartão de agente para um agente que ainda não foi implantado.

  1. Navegue até o seu agente.
  2. Clique em Ações e, em seguida, clique em Exibir cartão do agente e Cartão do agente preliminar.

    O criador visual do fluxo do agente é exibido. O menu Ações e a subopção Exibir cartão do agente são selecionados. O rascunho do cartão do agente é destacado.

  3. Clique emEditar.

    A caixa de diálogo Rascunho do cartão do agente é exibida. O botão Editar é destacado.

  4. Você pode alternar a exibição clicando em Formulário ou JSON no canto superior direito. A view JSON é mais completa, mas somente leitura. Você só pode editar campos na exibição Formulário.

    A caixa de diálogo Editar cartão do agente é exibida. Os ícones de exibição JSON e Formulário são realçados. A view JSON está selecionada.

  5. Modifique os campos conforme necessário.
  6. Clique em Adicionar uma habilidade para adicionar as habilidades que você deseja expor aos clientes A2A.

    A caixa de diálogo Editar cartão do agente é exibida. O botão Adicionar uma habilidade é destacado.

  7. Clique em Salvar.

Editar um Cartão de Agente Publicado

Você pode modificar um cartão de agente publicado sem ter que cancelar a implantação ou reimplantar um agente.

O cartão publicado corresponde a um snapshot do cartão de rascunho no momento da implantação.

Observação:

As alterações feitas em um cartão publicado são imediatamente refletidas no arquivo agent-card.json acessível aos clientes A2A.
  1. Navegue até o seu agente.
  2. Clique em Ações e, em seguida, clique em Exibir cartão do agente e Cartão do agente publicado.

    A tela do Visual Builder é exibida. O menu Ações e a subopção Exibir cartão do agente são selecionados. O cartão do agente publicado está destacado.

  3. Você pode alternar a exibição clicando em Formulário ou JSON no canto superior direito. A view JSON é mais completa, mas somente leitura. Você só pode editar campos na exibição Formulário.
  4. Clique emEditar.

    A caixa de diálogo do cartão do agente publicado é exibida. O botão Editar é destacado.

  5. Modifique os campos conforme necessário.
  6. Clique em Adicionar uma habilidade para adicionar as habilidades que você deseja expor aos clientes A2A.

    Caixa de diálogo Editar cartão do agente. Aviso informando "Este cartão está anexado a um agente ativo; as atualizações afetarão o cartão do agente implantado." e o botão Publicar alterações são destacados.

  7. Clique em Publicar alterações.
Cartões de agente publicados não estão disponíveis publicamente. Um usuário precisa ser autenticado e ter a permissão certa (READ) para inspecionar o conteúdo do agent-card.json. Outros agentes podem descobrir seus recursos e metadados de agentes por meio de uma solicitação HTTP GET no caminho padrão:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a/agent-card.json