Orquestrar agentes de dados com A2A

A API Conversational Analytics no Google Cloud implementa o protocolo Agent-to-Agent (A2A) (link em inglês), que permite que agentes em fluxos de trabalho com vários agentes descubram recursos, deleguem consultas analíticas e transmitam respostas estruturadas, como consultas SQL executáveis e visualizações de gráficos.

É possível consultar agentes de dados integrados à API Conversational Analytics para BigQuery e Looker transmitindo o contexto do conjunto de dados na solicitação de API ou consultar agentes de dados personalizados configurados com a lógica de negócios da sua organização.

Para criar e consultar agentes de dados diretamente, consulte Criar um agente de dados usando o SDK do Python ou Criar um agente de dados usando HTTP.

Saiba como e quando o Gemini para Google Cloud usa seus dados.

Como funciona a orquestração de agentes de dados

Ao integrar agentes de dados da API Conversational Analytics a um aplicativo ou sistema multiagente, o fluxo de trabalho de orquestração segue estas operações:

  • O agente orquestrador descobre os recursos e as habilidades de um agente de dados inspecionando o card dele antes de delegar consultas analíticas.
  • O agente orquestrador envia uma mensagem para consultar um agente de dados integrado (agents/bigquery-ca ou agents/looker-ca) especificando fontes de dados na solicitação ou um agente de dados personalizado (dataAgents/DATA_AGENT_ID) configurado com a lógica de negócios do domínio.
  • O agente de dados processa a solicitação, executa as consultas necessárias e retorna os resultados, seja como uma resposta completa ou transmitindo o progresso do raciocínio e artefatos estruturados (como SQL executável e especificações de gráficos do Vega-Lite).

Antes de começar

Antes de começar, atenda aos seguintes pré-requisitos:

  1. Ative a API Conversational Analytics, a API BigQuery e a API Looker no seu projeto Google Cloud .
  2. Verifique se você tem os papéis e permissões necessários do IAM.
  3. Autentique-se na API Conversational Analytics e instale a biblioteca de cliente ou receba um token de autorização.

Funções exigidas

Para ter as permissões necessárias para descobrir e consultar agentes de dados no A2A, peça ao administrador para conceder a você os seguintes papéis do IAM no seu projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias usando papéis personalizados ou outros papéis predefinidos.

Para consultar as fontes de dados subjacentes, você também precisa ter permissões de leitura nos conjuntos de dados de destino do BigQuery (como roles/bigquery.dataViewer) ou nas análises detalhadas do Looker.

Descobrir recursos do agente

Antes de delegar consultas a um agente de dados, um agente orquestrador ou um aplicativo cliente pode inspecionar o card do agente para conferir as funcionalidades e a configuração dele, como descrição, habilidades disponíveis e extensões compatíveis. É possível recuperar cards de agentes usando o método getCard para agentes de dados integrados (agents/bigquery-ca e agents/looker-ca) e personalizados (dataAgents/DATA_AGENT_ID).

Recuperar um card do agente

Os exemplos de código a seguir mostram como recuperar um card de agente. Esses exemplos usam o agente de dados integrado do BigQuery (agents/bigquery-ca) como exemplo, mas é possível recuperar o card do agente integrado do Looker (agents/looker-ca) ou de um agente de dados personalizado (dataAgents/DATA_AGENT_ID) mudando o nome do recurso do agente na sua solicitação:

SDK do Python

from google.cloud import geminidataanalytics_v1

client = geminidataanalytics_v1.DataA2AServiceClient()

agent_name = "projects/PROJECT_ID/locations/LOCATION/agents/bigquery-ca"

request = geminidataanalytics_v1.GetAgentCardRequest(tenant=agent_name)
card = client.get_agent_card(request=request)

print(card)

No exemplo anterior, substitua os valores da seguinte forma:

  • PROJECT_ID: ID do projeto Google Cloud
  • LOCATION: o local do recurso do agente (como us, us-east4, eu ou global)

HTTP

curl -X GET \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  "https://geminidataanalytics.googleapis.com/v1/a2a/projects/PROJECT_ID/locations/LOCATION/agents/bigquery-ca/v1/card"

No exemplo anterior, substitua os valores da seguinte forma:

  • PROJECT_ID: ID do projeto Google Cloud
  • LOCATION: o local do recurso do agente (como us, us-east4, eu ou global)

Entender a estrutura do card do agente

Uma solicitação bem-sucedida retorna um objeto de card do agente que contém metadados, habilidades e extensões compatíveis:

{
  "name": "BigQuery Conversational Analytics Agent",
  "description": "This agent can answer questions about your data using BigQuery.",
  "protocolVersion": "1.0",
  "skills": [
    {
      "id": "data-analysis",
      "name": "Data Analysis",
      "description": "Provides data analysis assistance",
      "examples": [
        "What is the total sales for the last 3 months?"
      ],
      "inputModes": [
        "text/plain"
      ],
      "outputModes": [
        "text/plain",
        "application/json"
      ]
    }
  ],
  "capabilities": {
    "streaming": true,
    "extensions": [
      {
        "uri": "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1",
        "description": "Google Data Analytics BigQuery Context extension"
      }
    ]
  },
  "defaultInputModes": [
    "text/plain"
  ],
  "defaultOutputModes": [
    "text/plain",
    "application/json"
  ]
}

O card do agente inclui os seguintes campos:

  • name: o nome de exibição do agente de dados
  • description: um resumo das capacidades analíticas do agente de dados
  • protocolVersion: a versão do protocolo A2A compatível com o endpoint (como 1.0)
  • skills: as tarefas que o agente de dados pode realizar, incluindo exemplos de comandos (examples) e formatos de dados compatíveis (inputModes e outputModes, como text/plain ou application/json)
  • capabilities.streaming: um valor booleano que indica se o agente de dados é compatível com o streaming em tempo real pelo método stream.
  • capabilities.extensions: as extensões A2A compatíveis com o agente de dados, como bigquery_context/v1, stateless/v1 e kms/v1.
  • defaultInputModes e defaultOutputModes: os formatos de dados padrão (como text/plain ou application/json) para payloads de solicitação e resposta

Enviar uma mensagem para um agente de dados

Para enviar uma mensagem a um agente de dados, use o método send. O agente de dados processa a solicitação, gera e executa as consultas SQL necessárias nos seus dados e retorna a resposta em linguagem natural com os artefatos de dados gerados.

Enviar uma mensagem

Ao enviar uma mensagem, especifique o agente de dados de destino no caminho do recurso:

  • Para agentes de dados integrados (agents/bigquery-ca ou agents/looker-ca), transmita referências de tabela de destino ou de análise no campo metadata usando a extensão bigquery_context/v1 ou looker_context/v1.
  • Para agentes de dados personalizados (dataAgents/DATA_AGENT_ID), omita o campo metadata porque o contexto, os esquemas e as instruções são configurados diretamente no recurso do agente.

Para processar consultas sem armazenar o histórico de conversas em Google Cloud, inclua a extensão stateless/v1 na sua solicitação. Para criptografar dados e metadados de conversas armazenadas usando uma chave de criptografia gerenciada pelo cliente, transmita a extensão kms/v1 com o nome da chave do Cloud KMS. Para mais informações, consulte Chaves de criptografia gerenciadas pelo cliente (CMEK).

Os exemplos de código a seguir mostram como enviar uma mensagem ao agente de dados integrado do BigQuery:

SDK do Python

from google.cloud import geminidataanalytics_v1

client = geminidataanalytics_v1.DataA2AServiceClient()

agent_name = "projects/PROJECT_ID/locations/LOCATION/agents/bigquery-ca"

request = geminidataanalytics_v1.SendMessageRequest(
    tenant=agent_name,
    message=geminidataanalytics_v1.Message(
        role="ROLE_USER",
        # Optional: Pass context_id to continue an existing conversation
        # context_id="projects/PROJECT_ID/locations/LOCATION/conversations/CONVERSATION_ID",
        parts=[
            geminidataanalytics_v1.Part(
                text="What are the top 5 countries where our users are located?"
            )
        ],
    ),
    configuration=geminidataanalytics_v1.SendMessageConfiguration(
        return_immediately=False
    ),
    metadata={
        "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1": {
            "datasource_references": {
                "bq": {
                    "tableReferences": [
                        {
                            "projectId": "DATASET_PROJECT_ID",
                            "datasetId": "DATASET_ID",
                            "tableId": "TABLE_ID",
                        }
                    ]
                }
            }
        },
        # Optional: Process queries without storing conversation history in Google Cloud
        # "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/stateless/v1": {},
        # Optional: Encrypt conversation history and metadata with a customer-managed encryption key (CMEK)
        # "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/kms/v1": {
        #     "kmsKey": "projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME"
        # },
    },
)

response = client.send_message(request=request)

print(response)

No exemplo anterior, substitua os valores da seguinte forma:

  • PROJECT_ID: ID do projeto Google Cloud
  • LOCATION: o local do recurso do agente (como us, us-east4, eu ou global)
  • CONVERSATION_ID: (opcional) o ID de uma sessão de conversa atual para continuar.
  • What are the top 5 countries where our users are located?: a pergunta em linguagem natural para fazer ao agente de dados
  • DATASET_PROJECT_ID: o ID do projeto do Google Cloud que contém o conjunto de dados do BigQuery (por exemplo, bigquery-public-data)
  • DATASET_ID: o ID do conjunto de dados do BigQuery (por exemplo, thelook_ecommerce)
  • TABLE_ID: o ID da tabela do BigQuery (por exemplo, users)
  • KEY_RING: (opcional) o nome do keyring do Cloud KMS ao usar a CMEK
  • KEY_NAME: (opcional) o nome da chave criptografada do Cloud KMS ao usar a CMEK.

HTTP

curl -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json; charset=utf-8" \
  -H "A2A-Extensions: https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1" \
  -d '{
    "message": {
      "role": "ROLE_USER",
      "parts": [
        {
          "text": "What are the top 5 countries where our users are located?"
        }
      ]
    },
    "configuration": {
      "return_immediately": false
    },
    "metadata": {
      "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1": {
        "datasource_references": {
          "bq": {
            "tableReferences": [
              {
                "projectId": "DATASET_PROJECT_ID",
                "datasetId": "DATASET_ID",
                "tableId": "TABLE_ID"
              }
            ]
          }
        }
      }
    }
  }' \
  "https://geminidataanalytics.googleapis.com/v1/a2a/projects/PROJECT_ID/locations/LOCATION/agents/bigquery-ca/v1/message:send"

No exemplo anterior, substitua os valores da seguinte forma:

  • PROJECT_ID: ID do projeto Google Cloud
  • LOCATION: o local do recurso do agente (como us, us-east4, eu ou global)
  • What are the top 5 countries where our users are located?: a pergunta em linguagem natural para fazer ao agente de dados
  • DATASET_PROJECT_ID: o ID do projeto do Google Cloud que contém o conjunto de dados do BigQuery (por exemplo, bigquery-public-data)
  • DATASET_ID: o ID do conjunto de dados do BigQuery (por exemplo, thelook_ecommerce)
  • TABLE_ID: o ID da tabela do BigQuery (por exemplo, users)

Entender a estrutura da resposta

Uma solicitação bem-sucedida retorna um objeto task que contém o status final, o identificador da conversa e os artefatos gerados:

{
  "task": {
    "id": "ab12d1f2-e170-4c4f-aff4-be466c6beaaa",
    "contextId": "projects/my-project/locations/us/conversations/conv-67890",
    "status": {
      "state": "TASK_STATE_COMPLETED"
    },
    "artifacts": [
      {
        "artifactId": "synthetic-8a368e8e-378a-4b80-9f07-0b1a397c221d",
        "name": "Final response",
        "description": "Final response from the agent.",
        "parts": [
          {
            "text": "The top 5 countries where our users are located are China (33,783), the United States (22,701), Brasil (14,620), South Korea (5,302), and France (4,645)."
          }
        ]
      },
      {
        "artifactId": "synthetic-50483808-b231-4b30-a859-2c30d0355a8d",
        "name": "Generated SQL",
        "description": "Generated SQL from the agent.",
        "parts": [
          {
            "text": "SELECT country, COUNT(DISTINCT id) AS user_count FROM `bigquery-public-data.thelook_ecommerce.users` GROUP BY country ORDER BY user_count DESC LIMIT 5",
            "mediaType": "text/x-sql"
          }
        ]
      }
    ]
  }
}

A resposta inclui os seguintes campos principais:

  • task.id: o identificador exclusivo da tarefa de execução
  • task.contextId: o caminho do recurso da conversa, que você transmite no campo message.contextId de solicitações subsequentes para continuar a sessão.
  • task.status.state: o estado de execução da tarefa (como TASK_STATE_COMPLETED)
  • task.artifacts[]: recursos estruturados gerados pelo agente de dados, como a resposta em linguagem natural (Final response), a consulta SQL executável (Generated SQL) e as linhas de resultados tabulares (Data result).

Respostas de stream de um agente de dados

Para receber atualizações em tempo real enquanto o agente de dados processa uma consulta, use o método stream. A resposta transmite atualizações de status (status_update) com ideias intermediárias e artefatos incrementais (artifact_update), como consultas SQL geradas e especificações de gráficos do Vega-Lite.

As solicitações de streaming também oferecem suporte a conversas contínuas (context_id), processamento sem estado (stateless/v1) e chaves de criptografia gerenciadas pelo cliente (kms/v1).

Enviar uma mensagem de streaming

Os exemplos de código a seguir mostram como transmitir eventos do agente de dados integrado do BigQuery. Para transmitir de um agente de dados personalizado (dataAgents/DATA_AGENT_ID), direcione o caminho do recurso do agente personalizado e omita o campo metadata:

SDK do Python

from google.cloud import geminidataanalytics_v1

client = geminidataanalytics_v1.DataA2AServiceClient()

agent_name = "projects/PROJECT_ID/locations/LOCATION/agents/bigquery-ca"

request = geminidataanalytics_v1.SendMessageRequest(
    tenant=agent_name,
    message=geminidataanalytics_v1.Message(
        role="ROLE_USER",
        parts=[
            geminidataanalytics_v1.Part(
                text="What are the top 5 countries where our users are located? Please show a pie chart."
            )
        ],
    ),
    metadata={
        "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1": {
            "datasource_references": {
                "bq": {
                    "tableReferences": [
                        {
                            "projectId": "DATASET_PROJECT_ID",
                            "datasetId": "DATASET_ID",
                            "tableId": "TABLE_ID",
                        }
                    ]
                }
            }
        },
        # Optional: Process queries without storing conversation history in Google Cloud
        # "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/stateless/v1": {},
        # Optional: Encrypt conversation history and metadata with a customer-managed encryption key (CMEK)
        # "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/kms/v1": {
        #     "kmsKey": "projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME"
        # },
    },
)

# Stream response events
stream = client.send_streaming_message(request=request)

for chunk in stream:
  print(chunk)

No exemplo anterior, substitua os valores da seguinte forma:

  • PROJECT_ID: ID do projeto Google Cloud
  • LOCATION: o local do recurso do agente (como us, us-east4, eu ou global)
  • What are the top 5 countries where our users are located? Please show a pie chart.: a pergunta em linguagem natural para fazer ao agente de dados
  • DATASET_PROJECT_ID: o ID do projeto do Google Cloud que contém o conjunto de dados do BigQuery (por exemplo, bigquery-public-data)
  • DATASET_ID: o ID do conjunto de dados do BigQuery (por exemplo, thelook_ecommerce)
  • TABLE_ID: o ID da tabela do BigQuery (por exemplo, users)
  • KEY_RING: (opcional) o nome do keyring do Cloud KMS ao usar a CMEK
  • KEY_NAME: (opcional) o nome da chave criptografada do Cloud KMS ao usar a CMEK.

HTTP

curl -X POST \
  -N \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json; charset=utf-8" \
  -H "Accept: text/event-stream, application/json" \
  -H "A2A-Extensions: https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1" \
  -d '{
    "message": {
      "role": "ROLE_USER",
      "parts": [
        {
          "text": "What are the top 5 countries where our users are located? Please show a pie chart."
        }
      ]
    },
    "metadata": {
      "https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/reference/a2a/extensions/bigquery_context/v1": {
        "datasource_references": {
          "bq": {
            "tableReferences": [
              {
                "projectId": "DATASET_PROJECT_ID",
                "datasetId": "DATASET_ID",
                "tableId": "TABLE_ID"
              }
            ]
          }
        }
      }
    }
  }' \
  "https://geminidataanalytics.googleapis.com/v1/a2a/projects/PROJECT_ID/locations/LOCATION/agents/bigquery-ca/v1/message:stream"

No exemplo anterior, substitua os valores da seguinte forma:

  • PROJECT_ID: ID do projeto Google Cloud
  • LOCATION: o local do recurso do agente (como us, us-east4, eu ou global)
  • What are the top 5 countries where our users are located? Please show a pie chart.: a pergunta em linguagem natural para fazer ao agente de dados
  • DATASET_PROJECT_ID: o ID do projeto do Google Cloud que contém o conjunto de dados do BigQuery (por exemplo, bigquery-public-data)
  • DATASET_ID: o ID do conjunto de dados do BigQuery (por exemplo, thelook_ecommerce)
  • TABLE_ID: o ID da tabela do BigQuery (por exemplo, users)

Entender a estrutura da resposta de streaming

Quando você envia uma solicitação de streaming, o servidor retorna um fluxo de objetos de evento (StreamResponse). Cada evento contém uma atualização de status ou de artefato.

Os eventos de atualização de status entregam notificações de progresso intermediário e mensagens de pensamento à medida que o agente de dados raciocina sobre sua consulta:

{
  "statusUpdate": {
    "taskId": "f41cd8e3-e665-460c-aceb-7b337f1848ef",
    "status": {
      "state": "TASK_STATE_WORKING",
      "message": {
        "role": "ROLE_AGENT",
        "parts": [
          {
            "text": "Analyzing context"
          },
          {
            "text": "Retrieved context for 1 table."
          }
        ]
      }
    }
  }
}

Os eventos de atualização de artefatos entregam objetos de saída estruturados, como consultas SQL executáveis, respostas em linguagem natural ou especificações de gráficos:

{
  "artifactUpdate": {
    "taskId": "f41cd8e3-e665-460c-aceb-7b337f1848ef",
    "artifact": {
      "artifactId": "synthetic-7ca98286-0a15-4ca0-a8bc-f14dc231b3ba",
      "name": "Chart result",
      "description": "Chart visualization generated by the data agent.",
      "parts": [
        {
          "data": {
            "title": "Top 5 Countries by User Population",
            "mark": "arc",
            "encoding": {
              "color": {
                "field": "country",
                "type": "nominal"
              },
              "theta": {
                "field": "user_count",
                "type": "quantitative"
              }
            },
            "data": {
              "values": [
                {
                  "country": "China",
                  "user_count": 33783
                },
                {
                  "country": "United States",
                  "user_count": 22701
                },
                {
                  "country": "Brasil",
                  "user_count": 14620
                },
                {
                  "country": "South Korea",
                  "user_count": 5302
                },
                {
                  "country": "France",
                  "user_count": 4645
                }
              ]
            }
          }
        }
      }
    },
    "lastChunk": true
  }
}

A resposta de streaming inclui os seguintes campos principais:

  • statusUpdate.status.state: o estado intermediário ou final da tarefa (como TASK_STATE_WORKING ou TASK_STATE_COMPLETED)
  • statusUpdate.status.message.parts[]: descrições de pensamento ou progresso emitidas durante a execução
  • artifactUpdate.artifact: o recurso estruturado gerado pelo agente de dados, como uma especificação de gráfico do Vega-Lite (data) ou uma consulta SQL (text).
  • artifactUpdate.lastChunk: uma flag booleana que indica se o stream de artefatos está concluído.

Para renderizar a especificação Vega ou Vega-Lite retornada em aplicativos Python ou de front-end, consulte Renderizar uma resposta do agente como uma visualização.

A seguir