chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:30:30 +08:00
commit 914fea506e
2793 changed files with 802106 additions and 0 deletions
@@ -0,0 +1,503 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "copyright"
},
"outputs": [],
"source": [
"# Copyright 2026 Google LLC\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "header"
},
"source": [
"# Gemini Data Analytics: A2A HTTP API Sample\n",
"\n",
"This notebook demonstrates how to interact with the **DataA2AService** using standard HTTP requests. This is useful for environments where a high-level SDK is not available or when you want to minimize dependencies."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github"
},
"source": [
"<table align=\"left\">\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/agents/gemini_data_analytics/a2a_http_sample.ipynb\">\n",
" <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fagents%2Fgemini_data_analytics%2Fa2a_http_sample.ipynb\">\n",
" <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/agents/gemini_data_analytics/a2a_http_sample.ipynb\">\n",
" <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/agents/gemini_data_analytics/a2a_http_sample.ipynb\">\n",
" <img width=\"32px\" src=\"https://raw.githubusercontent.com/primer/octicons/refs/heads/main/icons/mark-github-24.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
" </a>\n",
" </td>\n",
"</table>\n",
"\n",
"<div style=\"clear: both;\"></div>\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "background-and-overview"
},
"source": [
"# Background and Overview\n",
"The **Conversational Analytics API** (also known as Gemini Data Analytics) lets you chat with your BigQuery or Looker data anywhere. This notebook demonstrates how to use the **A2A (Agent-to-Agent)** interface via standard HTTP requests. This is useful for environments where a high-level SDK is not available or when you want to minimize dependencies.\n",
"\n",
"This is a **Pre-GA** product. See [documentation](https://cloud.google.com/gemini/docs/conversational-analytics-api/overview) for more details.\n",
"\n",
"Please provide feedback to conversational-analytics-api-feedback@google.com\n",
"<br>\n",
"### This notebook will help you\n",
"1. Authenticate to Google Cloud\n",
"2. Retrieve the Agent Card\n",
"3. Send asynchronous messages and poll for results\n",
"4. Process agent outputs (Artifacts)\n",
"5. Cancel active tasks\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "setup",
"executionInfo": {
"status": "ok",
"timestamp": 1776195682585,
"user_tz": 420,
"elapsed": 138,
"user": {
"displayName": "",
"userId": ""
}
},
"outputId": "631853b2-2807-478e-d18c-761b72a77788"
},
"outputs": [],
"source": [
"# @title Setup and Authentication\n",
"import json\n",
"import os\n",
"import time\n",
"import uuid\n",
"from google.auth import default\n",
"from google.auth.transport.requests import Request\n",
"from google.colab import auth\n",
"import requests\n",
"\n",
"# Authenticate the user\n",
"auth.authenticate_user()\n",
"\n",
"# Get credentials and project ID\n",
"creds, _ = default()\n",
"creds.refresh(Request())\n",
"access_token = creds.token\n",
"\n",
"ENDPOINT = \"https://geminidataanalytics.googleapis.com\"\n",
"LOCATION = \"global\" # @param {type:\"string\"}\n",
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"# AGENT_ID can be found from the Cloud URL, e.g.\n",
"# https://console.cloud.google.com/bigquery/agents_hub/<your-agent-id>?project=<your-project-id>\n",
"AGENT_ID = \"your-agent-id\" # @param {type:\"string\"}\n",
"\n",
"if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\"\n",
" PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n",
"if not LOCATION:\n",
" LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\")\n",
" \n",
"TENANT = f\"projects/{PROJECT_ID}/locations/{LOCATION}/agents/{AGENT_ID}\"\n",
"BASE_URL = f\"{ENDPOINT}/v1beta/a2a/{TENANT}/v1\"\n",
"HEADERS = {\n",
" \"Authorization\": f\"Bearer {access_token}\",\n",
" \"Content-Type\": \"application/json\",\n",
"}\n",
"print(f\"Target Tenant: {TENANT}\")\n",
"print(f\"Access Token Length: {len(access_token) if access_token else 0}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "get-agent-card-header"
},
"source": [
"## 1. Get Agent Card\n",
"\n",
"First, let's retrieve the Agent Card to verify connectivity and see what the agent can do."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "get-agent-card-code",
"outputId": "437c7de7-c2ef-455d-e0b0-5f7bede70971"
},
"outputs": [],
"source": [
"url = f\"{BASE_URL}/card\"\n",
"\n",
"try:\n",
" response = requests.get(url, headers=HEADERS, timeout=30)\n",
" response.raise_for_status()\n",
" print(\"Agent Card:\")\n",
" print(json.dumps(response.json(), indent=2))\n",
"except Exception as e:\n",
" print(f\"Error fetching agent card: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "send-message-async-header"
},
"source": [
"## 2. Send Message (Asynchronous + Polling)\n",
"\n",
"For long-running tasks, use `blocking=False`. This returns a `Task` object immediately, which you can poll for status."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "send-message-async-code"
},
"outputs": [],
"source": [
"USER_QUERY = \"Hello\" # @param {type:\"string\"}\n",
"\n",
"def send_async_message(query):\n",
" url = f\"{BASE_URL}/message:send\"\n",
" payload = {\n",
" \"tenant\": TENANT,\n",
" \"message\": {\n",
" \"message_id\": f\"msg-{uuid.uuid4()}\",\n",
" \"role\": \"ROLE_USER\",\n",
" \"content\": [{\"text\": query}],\n",
" },\n",
" \"configuration\": {\"blocking\": False},\n",
" }\n",
"\n",
" response = requests.post(url, headers=HEADERS, json=payload, timeout=30)\n",
" response.raise_for_status()\n",
"\n",
" res_json = response.json()\n",
" \n",
" task = res_json.get(\"task\")\n",
" if task:\n",
" print(f\"Task created: {task.get('id')}\")\n",
" return task.get(\"id\")\n",
" elif \"message\" in res_json:\n",
" print(\"Received message directly instead of task.\")\n",
" return None\n",
" else:\n",
" print(\"Response did not contain 'task' or 'message'\")\n",
" return None\n",
"\n",
"\n",
"def poll_task(task_id, max_retries=15):\n",
" url = f\"{BASE_URL}/tasks/{task_id}\"\n",
" retry_count = 0\n",
" wait_time = 2\n",
"\n",
" while retry_count < max_retries:\n",
" response = requests.get(url, headers=HEADERS, timeout=30)\n",
" response.raise_for_status()\n",
"\n",
" task = response.json()\n",
" state = task.get(\"status\", {}).get(\"state\")\n",
" print(f\"Current State: {state}\")\n",
"\n",
" if state in [\n",
" \"TASK_STATE_COMPLETED\",\n",
" \"TASK_STATE_FAILED\",\n",
" \"TASK_STATE_CANCELLED\",\n",
" ]:\n",
" return task\n",
"\n",
" time.sleep(wait_time)\n",
" wait_time = min(wait_time * 1.5, 10)\n",
" retry_count += 1\n",
"\n",
" print(\"Polling timed out.\")\n",
" return None\n",
"\n",
"try:\n",
" print(\"Starting Send Message...\")\n",
" task_id = send_async_message(USER_QUERY)\n",
" \n",
" if task_id:\n",
" print(f\"Polling task {task_id}...\")\n",
" final_task = poll_task(task_id)\n",
" if final_task:\n",
" print(\"Final Task Result:\")\n",
" print(json.dumps(final_task, indent=2))\n",
" else:\n",
" print(\"No task ID returned, skipping polling.\")\n",
" \n",
"except Exception as e:\n",
" print(f\"Error during messaging/polling: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "artifact-parsing-header"
},
"source": [
"## 3. Processing Agent Outputs (Artifacts)\n",
"\n",
"Agents often produce **Artifacts** (structured data, files, or references). Here is how to parse them from a completed task."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "artifact-parsing-code"
},
"outputs": [],
"source": [
"USER_QUERY = \"Which item categories had the highest sales last year?\" # @param {type:\"string\"}\n",
"\n",
"\n",
"def get_data_and_extract_artifacts(query):\n",
" url = f\"{BASE_URL}/message:send\"\n",
" payload = {\n",
" \"tenant\": TENANT,\n",
" \"message\": {\n",
" \"message_id\": f\"msg-{uuid.uuid4()}\",\n",
" \"role\": \"ROLE_USER\",\n",
" \"content\": [{\"text\": query}],\n",
" },\n",
" # We set blocking=True to wait for the full response (including artifacts)\n",
" \"configuration\": {\"blocking\": True},\n",
" }\n",
"\n",
" print(f\"Sending analysis query: '{query}'\")\n",
" print(\"This involves data processing, so it may take 30-60 seconds...\")\n",
" \n",
" # 120 second timeout to give it plenty of time to compute\n",
" response = requests.post(url, headers=HEADERS, json=payload, timeout=120)\n",
" response.raise_for_status()\n",
"\n",
" res_json = response.json()\n",
" print(\"\\n--- Response Received ---\")\n",
"\n",
" # Case 1: The server returned a Task\n",
" task = res_json.get(\"task\")\n",
" if task:\n",
" print(\"Server returned a Task. Processing artifacts...\")\n",
" artifacts = task.get(\"artifacts\", [])\n",
" display_artifacts(artifacts)\n",
" return\n",
"\n",
" # Case 2: The server returned a Direct Message\n",
" message = res_json.get(\"message\")\n",
" if message:\n",
" print(\"Server returned a direct Message.\")\n",
" # Check if there are artifacts attached to the message or in the content\n",
" content_parts = message.get(\"content\", [])\n",
" \n",
" print(f\"Message contains {len(content_parts)} content parts.\")\n",
" for part in content_parts:\n",
" # Print the text response\n",
" if \"text\" in part:\n",
" print(f\"\\nText Response:\\n{part['text']}\")\n",
" \n",
" # Check for metadata that might contain structured data (artifacts)\n",
" metadata = part.get(\"metadata\", {})\n",
" if metadata:\n",
" print(f\"\\nMetadata found: {json.dumps(metadata, indent=2)}\")\n",
" return\n",
"\n",
" print(f\"Unexpected response structure: {res_json}\")\n",
"\n",
"\n",
"def display_artifacts(artifacts):\n",
" if not artifacts:\n",
" print(\"No artifacts found in the task.\")\n",
" return\n",
"\n",
" print(f\"Found {len(artifacts)} artifacts:\")\n",
" for art in artifacts:\n",
" name = art.get(\"name\", \"Unnamed\")\n",
" \n",
" art_type = (\n",
" art.get(\"metadata\", {})\n",
" .get(\"fields\", {})\n",
" .get(\"type\", {})\n",
" .get(\"stringValue\", None)\n",
" )\n",
" \n",
" if not art_type:\n",
" art_type = art.get(\"metadata\", {}).get(\"type\", \"Unknown\")\n",
" \n",
" print(f\"\\n- [{art_type}] {name}: {art.get('description')}\")\n",
" \n",
" for part in art.get(\"parts\", []):\n",
" if \"text\" in part:\n",
" content = part[\"text\"]\n",
" snippet = content[:500] + \"...\" if len(content) > 500 else content\n",
" print(f\" Content:\\n{snippet}\")\n",
"\n",
"try:\n",
" get_data_and_extract_artifacts(USER_QUERY)\n",
"except Exception as e:\n",
" print(f\"Error during artifact extraction: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cancel-task-header"
},
"source": [
"## 4. Cancel an Active Task\n",
"\n",
"If a task is taking too long or was sent in error, you can cancel it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cancel-task-code"
},
"outputs": [],
"source": [
"USER_QUERY = \"Which item categories had the highest sales last year?\" # @param {type:\"string\"}\n",
"\n",
"def cancel_task(task_id):\n",
" url = f\"{BASE_URL}/tasks/{task_id}:cancel\"\n",
" response = requests.post(url, headers=HEADERS, timeout=30)\n",
" response.raise_for_status()\n",
"\n",
" print(f\"Task {task_id} cancellation requested.\")\n",
" return response.json()\n",
"\n",
"def send_async_message_with_timeout(query, timeout_secs=60):\n",
" url = f\"{BASE_URL}/message:send\"\n",
" payload = {\n",
" \"tenant\": TENANT,\n",
" \"message\": {\n",
" \"message_id\": f\"msg-{uuid.uuid4()}\",\n",
" \"role\": \"ROLE_USER\",\n",
" \"content\": [{\"text\": query}],\n",
" },\n",
" \"configuration\": {\"blocking\": False},\n",
" }\n",
"\n",
" response = requests.post(url, headers=HEADERS, json=payload, timeout=timeout_secs)\n",
" response.raise_for_status()\n",
" \n",
" res_json = response.json()\n",
" task = res_json.get(\"task\")\n",
" if task:\n",
" return task.get(\"id\")\n",
" return None\n",
"\n",
"try:\n",
" print(f\"Starting task with 60s timeout: '{USER_QUERY}'\")\n",
" \n",
" new_task_id = send_async_message_with_timeout(USER_QUERY, timeout_secs=60)\n",
" \n",
" if new_task_id:\n",
" print(f\"Task created! ID: {new_task_id}. Cancelling now...\")\n",
" cancel_response = cancel_task(new_task_id)\n",
" print(f\"Cancel Response: {cancel_response}\")\n",
" else:\n",
" print(\"No task ID returned (the server might have answered immediately).\")\n",
" \n",
"except Exception as e:\n",
" print(f\"Error during cancellation demo: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cleanup-header"
},
"source": [
"## 5. Cleanup\n",
"\n",
"It is good practice to clean up any temporary resources or state created during your session."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cleanup-code"
},
"outputs": [],
"source": [
"# @title Resource Cleanup\n",
"print(\n",
" \"No specific cloud resources were created in this demo that require manual\"\n",
" \" deletion (e.g., storage buckets).\"\n",
")\n",
"print(\n",
" \"However, you can use this section to reset any local session state if\"\n",
" \" needed.\"\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
},
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@@ -0,0 +1,328 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "copyright"
},
"outputs": [],
"source": [
"# Copyright 2026 Google LLC\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "header"
},
"source": [
"# Gemini Data Analytics: A2A SDK API Sample\n",
"\n",
"This notebook demonstrates how to interact with the **DataA2Aservice** using the high-level A2A Python SDK."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github"
},
"source": [
"<table align=\"left\">\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/agents/gemini_data_analytics/a2a_sdk_sample.ipynb\">\n",
" <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fagents%2Fgemini_data_analytics%2Fa2a_sdk_sample.ipynb\">\n",
" <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/agents/gemini_data_analytics/a2a_sdk_sample.ipynb\">\n",
" <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/agents/gemini_data_analytics/a2a_sdk_sample.ipynb\">\n",
" <img width=\"32px\" src=\"https://storage.googleapis.com/github-repo/generative-ai/logos/GitHub_Invertocat_Dark.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
" </a>\n",
" </td>\n",
"</table>\n",
"\n",
"<div style=\"clear: both;\"></div>\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "background-and-overview"
},
"source": [
"# Background and Overview\n",
"The **Conversational Analytics API** (also known as Gemini Data Analytics) lets you chat with your BigQuery or Looker data anywhere. This notebook demonstrates how to use the high-level usage patterns off standard developer operations.\n",
"\n",
"This is a **Pre-GA** product. See [documentation](https://cloud.google.com/gemini/docs/conversational-analytics-api/overview) for more details.\n",
"\n",
"Please provide feedback to conversational-analytics-api-feedback@google.com\n",
"<br>\n",
"### This notebook will help you\n",
"1. Authenticate to Google Cloud and Setup Environment\n",
"2. Install a2a-sdk Library\n",
"3. Instantiate a High-level A2A Client\n",
"4. Fulfill requests synchronously without needing async loops\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "setup"
},
"outputs": [],
"source": [
"# @title 1. Environment Setup\n",
"# Install core dependencies\n",
"%pip install google-auth requests httpx nest_asyncio\n",
"\n",
"import os\n",
"import time\n",
"import uuid\n",
"from google.auth import default\n",
"from google.auth.transport.requests import Request\n",
"from google.colab import auth\n",
"\n",
"# Authenticate the user\n",
"auth.authenticate_user()\n",
"\n",
"# Get credentials and project ID\n",
"creds, _ = default()\n",
"creds.refresh(Request())\n",
"access_token = creds.token\n",
"\n",
"ENDPOINT = \"https://geminidataanalytics.googleapis.com\"\n",
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"LOCATION = \"global\" # @param {type:\"string\"}\n",
"# AGENT_ID can be found from the Cloud URL, e.g.\n",
"# https://console.cloud.google.com/bigquery/agents_hub/<your-agent-id>?project=<your-project-id>\n",
"AGENT_ID = \"your-agent-id\" # @param {type:\"string\"}\n",
"\n",
"if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\"\n",
" PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n",
"if not LOCATION:\n",
" LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\")\n",
" \n",
"TENANT = f\"projects/{PROJECT_ID}/locations/{LOCATION}/agents/{AGENT_ID}\"\n",
"\n",
"print(f\"Target Tenant: {TENANT}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sdk-install-header"
},
"source": [
"## 2. Install A2A SDK\n",
"\n",
"Pulling library mounts drawn from high level ADK frameworks instead of manual stubs!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "sdk-install-code"
},
"outputs": [],
"source": [
"# @title Fetch and reference SDK\n",
"# Running external library installs natively on Sandbox environment\n",
"%pip install a2a-sdk\n",
"\n",
"from a2a.client import Client as A2AClient\n",
"from a2a.types import AgentCard\n",
"\n",
"print(\"High-level SDK imported successfully. Please restart runtime if import fails directly after execution!\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "grpc-client-header"
},
"source": [
"## 3. Implementation: SDK Native Client\n",
"\n",
"Create constructor wrappers using authentic SDK client hooks operations of pure synchronous execution!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "grpc-client-code"
},
"outputs": [],
"source": [
"import uuid\n",
"import asyncio\n",
"import httpx\n",
"import nest_asyncio\n",
"from a2a.client import Client as A2AClient\n",
"from a2a.client.client_factory import ClientFactory as A2AClientFactory\n",
"from a2a.client.client import ClientConfig as A2AClientConfig\n",
"from a2a.types import TransportProtocol as A2ATransport, AgentCapabilities\n",
"from a2a.types import AgentCard\n",
"\n",
"nest_asyncio.apply()\n",
"\n",
"class DataA2AClient:\n",
"\n",
" def __init__(self, endpoint, token):\n",
" self.endpoint = f\"https://{endpoint}\" if not endpoint.startswith(\"http\") else endpoint\n",
" self.token = token\n",
" httpx_client = httpx.AsyncClient(\n",
" headers={\"Authorization\": f\"Bearer {self.token}\"},\n",
" timeout=60.0\n",
" )\n",
" client_config = A2AClientConfig(\n",
" streaming=True,\n",
" polling=True,\n",
" httpx_client=httpx_client,\n",
" supported_transports=[A2ATransport.http_json]\n",
" )\n",
" factory = A2AClientFactory(config=client_config)\n",
" card = AgentCard(\n",
" url=f\"{self.endpoint}/v1beta/a2a/{TENANT}/\", \n",
" name=\"TargetAgent\",\n",
" description=\"Test Agent\",\n",
" version=\"1.0\",\n",
" preferred_transport=\"HTTP+JSON\",\n",
" capabilities=AgentCapabilities(),\n",
" default_input_modes=[],\n",
" default_output_modes=[],\n",
" skills=[]\n",
" )\n",
" self.client = factory.create(card)\n",
"\n",
" async def send_message(self, tenant, text):\n",
" from a2a.types import Message as A2AMessage\n",
" \n",
" message = A2AMessage(\n",
" message_id=str(uuid.uuid4()),\n",
" role=\"user\",\n",
" parts=[{\"text\": text}]\n",
" )\n",
" \n",
" responses = self.client.send_message(message)\n",
" async for response in responses:\n",
" if hasattr(response, \"status\") and response.status:\n",
" print(f\"[Status] {response.status.state}\")\n",
" elif hasattr(response, \"artifact\") and response.artifact:\n",
" print(f\"[Artifact] {response.artifact.name}: {response.artifact.description}\")\n",
" elif hasattr(response, \"parts\") and response.parts:\n",
" part = response.parts[0]\n",
" if hasattr(part, \"root\") and part.root:\n",
" print(f\"[Message] {part.root.text}\")\n",
" elif hasattr(part, \"text\") and part.text:\n",
" print(f\"[Message] {part.text}\")\n",
"\n",
"client = DataA2AClient(ENDPOINT, access_token)\n",
"print(\"Client created successfully using authentic A2A SDK!\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "streaming-demo-header"
},
"source": [
"## 4. Example: Standard Resolution\n",
"\n",
"We can now receive targeted execution states naturally mapped on list loops!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "streaming-demo-code"
},
"outputs": [],
"source": [
"query = \"Show me sales trends for 2025\"\n",
"print(f\"Sending request: {query}\\n\")\n",
"\n",
"try:\n",
" asyncio.run(client.send_message(TENANT, query))\n",
"except Exception as e:\n",
" print(f\"Error: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cleanup-header"
},
"source": [
"## 5. Cleanup\n",
"\n",
"It is good practice to clean up any temporary resources or local session state."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cleanup-code"
},
"outputs": [],
"source": [
"# @title Resource Cleanup\n",
"print(\n",
" \"No specific cloud resources were created in this demo that require manual\"\n",
" \" deletion.\"\n",
")\n",
"print(\n",
" \"However, you can use this section to reset any local session state if\"\n",
" \" needed.\"\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-pointer",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff