<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:discourse="http://www.discourse.org/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Google Developer forums - Latest topics</title>
    <link>https://discuss.google.dev/latest</link>
    <description>Latest topics</description>
    
      <lastBuildDate>Tue, 15 Sep 2026 15:29:17 +0000</lastBuildDate>
      <atom:link href="https://discuss.google.dev/latest.rss" rel="self" type="application/rss+xml" />
        <item>
          <title>OAuth branding verification stuck — issues already fixed, no Trust &amp; Safety email received</title>
          <dc:creator><![CDATA[Dev_HerdTrack]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Hello Google Cloud Team,</p>
<p>I’m requesting help with a stuck OAuth branding verification.</p>
<p>Project ID: (PII Removed by Staff)<br>
App name: (PII Removed by Staff)<br>
User type: External</p>
<p>Situation:<br>
The Verification Center flagged 3 issues from a previous review:</p>
<ol>
<li>Privacy policy page does not have sufficient content</li>
<li>Home page is behind a login page</li>
<li>Home page does not explain the purpose of the app</li>
</ol>
<p>All three issues were already resolved before I first submitted for re-verification. I have re-verified again just now, logged out in an incognito browser, that:</p>
<ul>
<li>Our home page loads directly with no login wall, and clearly states the app’s purpose (“Dairy farm record-keeping, made simple… HerdTrack helps farmers track animals, milk records, health, breeding and expenses”)</li>
<li>Our privacy policy page has detailed, comprehensive content covering data collection, usage, and compliance with India’s DPDP Act 2023</li>
</ul>
<p>I selected “I have fixed the issues” and clicked Proceed on 14 Sep 2026. I have checked my registered contact email including Spam, and have not received any email from the Trust and Safety team since then. The Verification Center still shows the same stale issues today (15 Sep 2026).</p>
<p>Could someone please help trigger a status refresh, confirm whether my re-verification request was received, or escalate this to the Trust and Safety team?</p>
<p>Thank you.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/oauth-branding-verification-stuck-issues-already-fixed-no-trust-safety-email-received/397401">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/oauth-branding-verification-stuck-issues-already-fixed-no-trust-safety-email-received/397401</link>
          <pubDate>Tue, 15 Sep 2026 15:29:17 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397401</guid>
          <source url="https://discuss.google.dev/t/oauth-branding-verification-stuck-issues-already-fixed-no-trust-safety-email-received/397401.rss">OAuth branding verification stuck — issues already fixed, no Trust &amp; Safety email received</source>
        </item>
        <item>
          <title>New billing account creation stuck - OR_BACR2_32 and OR_BAOOC_15 errors</title>
          <dc:creator><![CDATA[Vikas_Bansal]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>I’m trying to create a new Google Cloud billing account for my organization.</p>
<p>First attempt failed with error: “Billing setup can’t be completed - Suspicious activity detected [OR_BACR2_32]”. I resolved this by finding and closing a duplicate payments profile (I had one India profile and one Honduras profile under the same name, which seemed to trigger the fraud check).</p>
<p>After that, subsequent attempts now show error “OR_BAOOC_15” asking to retry after 24 hours. UPI verification (small ₹2 authorization charges) succeeds each time, but the billing account creation never completes successfully.</p>
<p>Has anyone faced this issue or know how to resolve it? Would appreciate any guidance.</p>
            <p><small>1 post - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/new-billing-account-creation-stuck-or-bacr2-32-and-or-baooc-15-errors/397382">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/new-billing-account-creation-stuck-or-bacr2-32-and-or-baooc-15-errors/397382</link>
          <pubDate>Tue, 15 Sep 2026 14:47:19 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397382</guid>
          <source url="https://discuss.google.dev/t/new-billing-account-creation-stuck-or-bacr2-32-and-or-baooc-15-errors/397382.rss">New billing account creation stuck - OR_BACR2_32 and OR_BAOOC_15 errors</source>
        </item>
        <item>
          <title>Missing Date Range control on Postgresql Connector for Looker</title>
          <dc:creator><![CDATA[Carlos_de_Frutos]]></dc:creator>
          <category>Data Studio Q&amp;A</category>
          <description><![CDATA[
            <p>Hi all,</p>
<p>I’m trying to replicate a report that previously used the BigQuery connector (with native date range pushdown) but now needs to pull data from AlloyDB via the native PostgreSQL connector.</p>
<p>**Issue:** When using Custom Query mode and referencing the date range parameters `$DS_START_DATE` / `$DS_END_DATE` (with PostgreSQL casting, e.g. `‘$DS_START_DATE’::DATE`), Looker Studio throws a System Error before the query even reaches the database (Error IDs: 04578c6e, 04f8fd74).</p>
<p>**What I tested:** - Custom Query with `$DS_START_DATE` / `$DS_END_DATE` + casting → System Error (crashes immediately) - Direct table connection (no custom query) → report appears to pull the entire table regardless of the Date Range Control selection - Workaround: static `WHERE part_date &gt;= CURRENT_DATE - INTERVAL ‘X days’` in Custom Query → works, but is NOT dynamic (ignores the report’s date range control)</p>
<p>**Question:** 1. Does the native PostgreSQL connector actually support `$DS_START_DATE` / `$DS_END_DATE` in Custom Query mode? I couldn’t find this confirmed anywhere in the documentation. 2. If supported, what is the correct syntax/casting to avoid the System Error? 3. If not supported, is this a known limitation, and is there a workaround to get dynamic date-range pushdown to a PostgreSQL/AlloyDB source (similar to how the BigQuery connector handles it)?</p>
<p>This is currently blocking a migration from BigQuery to AlloyDB as the report’s underlying data source. Any guidance from the community or Product Experts would be greatly appreciated. Thanks!</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/missing-date-range-control-on-postgresql-connector-for-looker/397374">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/missing-date-range-control-on-postgresql-connector-for-looker/397374</link>
          <pubDate>Tue, 15 Sep 2026 14:33:48 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397374</guid>
          <source url="https://discuss.google.dev/t/missing-date-range-control-on-postgresql-connector-for-looker/397374.rss">Missing Date Range control on Postgresql Connector for Looker</source>
        </item>
        <item>
          <title>Mastering GCP VPC Service Controls: The Enterprise Guide</title>
          <dc:creator><![CDATA[utkarsh-google]]></dc:creator>
          <category>Compute Infrastructure</category>
          <description><![CDATA[
            <p>Identity and Access Management (IAM) controls <em>who</em> can access Google Cloud Platform (GCP) resources, and Virtual Private Cloud (VPC) firewalls dictate <em>where</em> IP traffic flows between compute instances. However, neither mechanism stops a legitimate user or compromised service account from exfiltrating sensitive data to an unauthorized external Cloud Storage bucket or public BigQuery dataset. VPC Service Controls (VPC-SC) closes this exfiltration gap by enforcing a security perimeter around Google Cloud APIs.</p>
<h2><a name="p-990032-h-1-why-vpc-service-controls-the-threat-model-1" class="anchor" href="https://discuss.google.dev#p-990032-h-1-why-vpc-service-controls-the-threat-model-1" aria-label="Heading link"></a><strong>1. Why VPC Service Controls? The Threat Model</strong></h2>
<p>Standard cloud security controls operate on identity boundaries (IAM) and network infrastructure boundaries (VPC Firewalls). Because Google Cloud managed services (BigQuery, Cloud Storage, Vertex AI, Cloud SQL) are multi-tenant services hosted on public API endpoints (<code>*.googleapis.com</code>), traditional perimeter defenses fail to prevent data movement across project boundaries.</p>
<pre><code class="lang-auto">+-----------------------------------------------------------------------------------+
|                              THE DATA EXFILTRATION RISK                           |
|                                                                                   |
|  [Compromised Identity or Service Account]                                        |
|                       |                                                           |
|                       |  1. IAM Permission Check PASSES (User has Read Access)     |
|                       v                                                           |
|        [Production BigQuery / GCS Bucket]                                         |
|                       |                                                           |
|                       |  2. Attacker runs: gsutil cp gs://prod/data gs://attacker |
|                       v                                                           |
|        [External / Personal GCS Bucket] &lt;--- IAM passes, Firewall bypassed!       |
+-----------------------------------------------------------------------------------+
</code></pre>
<h2><a name="p-990032-the-exfiltration-vectors-vpc-sc-prevents-2" class="anchor" href="https://discuss.google.dev#p-990032-the-exfiltration-vectors-vpc-sc-prevents-2" aria-label="Heading link"></a><strong>The Exfiltration Vectors VPC-SC Prevents</strong></h2>
<ul>
<li><strong>Authorized Insider Copying Data Out:</strong> A database administrator with valid IAM <code>roles/bigquery.admin</code> credentials executes a BigQuery extract job from a corporate laptop, copying sensitive PII into a personal Google Cloud account.</li>
<li><strong>Compromised Service Account Credentials:</strong> A stolen service account key with GCS read access is used outside the corporate network to dump database backups into an arbitrary external bucket.</li>
<li><strong>Stolen Service Agent Tokens:</strong> A compromised VM inside a VPC uses its compute engine default service account to write internal training datasets out to an untrusted external endpoint.</li>
</ul>
<p>VPC-SC mitigates these threats by shifting the security model from <strong>Identity-Only</strong> to <strong>Context-Aware Security at the API Layer</strong>. An API call is permitted only if the identity <em>and</em> the network context (IP origin, VPC network, device health, source project) satisfy the perimeter rules.</p>
<h2><a name="p-990032-h-2-architecture-core-primitives-3" class="anchor" href="https://discuss.google.dev#p-990032-h-2-architecture-core-primitives-3" aria-label="Heading link"></a><strong>2. Architecture &amp; Core Primitives</strong></h2>
<p>VPC Service Controls operates at the Google API Front End (GFE) layer. When a client issues a request to a protected API, the GFE evaluates the request against the perimeter configuration before routing it to the backend service.</p>
<p>Press enter or click to view image in full size</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/d/2/4/d24d3a5ff1b0ac1e2ed472532b0c73b5cb22a003.jpeg" data-download-href="/uploads/short-url/u0pJczGX1nni4vcOtJp7Wb5RJVV.jpeg?dl=1" title="" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/2/4/d24d3a5ff1b0ac1e2ed472532b0c73b5cb22a003_2_667x500.jpeg" alt="" data-base62-sha1="u0pJczGX1nni4vcOtJp7Wb5RJVV" width="667" height="500" role="presentation" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/2/4/d24d3a5ff1b0ac1e2ed472532b0c73b5cb22a003_2_667x500.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/2/4/d24d3a5ff1b0ac1e2ed472532b0c73b5cb22a003_2_1000x750.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/2/4/d24d3a5ff1b0ac1e2ed472532b0c73b5cb22a003_2_1334x1000.jpeg 2x" data-dominant-color="EEF1F6"></a></div><p></p>
<h2><a name="p-990032-core-architectural-components-4" class="anchor" href="https://discuss.google.dev#p-990032-core-architectural-components-4" aria-label="Heading link"></a><strong>Core Architectural Components</strong></h2>
<ul>
<li><strong>Service Perimeter:</strong> A logical security boundary enclosing one or more GCP projects. Managed service APIs selected inside the perimeter (e.g., <code>storage.googleapis.com</code>, <code>bigquery.googleapis.com</code>) refuse requests originating from outside the perimeter or crossing into unauthorized projects.</li>
<li><strong>Access Context Manager (ACM) &amp; Access Levels:</strong> ACM defines conditions based on public IP ranges, corporate subnets, user identities, or Chrome Enterprise device posture. Access Levels grant entry through the perimeter boundary.</li>
<li><strong>Ingress &amp; Egress Rules:</strong> Granular API-level access rules defined within the perimeter. They allow identity, project, and method-specific API communication into (Ingress) or out of (Egress) the perimeter.</li>
<li><strong>Perimeter Bridges:</strong> Bi-directional connections between two discrete perimeters that allow projects in separate perimeters to share specific Google APIs without merging the perimeters entirely.</li>
<li><strong>Restricted VIP</strong> (<code>restricted.googleapis.com</code>): A dedicated IP range (<code>199.36.90.4/30</code>) used to route Google API traffic entirely over internal network paths, ensuring protected traffic never traverses public internet routes.</li>
</ul>
<h2><a name="p-990032-h-3-key-enterprise-use-cases-5" class="anchor" href="https://discuss.google.dev#p-990032-h-3-key-enterprise-use-cases-5" aria-label="Heading link"></a><strong>3. Key Enterprise Use Cases</strong></h2>
<h2><a name="p-990032-real-world-use-case-1-financial-healthcare-data-isolation-piiphi-6" class="anchor" href="https://discuss.google.dev#p-990032-real-world-use-case-1-financial-healthcare-data-isolation-piiphi-6" aria-label="Heading link"></a><strong>Real-World Use Case 1: Financial &amp; Healthcare Data Isolation (PII/PHI)</strong></h2>
<p><strong>Scenario:</strong> An enterprise healthcare provider processes electronic health records (EHR) in BigQuery and Cloud Storage.</p>
<ul>
<li><strong>Objective:</strong> Ensure healthcare data cannot be read by or copied to external GCP accounts, while allowing data scientists on corporate laptops to run queries.</li>
</ul>
<p><strong>VPC-SC Implementation:</strong></p>
<ul>
<li>Place production data projects into a dedicated perimeter.</li>
<li>Restrict <code>bigquery.googleapis.com</code> and <code>storage.googleapis.com</code>.</li>
<li>Define an ACM Access Level permitting access <strong>only</strong> from corporate VPN public IP ranges and corporate-managed devices.</li>
<li>Block outbound <code>storage.objects.create</code> operations directed at non-approved project buckets via strict Egress policies.</li>
</ul>
<h2><a name="p-990032-real-world-use-case-2-multi-tenant-aiml-pipeline-security-vertex-ai-gemini-7" class="anchor" href="https://discuss.google.dev#p-990032-real-world-use-case-2-multi-tenant-aiml-pipeline-security-vertex-ai-gemini-7" aria-label="Heading link"></a><strong>Real-World Use Case 2: Multi-Tenant AI/ML Pipeline Security (Vertex AI &amp; Gemini)</strong></h2>
<p><strong>Scenario:</strong> An engineering organization trains custom LLMs using proprietary source code and customer datasets inside Vertex AI.</p>
<ul>
<li><strong>Objective:</strong> Prevent training datasets or fine-tuned model artifacts from being exported to external storage buckets or unauthorized third-party services.</li>
</ul>
<p><strong>VPC-SC Implementation:</strong></p>
<ul>
<li>Enclose Vertex AI, Artifact Registry, Cloud Storage, and Compute Engine APIs in a single AI perimeter.</li>
<li>Configure Egress rules to block connections to external GCS buckets while allowing internal service agents (<code>service-PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com</code>) to read from internal staging storage.</li>
</ul>
<h2><a name="p-990032-h-4-overcoming-complex-implementation-challenges-8" class="anchor" href="https://discuss.google.dev#p-990032-h-4-overcoming-complex-implementation-challenges-8" aria-label="Heading link"></a><strong>4. Overcoming Complex Implementation Challenges</strong></h2>
<h2><a name="p-990032-challenge-1-third-party-saas-multi-cloud-integrations-9" class="anchor" href="https://discuss.google.dev#p-990032-challenge-1-third-party-saas-multi-cloud-integrations-9" aria-label="Heading link"></a><strong>Challenge 1: Third-Party SaaS &amp; Multi-Cloud Integrations</strong></h2>
<p>External SaaS tools (Fivetran, Databricks, Snowflake) need to read/write data in BigQuery or GCS inside a protected perimeter.</p>
<ul>
<li><strong>Solution (Identity-Bound Ingress Rules):</strong> Avoid dynamic public IP whitelisting. Authenticate the SaaS vendor via service accounts or Workload Identity Federation, and restrict access to exact API operations:</li>
</ul>
<pre><code class="lang-auto"># Ingress Rule restricting external SaaS access to specific GCS write operations
ingress_policies {
  ingress_from {
    identity_type = "ANY_IDENTITY"
    identities    = ["serviceAccount:saas-data-ingest@vendor-project.iam.gserviceaccount.com"]
  }
  ingress_to {
    resources = ["projects/987654321012"]
    operations {
      service_name = "storage.googleapis.com"
      method_selectors {
        method = "google.storage.objects.create"
      }
    }
  }
}
</code></pre>
<h2><a name="p-990032-challenge-2-hidden-managed-service-dependencies-10" class="anchor" href="https://discuss.google.dev#p-990032-challenge-2-hidden-managed-service-dependencies-10" aria-label="Heading link"></a><strong>Challenge 2: Hidden Managed Service Dependencies</strong></h2>
<p>GCP managed services execute API calls across projects using implicit internal service agents (e.g., Dataflow worker nodes communicating with GCS, Compute, and Logging).</p>
<ul>
<li><strong>Solution:</strong> Map service agent accounts during discovery. Grant explicit Egress rules or include dependent APIs (Compute Engine, Cloud Storage, Artifact Registry) within the service perimeter boundary.</li>
</ul>
<h2><a name="p-990032-challenge-3-cicd-external-runners-github-actions-gitlab-ci-11" class="anchor" href="https://discuss.google.dev#p-990032-challenge-3-cicd-external-runners-github-actions-gitlab-ci-11" aria-label="Heading link"></a><strong>Challenge 3: CI/CD External Runners (GitHub Actions / GitLab CI)</strong></h2>
<p>Deployments from cloud-hosted runners outside the network perimeter are blocked when pushing build artifacts or executing Terraform apply.</p>
<ul>
<li><strong>Solution A:</strong> Use self-hosted runners deployed inside a dedicated management VPC inside the perimeter.</li>
<li><strong>Solution B:</strong> Use Workload Identity Federation paired with an Ingress rule granting the CI/CD identity access solely to deployment endpoints (e.g., <code>artifactregistry.googleapis.com</code> or <code>container.googleapis.com</code>).</li>
</ul>
<h2><a name="p-990032-h-6-phased-migration-methodology-12" class="anchor" href="https://discuss.google.dev#p-990032-h-6-phased-migration-methodology-12" aria-label="Heading link"></a><strong>6. Phased Migration Methodology</strong></h2>
<p>Transitioning to VPC Service Controls without interrupting business operations requires a strict four-phase rollout:</p>
<p><strong>1.Phase 1: Discovery &amp; Log Sink Setup</strong>:Prerequisite Phase.</p>
<p>Catalog all projects, active APIs, cross-project service accounts, and external third-party integrations. Create an organization-level Cloud Audit Log sink routing policy logs directly to BigQuery.</p>
<p><strong>2.Phase 2: Network Infrastructure &amp; Dry-Run Deployment</strong>:Weeks 1–2.</p>
<p>Configure private DNS zones mapping <code>*.googleapis.com</code> to <code>restricted.googleapis.com</code> (<code>199.36.90.4/30</code>). Deploy all perimeters and Access Levels in <code>DRY_RUN</code> mode using Infrastructure as Code (Terraform).</p>
<p><strong>3.Phase 3: Log Remediation &amp; Policy Iteration</strong>:Weeks 2–4.</p>
<p>Query BigQuery to isolate dry-run violations. Differentiate legitimate service interactions from unauthorized calls, and iteratively refine Ingress/Egress policies and Access Context Manager levels.</p>
<p><strong>4.Phase 4: Enforcement &amp; Operational Readiness</strong>:Maintenance Window.</p>
<p>Confirm zero unintended violations over 14 consecutive days. Transition perimeters to <code>ENFORCED</code> mode, trigger break-glass procedure drills, and activate SIEM alerting for unexpected blocks.</p>
<h2><a name="p-990032-h-7-production-automation-log-analysis-13" class="anchor" href="https://discuss.google.dev#p-990032-h-7-production-automation-log-analysis-13" aria-label="Heading link"></a><strong>7. Production Automation &amp; Log Analysis</strong></h2>
<h2><a name="p-990032-terraform-pattern-perimeter-with-scoped-policy-ingress-rules-14" class="anchor" href="https://discuss.google.dev#p-990032-terraform-pattern-perimeter-with-scoped-policy-ingress-rules-14" aria-label="Heading link"></a><strong>Terraform Pattern: Perimeter with Scoped Policy &amp; Ingress Rules</strong></h2>
<p>To prevent configuration drift, manage all VPC-SC resources declaratively:</p>
<pre><code class="lang-auto">#Terraform
resource "google_access_context_manager_service_perimeter" "production_perimeter" {
  parent         = "accessPolicies/${var.access_policy_id}"
  name           = "accessPolicies/${var.access_policy_id}/servicePerimeters/prod_perimeter"
  title          = "Production Data Service Perimeter"
  perimeter_type = "PERIMETER_TYPE_REGULAR"

  status {
    restricted_services = [
      "bigquery.googleapis.com",
      "storage.googleapis.com",
      "secretmanager.googleapis.com"
    ]

    resources = [
      "projects/123456789012" # Production Data Project
    ]

    ingress_policies {
      ingress_from {
        identity_type = "ANY_IDENTITY"
        sources {
          access_level = "accessPolicies/${var.access_policy_id}/accessLevels/corp_vpn_access"
        }
      }
      ingress_to {
        resources = ["*"]
        operations {
          service_name = "bigquery.googleapis.com"
          method_selectors {
            method = "google.bigquery.v2.JobService.InsertJob"
          }
        }
      }
    }
  }
}
</code></pre>
<h2><a name="p-990032-dry-run-log-diagnostics-query-15" class="anchor" href="https://discuss.google.dev#p-990032-dry-run-log-diagnostics-query-15" aria-label="Heading link"></a><strong>Dry-Run Log Diagnostics Query</strong></h2>
<p>Execute this query in BigQuery against your centralized Cloud Audit Log dataset to inspect blocked operations during the Dry-Run phase:</p>
<pre><code class="lang-auto">SELECT
  timestamp,
  protoPayload.authenticationInfo.principalEmail AS caller_identity,
  protoPayload.serviceName AS target_service,
  protoPayload.methodName AS api_method,
  protoPayload.resourceName AS target_resource,
  protoPayload.metadata.violationReason AS violation_reason,
  protoPayload.metadata.ingressViolations,
  protoPayload.metadata.egressViolations,
  protoPayload.metadata.vpcServiceControlsUniqueId AS violation_id
FROM
  `your_gcp_project.audit_logs.cloudaudit_googleapis_com_policy`
WHERE
  protoPayload.metadata.vpcServiceControlsUniqueId IS NOT NULL
  AND timestamp &gt;= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
ORDER BY
  timestamp DESC;
</code></pre>
<p><a href="https://medium.com/tag/vpc-service-control?source=post_page---footer_tags--c9417c76e549-----------------------------------------" rel="noopener nofollow ugc">Vpc Service Control</a></p>
<p><a href="https://medium.com/tag/vpc-sc?source=post_page---footer_tags--c9417c76e549-----------------------------------------" rel="noopener nofollow ugc">Vpcsc</a></p>
<p><a href="https://medium.com/tag/gcp-vpc-service-controls?source=post_page---footer_tags--c9417c76e549-----------------------------------------" rel="noopener nofollow ugc">Gcp Vpc Service Controls</a></p>
<p><a href="https://medium.com/tag/gcp-vpcsc?source=post_page---footer_tags--c9417c76e549-----------------------------------------" rel="noopener nofollow ugc">Gcp Vpcsc</a></p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/mastering-gcp-vpc-service-controls-the-enterprise-guide/397366">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/mastering-gcp-vpc-service-controls-the-enterprise-guide/397366</link>
          <pubDate>Tue, 15 Sep 2026 14:16:17 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397366</guid>
          <source url="https://discuss.google.dev/t/mastering-gcp-vpc-service-controls-the-enterprise-guide/397366.rss">Mastering GCP VPC Service Controls: The Enterprise Guide</source>
        </item>
        <item>
          <title>Swag Drop: The Arcade Weather-Shield Jacket</title>
          <dc:creator><![CDATA[Yugali]]></dc:creator>
          <category>Community News &amp; Announcements</category>
          <description><![CDATA[
            <p>If you climbed all the way to the <strong>Legend Tier</strong>, you didn’t do it by waiting for perfect conditions—you built through the storm.</p>
<p>To kick off the very first swag drop of 2026, we’re outfitting you with the ultimate barrier against the elements: <strong>The Arcade Weather-Shield Jacket.</strong> Throw it on for your morning commute or wear it to work—either way, it’s a flex you actually had to earn.</p>
<p><img src="https://d2yds90mtvelsl.cloudfront.net/original/4X/c/d/1/cd1f29603f7b53e485bede1ff9044751ae1ee722.gif" alt="_ 2026 Swag Drop  (1)" data-base62-sha1="tgADZ3pk64Hch1IG1LYSlnFU7wm" width="596" height="500" class="animated"></p>
<p><strong>Placed in the Champion and Legend Tier, here’s why it belongs in your rotation:</strong></p>
<ul>
<li>
<p><strong>Storm-ready weave:</strong> Repels light rain and shuts down gusting winds before they hit your layer.</p>
</li>
<li>
<p><strong>Official branding:</strong> Clean Google Cloud logo on the left chest paired with the super cloud logo on the sleeve.</p>
</li>
<li>
<p><strong>Total draft block:</strong> High stand-up collar, custom Velcro cuffs, and a ribbed elastic hem lock warmth in and the weather out.</p>
</li>
<li>
<p><strong>Secure cargo:</strong> Deep zippered hand-warmer pockets keep your phone, keys, and hands safe from cold snaps.</p>
</li>
<li>
<p><strong>Weightless mobility:</strong> Technical performance without the heavy winter bulk—made to keep you moving.</p>
</li>
</ul>
<p>Don’t leave this sitting on the table because it is built for whatever the forecast throws at your deploy!</p>
<p>If you’re new to the tier system, <strong>here’s how the Prize Tiers work:</strong> think of it like a “Snowball”. You never have to pick and choose between tiers when you rank up; your rewards just keep rolling forward and getting bigger:</p>
<ul>
<li>
<p><strong>Arcade Trooper Tier:</strong> This is your foundational milestone. Once you hit this points threshold, you unlock the core swag pack filled with essential Google Skills Arcade gear.</p>
</li>
<li>
<p><strong>Arcade Ranger Tier:</strong> The natural next step for participants pushing past the basics. It’s designed for players who stay consistent, bank more Arcade Points, and put in that extra effort across challenges—unlocking everything from the Trooper Tier plus an additional bonus reward on top.</p>
</li>
<li>
<p><strong>Arcade Champion Tier:</strong> A major leap into the upper ranks. Hitting the Arcade Champion Tier takes serious dedication, unlocking a high-tier collection of premium Google Skills Arcade gear that really stands out.</p>
</li>
<li>
<p><strong>Arcade Legend Tier:</strong> The absolute summit of the Google Skills Arcade. Reserved exclusively for the users who max out their points to finish at the very top, scoring everything from the Champion Tier plus an exclusive Legend-only reward.</p>
</li>
</ul>
<p><strong>In simple terms, you never miss out when you rank up. Reaching Arcade Ranger Tier gives you all the Arcade Trooper Tier swags plus extra gear, and reaching the Arcade Legend Tier gives you the complete Arcade Champion Tier pack plus exclusive rewards waiting at the very top.</strong></p>
<p><strong>Please note that Arcade Trooper and Arcade Ranger prizes won’t snowball into the Arcade Champion and Arcade Legend Tiers.</strong></p>
<p>That means every single badge and point you bank right now isn’t just getting you closer to the jacket—it’s building up the whole pile of gear waiting for you on the other side.</p>
<p>The clock’s ticking, the next challenge is waiting, and that Arcade Legend spot won’t claim itself. Go get it!</p>
<p><strong><a href="https://go.cloudskillsboost.google/arcade?utm_source=gcc&amp;utm_medium=post+&amp;utm_campaign=arcade-sept26-swag-drop-jacket" rel="noopener nofollow ugc">See You In The Cloud</a></strong></p>
            <p><small>11 posts - 9 participants</small></p>
            <p><a href="https://discuss.google.dev/t/swag-drop-the-arcade-weather-shield-jacket/397353">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/swag-drop-the-arcade-weather-shield-jacket/397353</link>
          <pubDate>Tue, 15 Sep 2026 13:23:46 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397353</guid>
          <source url="https://discuss.google.dev/t/swag-drop-the-arcade-weather-shield-jacket/397353.rss">Swag Drop: The Arcade Weather-Shield Jacket</source>
        </item>
        <item>
          <title>OAuth verification stuck on &quot;Homepage requirements&quot; — issue resolved, no Trust &amp; Safety email ever received (PII Removed by Staff)</title>
          <dc:creator><![CDATA[Gestión_Cloud_Uxe_Te]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>Our OAuth verification is blocked and we cannot find a way to move it forward.</p>
<p>Project ID: (PII Removed by Staff)<br>
Homepage: (URL Removed by Staff)<br>
Requested sensitive scope: …/auth/contacts<br>
Last review: 6 August 2026</p>
<p>Current status in the Verification Center:</p>
<ul>
<li>App functionality: approved</li>
<li>Branding guidelines: approved</li>
<li>Homepage requirements: FAILED — “Your homepage is protected by a sign-in page”</li>
<li>Privacy policy requirements: in review</li>
<li>Minimum scopes: in review</li>
</ul>
<p>The homepage issue has been fixed. (URL Removed by Staff) now serves our public<br>
product page directly: it does not redirect to any other URL, it does not<br>
require sign-in, it describes what the app does and why we request access to<br>
the user’s contacts, and it links to our privacy policy. The sign-in page now<br>
lives on a separate URL.</p>
<p>The Verification Center tells us to reply to the email thread with the Trust &amp;<br>
Safety team once the issues are resolved. We never received that email. We have<br>
searched all project owner and editor mailboxes, including spam, for messages<br>
from api-oauth-dev-verification-reply and google-cloud-compliance, and there is<br>
nothing. The console offers no option to resubmit or to request the thread<br>
again.</p>
<p>Could you please either re-trigger the review now that the homepage complies,<br>
or resend the Trust &amp; Safety thread so we can reply to it?</p>
<p>Happy to provide any additional information.</p>
<p>Thanks</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/oauth-verification-stuck-on-homepage-requirements-issue-resolved-no-trust-safety-email-ever-received-pii-removed-by-staff/397348">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/oauth-verification-stuck-on-homepage-requirements-issue-resolved-no-trust-safety-email-ever-received-pii-removed-by-staff/397348</link>
          <pubDate>Tue, 15 Sep 2026 13:16:08 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397348</guid>
          <source url="https://discuss.google.dev/t/oauth-verification-stuck-on-homepage-requirements-issue-resolved-no-trust-safety-email-ever-received-pii-removed-by-staff/397348.rss">OAuth verification stuck on &quot;Homepage requirements&quot; — issue resolved, no Trust &amp; Safety email ever received (PII Removed by Staff)</source>
        </item>
        <item>
          <title>Sharing Gemini Notebooks with domains that are part of your organisation</title>
          <dc:creator><![CDATA[richard_evans1]]></dc:creator>
          <category>Q&amp;A</category>
          <description><![CDATA[
            <p>I would like to be able to share Gemini Notebooks (NotebookLM) with users that are within my Google Workspace organisation, but use a completely different UPN.</p>
<p>For example, in my Google Workspace organisation, I have two domains registered in the “Domains” section.  I have the primary domain: “<a href="http://company1.co.uk" rel="noopener nofollow ugc">company1.co.uk</a>” and an additional domain: “<a href="http://company2.co.uk" rel="noopener nofollow ugc">company2.co.uk</a>” (this is all still within the same Google Workspace organisation).</p>
<p>Let’s say I (<a href="mailto:me@company1.co.uk">me@company1.co.uk</a>) create a Gemini Notebook, with a source that is on a shared Google Drive (a Google Doc).  I have a requirement to share this Gemini Notebook with another user in our Google Workspace environment (<a href="mailto:you@company2.co.uk">you@company2.co.uk</a>) (<a href="mailto:you@company2.co.uk">you@company2.co.uk</a> has view access to the Google Drive area where the Google Doc is by default because of where it is located).</p>
<p>If I share this with <a href="mailto:you@company2.co.uk">you@company2.co.uk</a>, the sources are not read.   It states “Source:0” in the bottom right.</p>
<p>I understand that when Google states that Gemini Notebooks cannot be shared out of the organisation, should that really read “cannot be shared with another domain name”?</p>
<p>The new Gemini sharing options do not help either.  If I add “<a href="http://company2.co.uk" rel="noopener nofollow ugc">company2.co.uk</a>” as a Trusted Domain in the “Allowlist”, I am advised that you “Can’t add your own domain or domain alias as an allowlisted domain.”</p>
<p>I do not want to enable public sharing.</p>
<p>How can I best enable sharing with additional internal domains for our users?</p>
<p>I am aware of the workaround with Google Groups, but I have not tested this yet.  It is not solution I want to adopt.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/sharing-gemini-notebooks-with-domains-that-are-part-of-your-organisation/397322">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/sharing-gemini-notebooks-with-domains-that-are-part-of-your-organisation/397322</link>
          <pubDate>Tue, 15 Sep 2026 10:14:19 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397322</guid>
          <source url="https://discuss.google.dev/t/sharing-gemini-notebooks-with-domains-that-are-part-of-your-organisation/397322.rss">Sharing Gemini Notebooks with domains that are part of your organisation</source>
        </item>
        <item>
          <title>LatLong map picker: allow pinch-to-zoom and drag-to-pan on mobile</title>
          <dc:creator><![CDATA[Rausa]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>When entering a LatLong value in a form, the map picker opens so the user can place the pin. On mobile, this map does not respond to standard touch gestures:</p>
<ul>
<li>Pinch-to-zoom does nothing. Zoom is only possible through the + and − buttons.</li>
<li>Dragging with a finger does not pan the map.</li>
</ul>
<p>Every other map on the device, including the Google Maps app itself and AppSheet’s own Map views, responds to these gestures. The picker is the only place where they are unavailable, so it feels broken rather than restricted.</p>
<p>This matters for field data entry. I use the picker to record the location of agricultural parcels, and the pin has to land on a specific point in open terrain with few landmarks. Reaching that point with only the zoom buttons takes many taps, and without panning I cannot move the view to where the parcel actually is.</p>
<p>The underlying Google Maps SDKs expose these gestures as settings that are enabled by default, so this looks like they are being explicitly turned off in the picker rather than being unavailable.</p>
<p>Could pinch-to-zoom and drag-to-pan be enabled in the LatLong picker?</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/latlong-map-picker-allow-pinch-to-zoom-and-drag-to-pan-on-mobile/397321">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/latlong-map-picker-allow-pinch-to-zoom-and-drag-to-pan-on-mobile/397321</link>
          <pubDate>Tue, 15 Sep 2026 10:14:02 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397321</guid>
          <source url="https://discuss.google.dev/t/latlong-map-picker-allow-pinch-to-zoom-and-drag-to-pan-on-mobile/397321.rss">LatLong map picker: allow pinch-to-zoom and drag-to-pan on mobile</source>
        </item>
        <item>
          <title>Application Documentation export omits Automation, app-level settings, and toggle-based column requirements</title>
          <dc:creator><![CDATA[Rausa]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>I use the Application Documentation export as a configuration record for my app. Comparing a 370-page export against the Editor, three categories are missing entirely.</p>
<p><strong>1. Automation</strong></p>
<p>The export has no Automation section. The strings “Event name”, “Task name” and “Run this process” do not appear even once in the document.</p>
<p>My bots are visible only indirectly, as the system tables they generate, listed among my data tables with names like:</p>
<ul>
<li>Process for Delete Preferences Row by deleting UserAccount</li>
<li>Delete The preferenced row Output</li>
</ul>
<p>Their triggering event, conditions, steps and Bypass security setting are nowhere in the document.</p>
<p><strong>2. The Require toggle on columns</strong></p>
<p>“Required_If” appears 314 times but is null for every column where I enabled the simple Require toggle instead of writing an expression. Only expression-based requirements are written out.</p>
<p>Reading the export back, a mandatory field is indistinguishable from an optional one.</p>
<p><strong>3. App-level settings</strong></p>
<p>Theme, brand, localization, offline and sync settings do not appear anywhere in the export.</p>
<hr>
<p>The document contains only four sections: Tables, Views, Format Rules and Actions.</p>
<p>Security filters and Delete-triggered bots, which I reported as missing earlier, do now appear correctly.</p>
<p>Is the export intended to cover these areas, or is it limited to those four sections by design?</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/application-documentation-export-omits-automation-app-level-settings-and-toggle-based-column-requirements/397309">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/application-documentation-export-omits-automation-app-level-settings-and-toggle-based-column-requirements/397309</link>
          <pubDate>Tue, 15 Sep 2026 08:31:31 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397309</guid>
          <source url="https://discuss.google.dev/t/application-documentation-export-omits-automation-app-level-settings-and-toggle-based-column-requirements/397309.rss">Application Documentation export omits Automation, app-level settings, and toggle-based column requirements</source>
        </item>
        <item>
          <title>Account Blocked - User limit exceeded in prototype app</title>
          <dc:creator><![CDATA[leneshkumar]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>I need help as well please.</p>
            <p><small>3 posts - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/account-blocked-user-limit-exceeded-in-prototype-app/397394">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/account-blocked-user-limit-exceeded-in-prototype-app/397394</link>
          <pubDate>Tue, 15 Sep 2026 06:37:36 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397394</guid>
          <source url="https://discuss.google.dev/t/account-blocked-user-limit-exceeded-in-prototype-app/397394.rss">Account Blocked - User limit exceeded in prototype app</source>
        </item>
        <item>
          <title>Bug: Inconsistent font rendering in Google Docs templates for creating PDFs</title>
          <dc:creator><![CDATA[yugal.one]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>Hi everyone!</p>
<p>I’m running into a quirky issue where custom fonts like Inter and Libre Barcode 39 Text in my Google Docs templates for creating PDFs aren’t rendering reliably. Instead of working consistently, the output randomly defaults to Arial font.</p>
<p>While this is just a minor visual glitch for my standard text using the Inter font, it completely breaks my scannable barcodes that use the Libre Barcode 39 Text font, because they just render as regular text!</p>
<p><strong>My current workaround:</strong> If I manually re-trigger the automation a couple of times, it eventually catches the fonts and renders the PDF correctly.</p>
<p>Has anyone else run into this, or does anyone know a trick to make sure the fonts cache and render correctly every single time?</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/bug-inconsistent-font-rendering-in-google-docs-templates-for-creating-pdfs/397279">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/bug-inconsistent-font-rendering-in-google-docs-templates-for-creating-pdfs/397279</link>
          <pubDate>Tue, 15 Sep 2026 06:27:15 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397279</guid>
          <source url="https://discuss.google.dev/t/bug-inconsistent-font-rendering-in-google-docs-templates-for-creating-pdfs/397279.rss">Bug: Inconsistent font rendering in Google Docs templates for creating PDFs</source>
        </item>
        <item>
          <title>Engineering Agent Observability with BigQuery</title>
          <dc:creator><![CDATA[meghasaini]]></dc:creator>
          <category>Data Analytics</category>
          <description><![CDATA[
            <p>The transition from experimental LLM chats to production-grade autonomous agents represents a fundamental shift from “Systems of Record” to “Systems of Action.” In this new paradigm, traditional batch logging is an operational liability. Why? Because when an agent hallucinates, fails to trigger a tool, or enters an infinite loop, post-mortem analysis is insufficient.</p>
<blockquote>
<p><em>Architecting for immediate intervention requires real-time telemetry that treats <strong>BigQuery not just as a passive data warehouse, but as a high-velocity engine for agentic triggers.</strong></em></p>
</blockquote>
<p>Most operational systems that rely on scheduled batch queries suffer from massive operational delays in scenarios like credit card fraud detection or supply chain bottlenecks. Human investigators piece together log entries and run ad-hoc SQL. Conversely, pushing raw data streams straight into LLMs is cost-prohibitive due to token burn. We need a hybrid model where high-speed, stateful SQL filters out the noise so AI agents only process targeted, enriched anomaly context.</p>
<p>Press enter or click to view image in full size</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/9/7/2/97285c71caa19c00a436d0cae79dcf4198251020.jpeg" data-download-href="/uploads/short-url/lzczq9yj1pgPfRfbeKROv7KFzcQ.jpeg?dl=1" title="" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/original/4X/9/7/2/97285c71caa19c00a436d0cae79dcf4198251020.jpeg" alt="" data-base62-sha1="lzczq9yj1pgPfRfbeKROv7KFzcQ" width="690" height="385" role="presentation" data-dominant-color="DFDEDC"></a></div><p></p>
<p>Mastering Agent Observability with BigQuery</p>
<h2><a name="p-989873-the-3-pillar-hybrid-architecture-detect-route-resolve-1" class="anchor" href="https://discuss.google.dev#p-989873-the-3-pillar-hybrid-architecture-detect-route-resolve-1" aria-label="Heading link"></a><strong>The 3-Pillar Hybrid Architecture: Detect, Route, Resolve</strong></h2>
<p>To solve this, Google Cloud provides a three-pillar event-driven architecture-</p>
<ol>
<li><strong>Detection (BigQuery Continuous Queries)</strong>: Persistent SQL runs continuously over streaming ingestion tables (<em>via the Storage Write API)</em> to evaluate rules and windowed heuristics. Rather than polling, BigQuery uses stateful operations like tumbling windows ( TUMBLE ) <em>and</em> stream-to-stream JOINs to compute rolling metrics and detect complex conditions, such as a customer making transactions in two distant countries within minutes (‘Impossible Travel’)<em>.</em> When an anomaly condition is met, EXPORT DATA immediately streams the structured alert payload to a Pub/Sub topic without leaving the data warehouse</li>
<li><strong>Routing (Pub/Sub &amp; Single Message Transforms)</strong>: Pub/Sub intercepts exported events, using lightweight JavaScript UDFs to reshape payloads into the exact schema expected by Vertex AI Agent Engine, and pushes it directly to the agent’s webhook endpoint.</li>
<li><strong>Resolution (ADK &amp; Agent Engine)</strong>: Autonomous agents hosted on Vertex AI Agent Engine receive the event, execute reasoning loops using custom tools, and either resolve the issue or escalate to human-in-the-loop workflows.</li>
</ol>
<p>Press enter or click to view image in full size</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/1/8/c/18c69ab2c6a28f3d137a703c298f8804ad2a25b0.jpeg" data-download-href="/uploads/short-url/3xaXXe4wAXdZGHQj9HmQ03HVfc4.jpeg?dl=1" title="" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/original/4X/1/8/c/18c69ab2c6a28f3d137a703c298f8804ad2a25b0.jpeg" alt="" data-base62-sha1="3xaXXe4wAXdZGHQj9HmQ03HVfc4" width="690" height="383" role="presentation" data-dominant-color="353C46"></a></div><p></p>
<h2><a name="p-989873-real-world-scenario-cymbal-bank-fraud-detection-2" class="anchor" href="https://discuss.google.dev#p-989873-real-world-scenario-cymbal-bank-fraud-detection-2" aria-label="Heading link"></a><strong>Real-World Scenario: Cymbal Bank Fraud Detection</strong></h2>
<p>Architecting for high-stakes environments such as fraud detection requires an event-driven loop where detection triggers autonomous action. In this pattern, <strong>BigQuery Continuous Queries</strong> monitor a stream of incoming data (e.g., retail transactions) for anomalies like “Impossible Travel.”</p>
<p>When an anomaly is detected, the query uses the <code>EXPORT DATA</code> statement to push the event to <strong>Pub/Sub</strong> in real-time. This message triggers an <strong>ADK Agent</strong> via Vertex AI Agent Engine, which can then use its tools to evaluate historical context and resolve the event or escalate it to a human.</p>
<h3><a name="p-989873-triggering-an-agent-via-continuous-stream-3" class="anchor" href="https://discuss.google.dev#p-989873-triggering-an-agent-via-continuous-stream-3" aria-label="Heading link"></a><strong>Triggering an Agent via Continuous Stream</strong></h3>
<p>The following SQL demonstrates the <strong>Reverse ETL</strong> pattern used to trigger an agent from a continuous stream:</p>
<pre><code class="lang-auto">EXPORT DATA OPTIONS (
  format = 'CLOUD_PUBSUB',
  uri = 'https://pubsub.googleapis.com/projects/[PROJECT_ID]/topics/fraud_investigator_trigger'
) AS (
  SELECT
    customer_id,
    transaction_id,
    'Anomaly Detected: Impossible Travel' AS alert_reason
  FROM
    APPENDS(TABLE `project.dataset.transactions`)
  WHERE
    is_anomaly = TRUE
);
</code></pre>
<h2><a name="p-989873-the-challenge-black-box-of-production-agents-4" class="anchor" href="https://discuss.google.dev#p-989873-the-challenge-black-box-of-production-agents-4" aria-label="Heading link"></a><strong>The Challenge: Black-Box of Production Agents</strong></h2>
<p>When you deploy such autonomous AI agents, traditional logging falls short because of the black box execution, unexpected token burn, silent hallucinations, and unmapped multi-agent decisions, etc.</p>
<p>Agents can make nondeterministic choices: they invoke nested tools, hand off control to sub-agents, pause for human approvals, and retry failed prompts. Without structured tracing, debugging a failed customer interaction feels like looking into a black box. Additionally, without token-level budgeting and latency tracking per tool, API costs and latency spikes can easily spiral out of control. <strong>We need an analytics engine that treats agent execution traces as queryable, structured data.</strong></p>
<p>Press enter or click to view image in full size</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/e/9/5/e95a0a39a1c2fd652f493de825a59341180186a1.jpeg" data-download-href="/uploads/short-url/xik9Wc5eeUJmfIPe8wuU0xrnlLj.jpeg?dl=1" title="" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/original/4X/e/9/5/e95a0a39a1c2fd652f493de825a59341180186a1.jpeg" alt="" data-base62-sha1="xik9Wc5eeUJmfIPe8wuU0xrnlLj" width="690" height="380" role="presentation" data-dominant-color="BDBDBF"></a></div><p></p>
<p>The <strong>BigQuery Agent Analytics plugin</strong> for the ADK bridges the observability gap. It provides high-throughput, low-latency telemetry essential for debugging complex multi-agent fleets. By leveraging a <strong>Reverse ETL</strong> pattern, it allows BigQuery to push insights directly into the agentic workflow, transforming raw logs into actionable intelligence. It logs your AI agents’ operational telemetry, lifecycle events, tool executions, and LLM interactions directly into BigQuery tables.</p>
<p>Before we jump into how BigQuery Agent Analytics gives data practitioners total visbility into agent behavior, lets briefly look at the set up.</p>
<h3><a name="p-989873-the-set-up-5" class="anchor" href="https://discuss.google.dev#p-989873-the-set-up-5" aria-label="Heading link"></a><strong>The Set Up</strong></h3>
<p><strong>&gt;&gt;</strong> To set up the BQ Agent Analytics plugin, you have to follow these <a href="https://adk.dev/integrations/bigquery-agent-analytics/#configuration-options" rel="noopener nofollow ugc">config options</a> and understand the <a href="https://adk.dev/integrations/bigquery-agent-analytics/#schema-and-production-setup" rel="noopener nofollow ugc">schema and production setup</a>.</p>
<p><strong>&gt;&gt; The <code>attributes.adk</code> envelope —</strong> In the multi-agent workflows (agents that transfer control, checkpoint their state, and compact long histories) and long-running tools that pause and resume across turns, a small metadata envelope, <a href="https://adk.dev/integrations/bigquery-agent-analytics/#the-attributesadk-envelope" rel="noopener nofollow ugc"><code>attributes.adk</code></a>is used to build observability by tying the rows back to the ADK event that produced them.</p>
<p><strong>&gt;&gt; Event Lifecycle Coverage:</strong> The plugin automatically provisions a partitioned, clustered <em>agent_events</em> table that records 24 canonical event types. There are default <a href="https://adk.dev/integrations/bigquery-agent-analytics/#event-types" rel="noopener nofollow ugc">event types and payload generated</a> to trace LLM interactions. These events track the execution of tools by the agent and changes to agent’s state typically triggered by tools.</p>
<h2><a name="p-989873-unboxing-the-black-box-of-agent-analytics-6" class="anchor" href="https://discuss.google.dev#p-989873-unboxing-the-black-box-of-agent-analytics-6" aria-label="Heading link"></a><strong>Unboxing the Black-Box of Agent Analytics</strong></h2>
<p>BigQuery Agent Analytics Unboxes Agent Behavior into 5 Observable Pillars:</p>
<ol>
<li><strong>Muti-Agent Tracing &amp; Execution Graphs:</strong> Every single action carries a persistent session_id and OpenTelemetry (<code>trace_id</code>, <code>span_id</code>). The plugin stamps an <code>attributes.adk</code> envelope on log rows to reconstruct multi-agent execution graphs (DAG), handle agent transfers, and track long-running pauses.</li>
<li><strong>Multimodal Analysis:</strong> Automatically offloads large files (such as images and audio) to Google Cloud Storage and exposes them to BigQuery ML via Object Tables.</li>
<li><strong>Tool Provenance &amp; Human-in-the-Loop (HITL) Tracing:</strong> Tracks the exact origin of tools with explicit provenance tags (<code>LOCAL</code>, <code>MCP</code>, <code>SUB_AGENT</code>, <code>A2A</code>, <code>TRANSFER_AGENT</code>) and records Human-in-the-Loop (HITL) confirmation prompts, credential requests, and user inputs.</li>
<li><strong>Fleet Observability to Manage Costs and Performance-</strong> Monitoring an enterprise agent fleet requires granular tracking of token consumption and responsiveness. The plugin captures detailed metrics, including <code>usage_prompt_tokens</code> and <code>usage_completion_tokens</code>, allowing for precise cost-attribution strategies. Performance is measured via <code>total_ms</code> and <code>ttft_ms</code> (Time-to-First-Token)</li>
<li><strong>Business Decision Intelligence:</strong> The <strong>Context Graph</strong> feature (enabled via the BigQuery Agent Analytics SDK and the <code>bqaa context-graph</code> CLI tool) bridges the gap between raw, unstructured agent event logs and high-level business decision intelligence. The logged events can be materialized into a property graph, allowing operators to query decision trees using Graph Query Language (GQL)</li>
</ol>
<p>Let’s look at each of these in further detail.</p>
<h2><a name="p-989873-h-1-multi-agent-tracing-execution-graphs-7" class="anchor" href="https://discuss.google.dev#p-989873-h-1-multi-agent-tracing-execution-graphs-7" aria-label="Heading link"></a><strong>1. Multi-Agent Tracing &amp; Execution Graphs</strong></h2>
<p>BigQuery Agent Analytics reconstructs agent sessions using distributed tracing and execution graphs. For the failed sessions, it runs Root Cause Analysis (RCA) using BigQuery AI functions.</p>
<ol>
<li><strong>Granular Telemetry Streaming &amp; Immutable Event Capture:</strong> As an agent executes, the plugin captures every operational event (such as <code>AGENT_STARTING</code>, <code>LLM_REQUEST</code>, <code>TOOL_STARTING</code>, and <code>TOOL_ERROR</code>) and streams them asynchronously into BigQuery tables via the high-throughput Storage Write API. This guarantees a complete, chronological record of every step the agent took.</li>
<li><strong>Distributed Tracing via <code>trace_id</code>, <code>span_id</code>, and the <code>attributes.adk</code> envelope</strong>: Every logged row is stamped with OpenTelemetry-compatible identifiers (<code>trace_id</code>, <code>span_id</code>) and an <code>attributes.adk</code> metadata envelope. <code>parent_span_id</code>is a 16-char HEX span id to reconstruct the hierarchical <strong>Directed Acyclic Graph (DAG)</strong>. For multi-agent workflows, the plugin links agent transfers, state checkpoints (<code>AGENT_STATE_CHECKPOINT</code>), and long-running tool suspensions (<code>TOOL_PAUSED</code>) back to the exact conversation turn that triggered them.</li>
<li><strong>Automated Diagnostics via BigQuery AI Functions (<code>AI.GENERATE</code>):</strong> The plugin identifies the failed session and reconstructs the full conversation context. Then asks Gemini to diagnose the issue using AI.GENERATE. Instead of manual hunting, Supervisor agents automatically run AI.GENERATE over the aggregated history of a failed session to self-diagnose why an agent hit an API error or hallucinated.</li>
</ol>
<pre><code class="lang-auto">DECLARE failed_session_id STRING;
-- Find a recent failed session
SET failed_session_id = (
    SELECT session_id
    FROM `your-gcp-project-id.your-dataset-id.agent_events`
    WHERE error_message IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1
);

-- Reconstruct the full conversation context
WITH SessionContext AS (
    SELECT
        session_id,
        STRING_AGG(CONCAT(event_type, ': ', COALESCE(TO_JSON_STRING(content), '')), '\n' ORDER BY timestamp) as full_history
    FROM `your-gcp-project-id.your-dataset-id.agent_events`
    WHERE session_id = failed_session_id
    GROUP BY session_id
)
-- Ask Gemini to diagnose the issue
SELECT
    session_id,
    AI.GENERATE(
        ('Analyze this conversation log and explain the root cause of the failure. Log: ', full_history),
        endpoint =&gt; 'gemini-flash-latest'
    ).result AS root_cause_explanation
FROM SessionContext;
</code></pre>
<h2><a name="p-989873-h-2-multimodal-analysis-8" class="anchor" href="https://discuss.google.dev#p-989873-h-2-multimodal-analysis-8" aria-label="Heading link"></a><strong>2. Multimodal Analysis</strong></h2>
<p>Multimodal GCS Offloading in the BigQuery Agent Analytics plugin solves a core infrastructure challenge: how to capture massive text prompts or rich binary media (such as customer-submitted identity documents, transaction receipts, or voice verification audio) without bloating your analytical database or hitting row-size limits.</p>
<ol>
<li><strong>Generating Secure Signed URLs</strong> — Large text prompts (&gt;500KB) or binary media (images, audio) are automatically offloaded to Google Cloud Storage. BigQuery stores an <code>ObjectRef</code> reference in <code>content_parts</code>, allowing operators to inspect images via BigQuery Object Tables or generate signed URLs with <code>OBJ.GET_ACCESS_URL.</code>If an engineer or fraud analyst needs to view a specific image or listen to an audio clip associated with a flagged session, BigQuery can dynamically generate time-bound, secure access URLs using the object reference.</li>
<li><strong>Linking Object Tables for Direct SQL Inspection</strong>- By connecting your GCS bucket to BigQuery as an Object Table, you can query multimodal assets like traditional relational data — inspecting file sizes, update times, and mime types alongside your agent execution logs.</li>
<li><strong>Multimodal Auditing with BigQuery Remote Models (Gemini)</strong> — Because the assets are securely referenced via GCS URIs, you can pass offloaded images or documents straight into BigQuery ML remote models (such as Gemini) to perform automated visual audits, OCR on receipts, or anomaly classification at scale</li>
</ol>
<pre><code class="lang-auto">SELECT
  ml_generate_text_result.candidates[0].content.parts[0].text AS ai_image_analysis
FROM
  ML.GENERATE_TEXT(
    MODEL `your-project.your_dataset.gemini_multimodal_model`,
    (
      SELECT
        CONCAT('Analyze this transaction document for signs of tampering: ', 
               ML.SET_DOCK_IMAGE(JSON_VALUE(content_part, '$.object_ref.uri'))) AS prompt
      FROM `your-project.your_dataset.agent_events`,
           UNNEST(JSON_EXTRACT_ARRAY(payload, '$.content_parts')) AS content_part
      WHERE trace_id = 'target_suspicious_trace_id'
    )
  );
</code></pre>
<h2><a name="p-989873-h-3-tool-provenance-hitl-tracing-9" class="anchor" href="https://discuss.google.dev#p-989873-h-3-tool-provenance-hitl-tracing-9" aria-label="Heading link"></a><strong>3. Tool Provenance &amp; HITL Tracing</strong></h2>
<p>BigQuery Agent Analytics plugin provides deep visibility into <em>who</em> executed a tool, <em>where</em> it came from, and <em>when</em> a human had to step in.</p>
<p>When an agent calls a tool, the plugin logs its execution payload and stamps its exact <strong>origin classification</strong> (<code>origin</code>). This prevents “black-box” confusion when multiple agent tiers or external servers interact. To query tool provenance in BigQuery, query <code>v_tool_completed</code> to audit which tool origins are consuming resources or failing most frequently.</p>
<pre><code class="lang-auto">SELECT
  JSON_VALUE(payload, '$.tool_name') AS tool_name,
  JSON_VALUE(payload, '$.origin') AS tool_origin,
  COUNT(1) AS total_invocations,
  AVG(CAST(JSON_VALUE(payload, '$.latency_ms') AS FLOAT64)) AS avg_latency_ms
FROM
  `cymbal-fraud.analytics.v_tool_completed`
GROUP BY
  tool_name,
  tool_origin
ORDER BY
  total_invocations DESC;
</code></pre>
<h3><a name="p-989873-h-31-hitl-tracing-10" class="anchor" href="https://discuss.google.dev#p-989873-h-31-hitl-tracing-10" aria-label="Heading link"></a><strong>3.1 HITL Tracing</strong></h3>
<p>In high-stakes financial pipelines like a $2,500 cross-border fraud check, automation must occasionally yield to a human expert. When an agent encounters an ambiguous risk threshold, it pauses execution and triggers a Human-in-the-Loop event . The plugin records dedicated event types for these interactions:— <strong><code>HITL_CREDENTIAL_REQUEST, HITL_CONFIRMATION_REQUEST, HITL_INPUT_REQUEST, *_COMPLETED.</code></strong> Under ADK 2.0 multi-agent workflows, when an HITL request is emitted, the plugin logs a <strong><code>TOOL_PAUSED</code></strong> event and stamps an <code>attributes.adk</code> envelope on the row.</p>
<h2><a name="p-989873-h-4-monitoring-fleet-health-in-real-time-11" class="anchor" href="https://discuss.google.dev#p-989873-h-4-monitoring-fleet-health-in-real-time-11" aria-label="Heading link"></a><strong>4. Monitoring Fleet Health in Real-Time</strong></h2>
<p><strong>Fleet observability</strong> shifts the focus from debugging a single isolated agent run to monitoring an entire production ecosystem of enterprise AI agents. In high-volume environments like Cymbal Bank’s fraud prevention pipeline — which processes thousands of concurrent transaction alerts — platform operators need microscopic visibility into two critical pillars: <strong>cost attribution (token burn)</strong> and <strong>responsiveness (latency SLAs)</strong>.</p>
<p>The BigQuery Agent Analytics plugin streams these vital telemetry markers directly into BigQuery tables, giving engineering and finance teams the granular data needed to optimize performance and control operational spend.</p>
<h3><a name="p-989873-h-41-granular-token-consumption-cost-attribution-12" class="anchor" href="https://discuss.google.dev#p-989873-h-41-granular-token-consumption-cost-attribution-12" aria-label="Heading link"></a><strong>4.1 Granular Token Consumption &amp; Cost-Attribution</strong></h3>
<p>LLM API costs scale directly with token volume. Rather than receiving a generic, aggregated monthly bill from your AI provider, the plugin captures detailed usage attributes on every model call:</p>
<ul>
<li><strong><code>usage_prompt_tokens</code></strong>: Measures the exact size of the incoming context window (system instructions, user prompts, retrieved customer profile data, and event payloads).</li>
<li><strong><code>usage_completion_tokens</code></strong>: Measures the length of the model’s generated response (reasoning steps, risk scoring rationale, and final decisions).</li>
</ul>
<p>By storing these metrics natively in BigQuery alongside metadata like <code>trace_id</code> and agent names, users can run precise <strong>cost-attribution models</strong> such as breakdown token burn by specific departments, identifying which agents or instruction sets are bloated &amp; allowing engineers to optimize system prompts, or set up automated BigQuery alerting thresholds when token consumption spikes.</p>
<h3><a name="p-989873-h-42-responsiveness-latency-tracking-total_ms-ttft-13" class="anchor" href="https://discuss.google.dev#p-989873-h-42-responsiveness-latency-tracking-total_ms-ttft-13" aria-label="Heading link"></a><strong>4.2 Responsiveness &amp; Latency Tracking</strong> (<code>total_ms</code> <strong>&amp;</strong> <code>TTFT</code>)</h3>
<p>In real-time fraud detection, seconds matter. If an agent takes too long to analyze a transaction, downstream systems time out or user experience degrades. The plugin tracks performance through two core latency metrics:</p>
<ul>
<li><strong><code>total_ms</code> (Total Execution Latency):</strong> Measures the complete end-to-end duration of an LLM request or a tool execution from start to finish.</li>
<li><strong><code>ttft_ms</code> (Time-to-First-Token):</strong> Measures how quickly the model begins streaming its response back. This is crucial for real-time applications where perceived responsiveness depends on getting that first token instantly.</li>
</ul>
<p>Users can query the <code>v_llm_response</code> view to track rolling averages, spot performance degradation across regions, and ensure SLAs are met.</p>
<pre><code class="lang-auto">SELECT
  JSON_VALUE(payload, '$.model') AS model_name,
  DATE(timestamp) AS execution_date,
  COUNT(1) AS total_requests,
  ROUND(AVG(CAST(JSON_VALUE(payload, '$.latency_ms') AS FLOAT64)), 2) AS avg_total_latency_ms,
  ROUND(AVG(CAST(JSON_VALUE(payload, '$.ttft_ms') AS FLOAT64)), 2) AS avg_ttft_ms,
  MAX(CAST(JSON_VALUE(payload, '$.latency_ms') AS FLOAT64)) AS max_total_latency_ms
FROM
  `cymbal-fraud.analytics.v_llm_response`
GROUP BY
  model_name,
  execution_date
ORDER BY
  execution_date DESC;
</code></pre>
<h3><a name="p-989873-h-43-combining-token-burn-and-latency-in-fleet-dashboards-14" class="anchor" href="https://discuss.google.dev#p-989873-h-43-combining-token-burn-and-latency-in-fleet-dashboards-14" aria-label="Heading link"></a><strong>4.3 Combining Token Burn and Latency in Fleet Dashboards</strong></h3>
<p>Because all fleet metrics reside natively in BigQuery, teams can easily connect BI tools (like Looker or Looker Studio) to build comprehensive executive dashboards showing:</p>
<ol>
<li><strong>Cost vs. Latency Trade-offs:</strong> Comparing cheaper, faster models (e.g., flash tiers) against heavier reasoning models to find the optimal balance for fraud classification.</li>
<li><strong>Spike Detection:</strong> Correlating sudden surges in <code>usage_prompt_tokens</code> with unexpected data bloat or recursive tool loops.</li>
</ol>
<h2><a name="p-989873-h-5-business-decision-intelligence-15" class="anchor" href="https://discuss.google.dev#p-989873-h-5-business-decision-intelligence-15" aria-label="Heading link"></a><strong>5. Business Decision Intelligence</strong></h2>
<p>Instead of treating agent traces as isolated lists of API requests, responses, and tool errors, the Context Graph transforms them into a <strong>queryable BigQuery property graph</strong> that maps out how decisions are made.</p>
<p>Using a scheduled refresh (<code>bqaa context-graph</code>) or event-driven pipeline, the SDK reads raw agent telemetry and distills session logs into structured decision components: <em>DecisionRequest, DecisionOption, DecisionOutcome</em></p>
<p>The extracted components are mapped into a native BigQuery property graph schema using declarative table DDL and a <code>CREATE PROPERTY GRAPH</code> statement. Crucially, <strong>no separate external graph database or complex ETL pipeline is required</strong>—everything lives and runs natively within BigQuery.</p>
<p>Once materialized, you can use standard <strong>Graph Query Language (GQL)</strong> inside BigQuery via <code>GRAPH_TABLE</code> to traverse the decision network. For example, auditors or engineers can trace the exact chain of reasoning and confidence scores for a transaction review.</p>
<pre><code class="lang-auto">SELECT * FROM GRAPH_TABLE (
  cymbal_fraud_graph
  MATCH (req:DecisionRequest) -[eo:evaluatesOption]-&gt; (opt:DecisionOption),
        (req) -[ri:resultedIn]-&gt; (out:DecisionOutcome)
  COLUMNS (
    req.request_id AS transaction_id,
    req.request_text AS alert_summary,
    opt.option_label AS risk_strategy_considered,
    opt.confidence AS confidence_score,
    out.status AS final_decision,
    out.rationale AS audit_rationale
  )
);
</code></pre>
<p>Press enter or click to view image in full size</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/2/7/8/2788768fc061b7a715c06b06e6b01d264c8faf62.jpeg" data-download-href="/uploads/short-url/5DIZweG8Hoedu04mf3HKBxyO8U2.jpeg?dl=1" title="" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/original/4X/2/7/8/2788768fc061b7a715c06b06e6b01d264c8faf62.jpeg" alt="" data-base62-sha1="5DIZweG8Hoedu04mf3HKBxyO8U2" width="690" height="387" role="presentation" data-dominant-color="F2F4F6"></a></div><p></p>
<p>Decision Graph using BigQuery Agent Analytics Plugin</p>
<h2><a name="p-989873-the-future-of-autonomous-operations-16" class="anchor" href="https://discuss.google.dev#p-989873-the-future-of-autonomous-operations-16" aria-label="Heading link"></a><strong>The Future of Autonomous Operations</strong></h2>
<p>The shift toward autonomous operations demands that we view telemetry not as an afterthought, but as a <strong>core agentic skill</strong>. The combination of the <strong>BigQuery Agent Analytics SDK</strong> and Looker dashboards turns raw operational traces into competitive business intelligence. By materializing execution graphs and utilizing AI-powered RCA, organizations can finally peer inside the “black box” of agentic AI, ensuring that every autonomous action is observable, accountable, and optimized for performance.</p>
<p>Hope this was a helpful read.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/engineering-agent-observability-with-bigquery/397254">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/engineering-agent-observability-with-bigquery/397254</link>
          <pubDate>Tue, 15 Sep 2026 03:26:07 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397254</guid>
          <source url="https://discuss.google.dev/t/engineering-agent-observability-with-bigquery/397254.rss">Engineering Agent Observability with BigQuery</source>
        </item>
        <item>
          <title>BUG: Filtering behaves differently when viewing the data versus downloading the data</title>
          <dc:creator><![CDATA[WillowMobileSys]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>When filtering a Text based column in a Table view, we can apply filtering text that is used like a CONTAINS() type operation where all rows containing some version of the filter text are included in the filtered view.</p>
<p>However, when attempting to download that view, the file is empty.  Adjusting the filter text so that it EXACTLY matches the full text in the filtered column, results in all those EXACT matching rows (but reduced from the initial filter) being downloaded into the file.</p>
<p>This indicates that there is mis-match when filtering is applied for viewing versus when it is applied for downloading from the same view.</p>
<p>Please update the download filtering so it applies a CONTAINS() type operation to be in sync with the filtering applied for views.</p>
<p>Thanks!</p>
            <p><small>3 posts - 3 participants</small></p>
            <p><a href="https://discuss.google.dev/t/bug-filtering-behaves-differently-when-viewing-the-data-versus-downloading-the-data/397225">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/bug-filtering-behaves-differently-when-viewing-the-data-versus-downloading-the-data/397225</link>
          <pubDate>Mon, 14 Sep 2026 22:13:32 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397225</guid>
          <source url="https://discuss.google.dev/t/bug-filtering-behaves-differently-when-viewing-the-data-versus-downloading-the-data/397225.rss">BUG: Filtering behaves differently when viewing the data versus downloading the data</source>
        </item>
        <item>
          <title>Mastering fleet-wide governance on GKE using fleet level OPA</title>
          <dc:creator><![CDATA[vranda]]></dc:creator>
          <category>Community Articles</category>
          <description><![CDATA[
            <p>Maintaining security, compliance, and operational standards across multiple Kubernetes clusters is one of the most significant challenges platform engineering teams face today. Without proper guardrails, managing configurations across a growing fleet of clusters can quickly lead to security vulnerabilities, configuration drift, and bloated cloud bills.</p>
<p>In this blog post, we will explore how you can establish centralized governance across your Google Kubernetes Engine (GKE) clusters using GKE Policy Controller and compare it with the open-source OPA Gatekeeper project.</p>
<hr>
<h2><a name="p-989805-centralized-governance-fleet-level-opa-setup-1" class="anchor" href="https://discuss.google.dev#p-989805-centralized-governance-fleet-level-opa-setup-1" aria-label="Heading link"></a><strong>Centralized governance: Fleet-level OPA setup</strong></h2>
<p>Manually installing and managing policy engines on a cluster-by-cluster basis is highly inefficient and error-prone. To solve this, Google Cloud allows you to define policy configurations at the <strong>fleet level</strong>.</p>
<p>Once fleet-level defaults are enabled, any new GKE cluster registered to the fleet automatically inherits:</p>
<ul>
<li>
<p><strong>Automatic Installation:</strong> Policy Controller is deployed automatically on registration.</p>
</li>
<li>
<p><strong>Version Management:</strong> The fleet centrally manages the controller version.</p>
</li>
<li>
<p><strong>Global Settings:</strong> Global settings such as audit intervals, exempted namespaces, and referential constraints are consistently applied.</p>
</li>
</ul>
<h3><a name="p-989805-managed-policy-bundles-2" class="anchor" href="https://discuss.google.dev#p-989805-managed-policy-bundles-2" aria-label="Heading link"></a><strong>Managed policy bundles</strong></h3>
<p>Google Cloud provides ready-to-use <strong>Policy Bundles</strong> mapped to industry standards. You can apply these to all member clusters simultaneously to achieve instant compliance:</p>
<ul>
<li>
<p><strong>CIS Kubernetes Benchmark:</strong> Align cluster settings with the Center for Internet Security standards.</p>
</li>
<li>
<p><strong>Regulated Industries (PCI-DSS / NIST / HIPAA):</strong> Compliance-specific bundles designed to meet rigorous regulatory controls.</p>
</li>
<li>
<p><strong>Cost &amp; Reliability:</strong> A bundle that proactively flags wasteful resource configurations or missing high-availability setups (like missing PodDisruptionBudgets).</p>
</li>
</ul>
<h3><a name="p-989805-fleet-dashboard-observability-3" class="anchor" href="https://discuss.google.dev#p-989805-fleet-dashboard-observability-3" aria-label="Heading link"></a><strong>Fleet dashboard &amp; observability</strong></h3>
<p>Within the GKE Enterprise console, you get a unified dashboard offering complete visibility:</p>
<ul>
<li>
<p><strong>Violation Summaries:</strong> Identify which clusters have the highest compliance risk.</p>
</li>
<li>
<p><strong>Security Command Center (SCC) Integration:</strong> Violations are pushed to SCC as “findings,” enabling security operations teams to track Kubernetes risks alongside general cloud infrastructure.</p>
</li>
</ul>
<p>[image]</p>
<hr>
<h2><a name="p-989805-gke-policy-controller-vs-oss-opa-gatekeeper-4" class="anchor" href="https://discuss.google.dev#p-989805-gke-policy-controller-vs-oss-opa-gatekeeper-4" aria-label="Heading link"></a><strong>GKE Policy Controller vs. OSS OPA Gatekeeper</strong></h2>
<p>While GKE Policy Controller is built on the open-source OPA Gatekeeper engine, Google Cloud adds significant enterprise management capabilities:<br>
<strong>Feature</strong><br>
<strong>OSS OPA Gatekeeper</strong><br>
<strong>GKE Policy Controller (Fleet)</strong><br>
<strong>Management</strong><br>
Manual (per cluster)<br>
Centralized (Fleet-wide)<br>
<strong>Bundles</strong><br>
Community-maintained<br>
Google-maintained &amp; updated<br>
<strong>Installation</strong><br>
Helm / Kubectl<br>
One-click or CLI Fleet enablement<br>
<strong>Observability</strong><br>
Prometheus / Grafana<br>
GCP Console + Security Command Center<br>
<strong>Support</strong><br>
Community<br>
Google Enterprise Support</p>
<hr>
<h2><a name="p-989805-getting-started-enabling-fleet-level-policies-5" class="anchor" href="https://discuss.google.dev#p-989805-getting-started-enabling-fleet-level-policies-5" aria-label="Heading link"></a><strong>Getting started: Enabling Fleet-level policies</strong></h2>
<p>Enabling Policy Controller across your GKE fleet is straightforward. Using the gcloud CLI, you can declare your configuration in a YAML file and roll it out instantly.</p>
<h3><a name="p-989805-step-1-create-a-fleet-default-configuration-file-6" class="anchor" href="https://discuss.google.dev#p-989805-step-1-create-a-fleet-default-configuration-file-6" aria-label="Heading link"></a><strong>Step 1: Create a Fleet default configuration file</strong></h3>
<p>Create a file named fleet-default.yaml to specify the default configuration and any compliance bundles you wish to pre-install:</p>
<p>policyControllerHubConfig:</p>
<p>installSpec: INSTALL_SPEC_ENABLED</p>
<p>policyContent:</p>
<pre><code>bundles:

  cis-k8s-v1.5.1:

    exemptedNamespaces: \["kube-system"\]
</code></pre>
<p><em>Note: The CLI commands above are provided for explanation, testing, and experiment purposes only. In production environments, policy configurations should be managed using GitOps tools like Config Sync.</em></p>
<h3><a name="p-989805-step-2-apply-the-configuration-to-the-fleet-7" class="anchor" href="https://discuss.google.dev#p-989805-step-2-apply-the-configuration-to-the-fleet-7" aria-label="Heading link"></a><strong>Step 2: Apply the configuration to the Fleet</strong></h3>
<p>Run the following CLI command to enable Policy Controller using your default configuration:</p>
<p>gcloud container fleet policycontroller enable \</p>
<pre><code>--fleet-default-member-config=fleet-default.yaml
</code></pre>
<h3><a name="p-989805-step-3-verify-the-deployment-status-8" class="anchor" href="https://discuss.google.dev#p-989805-step-3-verify-the-deployment-status-8" aria-label="Heading link"></a><strong>Step 3: Verify the deployment status</strong></h3>
<p>You can describe the fleet state to verify that the policies have been successfully rolled out and are active across all member clusters:</p>
<p>gcloud container fleet policycontroller describe</p>
<hr>
<h2><a name="p-989805-h-10-real-world-guardrail-scenarios-9" class="anchor" href="https://discuss.google.dev#p-989805-h-10-real-world-guardrail-scenarios-9" aria-label="Heading link"></a><strong>10 Real-world guardrail scenarios</strong></h2>
<p>Here are ten common scenarios where Policy Controller helps you maintain strict control over GKE workloads:</p>
<h3><a name="p-989805-h-1-enforce-organizational-labeling-10" class="anchor" href="https://discuss.google.dev#p-989805-h-1-enforce-organizational-labeling-10" aria-label="Heading link"></a><strong>1. Enforce organizational labeling</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Requires every Namespace or Deployment to have specific labels (e.g., team-id, cost-center, or env).</p>
</li>
<li>
<p><strong>Why it matters:</strong> Essential for accurate cost attribution, department chargebacks, and owner tracing in multi-tenant environments.</p>
</li>
</ul>
<h3><a name="p-989805-h-2-restrict-ingress-domains-11" class="anchor" href="https://discuss.google.dev#p-989805-h-2-restrict-ingress-domains-11" aria-label="Heading link"></a><strong>2. Restrict ingress domains</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Restricts Ingress resources to only expose services on pre-approved corporate domains (e.g., hostnames ending in *.yourcompany.com).</p>
</li>
<li>
<p><strong>Why it matters:</strong> Prevents “shadow IT” and accidental public exposure of internal services on arbitrary or unmapped domains.</p>
</li>
</ul>
<h3><a name="p-989805-h-3-image-registry-whitelisting-12" class="anchor" href="https://discuss.google.dev#p-989805-h-3-image-registry-whitelisting-12" aria-label="Heading link"></a><strong>3. Image registry whitelisting</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Blocks any Pod from starting if its container image comes from an untrusted public registry.</p>
</li>
<li>
<p><strong>Why it matters:</strong> Forces teams to pull verified, scanned container images strictly from your private <a href="https://cloud.google.com/artifact-registry" rel="noopener nofollow ugc">Artifact Registry</a>.</p>
</li>
</ul>
<h3><a name="p-989805-h-4-mandatory-resource-limits-13" class="anchor" href="https://discuss.google.dev#p-989805-h-4-mandatory-resource-limits-13" aria-label="Heading link"></a><strong>4. Mandatory resource limits</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Denies Pods that do not explicitly define CPU/memory limits and requests.</p>
</li>
<li>
<p><strong>Why it matters:</strong> Prevents “noisy neighbor” issues where a single unconstrained container consumes all node resources, risking cluster stability.</p>
</li>
</ul>
<h3><a name="p-989805-h-5-prevent-privilege-escalation-14" class="anchor" href="https://discuss.google.dev#p-989805-h-5-prevent-privilege-escalation-14" aria-label="Heading link"></a><strong>5. Prevent privilege escalation</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Blocks containers configured with privileged: true, direct hostPath mounts, or running as root.</p>
</li>
<li>
<p><strong>Why it matters:</strong> Eliminates critical container escape risks that could allow a compromised pod to take control of the host GKE node.</p>
</li>
</ul>
<h3><a name="p-989805-h-6-ban-specific-image-tags-15" class="anchor" href="https://discuss.google.dev#p-989805-h-6-ban-specific-image-tags-15" aria-label="Heading link"></a><strong>6. Ban specific image tags</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Enforces version pinning by rejecting volatile image tags like :test or :latest.</p>
</li>
<li>
<p><strong>Why it matters:</strong> Ensures deployments are predictable, repeatable, and easily rolled back by enforcing immutable digest or semantic tags.</p>
</li>
</ul>
<h3><a name="p-989805-h-7-limit-service-types-no-public-loadbalancers-16" class="anchor" href="https://discuss.google.dev#p-989805-h-7-limit-service-types-no-public-loadbalancers-16" aria-label="Heading link"></a><strong>7. Limit service types (No public LoadBalancers)</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Prevents the creation of Services with type: LoadBalancer, steering teams toward secure internal Ingress pathways.</p>
</li>
<li>
<p><strong>Why it matters:</strong> Avoids unnecessary external IP costs and secures the cluster’s network perimeter from direct, unauthorized public ingress.</p>
</li>
</ul>
<h3><a name="p-989805-h-8-enforce-network-policies-17" class="anchor" href="https://discuss.google.dev#p-989805-h-8-enforce-network-policies-17" aria-label="Heading link"></a><strong>8. Enforce network policies</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Requires every new Namespace to contain a default “deny-all” NetworkPolicy object on creation.</p>
</li>
<li>
<p><strong>Why it matters:</strong> Establishes a zero-trust network posture inside the cluster right from the start.</p>
</li>
</ul>
<h3><a name="p-989805-h-9-prohibit-nodeport-services-18" class="anchor" href="https://discuss.google.dev#p-989805-h-9-prohibit-nodeport-services-18" aria-label="Heading link"></a><strong>9. Prohibit NodePort Services</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Disallows Kubernetes Services from exposing node-level ports (type: NodePort).</p>
</li>
<li>
<p><strong>Why it matters:</strong> Eliminates security gaps by preventing arbitrary, high-numbered ports from being opened on GKE worker nodes.</p>
</li>
</ul>
<h3><a name="p-989805-h-10-service-port-naming-for-observability-19" class="anchor" href="https://discuss.google.dev#p-989805-h-10-service-port-naming-for-observability-19" aria-label="Heading link"></a><strong>10. Service port naming for observability</strong></h3>
<ul>
<li>
<p><strong>What it does:</strong> Mandates that Service port names follow standard conventions (e.g., starting with http- or grpc-).</p>
</li>
<li>
<p><strong>Why it matters:</strong> Ensures service meshes (such as Istio/Cloud Service Mesh) and monitoring tools can automatically discover and trace protocol-specific traffic.</p>
</li>
</ul>
<hr>
<h2><a name="p-989805-step-by-step-testing-a-new-constraint-20" class="anchor" href="https://discuss.google.dev#p-989805-step-by-step-testing-a-new-constraint-20" aria-label="Heading link"></a><strong>Step-by-step: Testing a new constraint</strong></h2>
<p>Let’s walk through how to deploy and test a policy that prevents the use of unapproved public container registries.</p>
<h3><a name="p-989805-step-1-verify-the-constraint-template-exists-21" class="anchor" href="https://discuss.google.dev#p-989805-step-1-verify-the-constraint-template-exists-21" aria-label="Heading link"></a><strong>Step 1: Verify the constraint template exists</strong></h3>
<p>Policy Controller comes pre-installed with a large template library. Verify that the K8sAllowedRepos template is available in your cluster:</p>
<p>kubectl get constrainttemplates k8sallowedrepos</p>
<h3><a name="p-989805-step-2-define-your-constraint-configuration-22" class="anchor" href="https://discuss.google.dev#p-989805-step-2-define-your-constraint-configuration-22" aria-label="Heading link"></a><strong>Step 2: Define your constraint configuration</strong></h3>
<p>Create a file named deny-public-images.yaml. This file configures the K8sAllowedRepos template to watch Pod resources and only allow images originating from your private Google Artifact Registry path:</p>
<p>apiVersion: constraints.gatekeeper.sh/v1beta1</p>
<p>kind: K8sAllowedRepos</p>
<p>metadata:</p>
<p>name: allow-only-internal-registries</p>
<p>spec:</p>
<p>enforcementAction: deny</p>
<p>match:</p>
<pre><code>kinds:

  - apiGroups: \[""\]

    kinds: \["Pod"\]

excludedNamespaces:

  - kube-system

  - gatekeeper-system
</code></pre>
<p>parameters:</p>
<pre><code>repos:

  - "gcr.io/your-project-id/"

  - "us-central1-docker.pkg.dev/your-project-id/"
</code></pre>
<h3><a name="p-989805-step-3-apply-the-constraint-23" class="anchor" href="https://discuss.google.dev#p-989805-step-3-apply-the-constraint-23" aria-label="Heading link"></a><strong>Step 3: Apply the constraint</strong></h3>
<p>For a single cluster test, apply the file directly via kubectl:</p>
<p>kubectl apply -f deny-public-images.yaml</p>
<p><em>(Note: In a production environment, it is best practice to commit this file to a Git repository managed centrally by <a href="https://cloud.google.com/kubernetes-engine/docs/add-on/config-sync/overview" rel="noopener nofollow ugc">Config Sync</a> to synchronize policies across all GKE clusters automatically).</em></p>
<h3><a name="p-989805-step-4-test-the-constraint-24" class="anchor" href="https://discuss.google.dev#p-989805-step-4-test-the-constraint-24" aria-label="Heading link"></a><strong>Step 4: Test the constraint</strong></h3>
<p>Attempt to deploy a Pod using a public image from Docker Hub (which is outside your allowlist):</p>
<p>kubectl run test-public-image --image=nginx:test-tag</p>
<h4><a name="p-989805-expected-result-25" class="anchor" href="https://discuss.google.dev#p-989805-expected-result-25" aria-label="Heading link"></a><strong>Expected result</strong></h4>
<p>The cluster’s admission controller should reject your request with a descriptive error message:</p>
<p>Error from server (Forbidden): admission webhook “validation.gatekeeper.sh” denied the request: [allow-only-internal-registries] container  has an invalid image repo <a>nginx:test-tag</a>, allowed repos are [“<a href="http://gcr.io/your-project-id/" rel="noopener nofollow ugc">gcr.io/your-project-id/</a>”, …]</p>
<p>[image]</p>
<p><em>Note: The direct kubectl commands and manual constraint setups shown above are intended for explanation, testing, and experiment purposes only.</em></p>
<hr>
<h2><a name="p-989805-managing-the-impact-of-constraints-on-running-workloads-26" class="anchor" href="https://discuss.google.dev#p-989805-managing-the-impact-of-constraints-on-running-workloads-26" aria-label="Heading link"></a><strong>Managing the impact of constraints on running workloads</strong></h2>
<p>Because Policy Controller acts as an <strong>Admission Controller</strong>, it acts as a “bouncer” at the door of your cluster. It evaluates requests during the creation or update phase, meaning <strong>it will not retroactively terminate pods that are already running</strong>.</p>
<p>Here is how a newly applied constraint affects existing workloads:</p>
<h3><a name="p-989805-h-1-immediate-impact-audit-mode-27" class="anchor" href="https://discuss.google.dev#p-989805-h-1-immediate-impact-audit-mode-27" aria-label="Heading link"></a><strong>1. Immediate impact: “Audit” mode</strong></h3>
<p>Since the Pod is already running, it continues to run. However, the background <strong>Audit</strong> engine flags the workload as a violation:</p>
<ul>
<li>
<p>You will see the violation reported under <strong>GKE &gt; Posture Management &gt; Policy</strong> in the Google Cloud Console.</p>
</li>
<li>
<p>This allows you to identify non-compliant workloads without causing production outages.</p>
</li>
</ul>
<p><strong>Pro Tip:</strong> When launching a new constraint, set enforcementAction: dryrun first. This lets you observe violations in the dashboard before switching to deny to block deployments.</p>
<h3><a name="p-989805-h-2-future-impact-admission-blocking-28" class="anchor" href="https://discuss.google.dev#p-989805-h-2-future-impact-admission-blocking-28" aria-label="Heading link"></a><strong>2. Future impact: Admission blocking</strong></h3>
<p>The next time the workload is modified or restarted, the policy will intercept and block the deployment in the following cases:</p>
<ul>
<li>
<p><strong>Node Restarts / Pod Crashes:</strong> If a node goes down or a pod crashes, Kubernetes will try to recreate the Pod. The Policy Controller will block recreation if the pod does not meet the policy.</p>
</li>
<li>
<p><strong>Updates:</strong> Modifying labels, environment variables, or other deployment specifications will fail if the underlying Pod template violates the policy.</p>
</li>
<li>
<p><strong>Autoscaling:</strong> GKE’s Cluster Autoscaling or Horizontal Pod Autoscaling (HPA) will fail to spin up new pods if the templates are non-compliant.</p>
</li>
</ul>
<h3><a name="p-989805-h-3-checking-active-violations-from-cli-29" class="anchor" href="https://discuss.google.dev#p-989805-h-3-checking-active-violations-from-cli-29" aria-label="Heading link"></a><strong>3. Checking active violations from CLI</strong></h3>
<p>You can view a list of active violations directly using kubectl:</p>
<p>kubectl get k8sallowedrepos allow-only-internal-registries -o yaml</p>
<p>Under the status.violations section of the output, you will find the namespace and name of every non-compliant Pod currently running.</p>
<hr>
<h2><a name="p-989805-scaling-policy-management-with-config-sync-30" class="anchor" href="https://discuss.google.dev#p-989805-scaling-policy-management-with-config-sync-30" aria-label="Heading link"></a><strong>Scaling policy management with Config Sync</strong></h2>
<p>While manual setup via direct CLI commands works for testing, scaling policy management across an entire enterprise requires a declarative, version-controlled approach. Organizations leverage <strong>Config Sync</strong> to implement GitOps-driven, fleet-wide policy management.</p>
<p>By storing constraints and constraint templates in a central Git repository, Config Sync continuously monitors and automatically reconciles configurations across all member clusters in the fleet. This ensures that policies remain consistent, auditable through standard git workflows, and resistant to configuration drift across dev, staging, and production environments.</p>
<h2><a name="p-989805-conclusion-31" class="anchor" href="https://discuss.google.dev#p-989805-conclusion-31" aria-label="Heading link"></a><strong>Conclusion</strong></h2>
<p>Standardizing policy enforcement across your GKE environments is key to achieving robust security and cost-efficiency at scale. By leveraging GKE Policy Controller, platform teams can easily automate enforcement of industry-standard security frameworks across their entire GKE Fleet.</p>
<h3><a name="p-989805-further-reading-32" class="anchor" href="https://discuss.google.dev#p-989805-further-reading-32" aria-label="Heading link"></a><strong>Further reading</strong></h3>
<ul>
<li>
<p><a href="https://cloud.google.com/kubernetes-engine/docs/add-on/policy-controller/overview" rel="noopener nofollow ugc">Google Cloud GKE Policy Controller Documentation</a></p>
</li>
<li>
<p><a href="https://github.com/open-policy-agent/gatekeeper" rel="noopener nofollow ugc">Open-Source OPA Gatekeeper GitHub Repository</a></p>
</li>
</ul>
            <p><small>1 post - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/mastering-fleet-wide-governance-on-gke-using-fleet-level-opa/397208">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/mastering-fleet-wide-governance-on-gke-using-fleet-level-opa/397208</link>
          <pubDate>Mon, 14 Sep 2026 21:03:28 +0000</pubDate>
          <discourse:topicPinned>Yes</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397208</guid>
          <source url="https://discuss.google.dev/t/mastering-fleet-wide-governance-on-gke-using-fleet-level-opa/397208.rss">Mastering fleet-wide governance on GKE using fleet level OPA</source>
        </item>
        <item>
          <title>Zero-infrastructure managed XProf: Profiling ML workloads on Cloud TPU with ML Diagnostics</title>
          <dc:creator><![CDATA[lakshaygpt]]></dc:creator>
          <category>Community Articles</category>
          <description><![CDATA[
            <p><strong>TL;DR:</strong> Capture XProf performance profiles and monitor real-time ML training metrics on Cloud TPU VMs with zero infrastructure setup. Skip self-hosted profiler servers, stream hardware telemetry directly to Google Cloud, and analyze multi-host traces up to 10x faster in the managed XProf viewer at zero compute charge.</p>
<hr>
<p>Waiting for a <a href="https://docs.jax.dev/" rel="noopener nofollow ugc">JAX</a> training loop to finish on a Cloud TPU slice while step times spike or accelerator utilization drops is frustrating. Debugging these bottlenecks often pulls ML engineers away from modeling and into operations: setting up self-hosted <a href="https://www.tensorflow.org/tensorboard" rel="noopener nofollow ugc">TensorBoard</a> and <a href="https://openxla.org/xprof" rel="noopener nofollow ugc">XProf</a> servers, configuring SSH port-forwarding, and manually syncing profile traces across storage buckets.</p>
<p>The <a href="https://pypi.org/project/google-cloud-mldiagnostics/" rel="noopener nofollow ugc"><strong>Google Cloud ML Diagnostics SDK</strong></a> (part of the <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/overview" rel="noopener nofollow ugc">ML Diagnostics platform</a>) eliminates this overhead. It delivers a fully managed <a href="https://openxla.org/xprof" rel="noopener nofollow ugc">XProf</a> profiling and observability experience directly in the Google Cloud console. <strong>Best of all, there is no compute charge for the managed XProf backend deployed by ML Diagnostics—you only pay for Cloud Logging metric ingestion and Cloud Storage trace storage.</strong></p>
<p>In this 5-minute walkthrough, you will provision a <a href="https://cloud.google.com/tpu/docs/users-guide-tpu-vm" rel="noopener nofollow ugc">Cloud TPU VM</a>, instrument a JAX training script to record metrics and capture XProf profiles, and inspect your hardware telemetry in the Google Cloud console.</p>
<h2><a name="p-989794-prerequisites-1" class="anchor" href="https://discuss.google.dev#p-989794-prerequisites-1" aria-label="Heading link"></a>Prerequisites</h2>
<p>Configure the required APIs, IAM permissions, and Cloud Storage bucket in your Google Cloud project so your workload can stream telemetry without permission errors.</p>
<h3><a name="p-989794-required-apis-and-iam-roles-2" class="anchor" href="https://discuss.google.dev#p-989794-required-apis-and-iam-roles-2" aria-label="Heading link"></a>Required APIs and IAM roles</h3>
<div class="md-table">
<table>
<thead>
<tr>
<th>Type</th>
<th>Resource</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>API</strong></td>
<td><code>hypercomputecluster.googleapis.com</code></td>
<td>Cluster Director API for <code>MLRun</code> registration, telemetry ingestion, and UI visualization</td>
</tr>
<tr>
<td><strong>API</strong></td>
<td><code>tpu.googleapis.com</code></td>
<td>Cloud TPU API for provisioning and managing Cloud TPU VMs</td>
</tr>
<tr>
<td><strong>API</strong></td>
<td><code>compute.googleapis.com</code></td>
<td>Compute Engine API for VM networking and SSH metadata</td>
</tr>
<tr>
<td><strong>IAM role</strong></td>
<td><code>roles/hypercomputecluster.editor</code></td>
<td>Creates and manages <code>MLRun</code> resources and grants UI access (displayed as <strong>Cluster Director Editor</strong> in the Google Cloud console)</td>
</tr>
<tr>
<td><strong>IAM role</strong></td>
<td><code>roles/logging.logWriter</code></td>
<td>Writes workload configurations and metrics to Cloud Logging</td>
</tr>
<tr>
<td><strong>IAM role</strong></td>
<td><code>roles/storage.objectUser</code></td>
<td>Uploads and reads XProf profile traces in Cloud Storage</td>
</tr>
</tbody>
</table>
</div><h3><a name="p-989794-h-1-enable-required-apis-3" class="anchor" href="https://discuss.google.dev#p-989794-h-1-enable-required-apis-3" aria-label="Heading link"></a>1. Enable required APIs</h3>
<p>Enable the required services in your Google Cloud project:</p>
<pre data-code-wrap="bash"><code class="lang-bash">gcloud services enable hypercomputecluster.googleapis.com tpu.googleapis.com compute.googleapis.com
</code></pre>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/memo.png?v=15" title=":memo:" class="emoji" alt=":memo:" loading="lazy" width="20" height="20"> <strong>Note:</strong> The <code>hypercomputecluster.googleapis.com</code> API powers <code>MLRun</code> registration, telemetry ingestion, and the console UI. You do <strong>not</strong> need the <a href="https://cloud.google.com/cluster-director/docs/overview" rel="noopener nofollow ugc">Cluster Director product</a> to manage your clusters—ML Diagnostics works independently with standalone Cloud TPU VMs and Google Kubernetes Engine (GKE). See the <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/overview#cluster-director" rel="noopener nofollow ugc">official overview</a> for details.</p>
</blockquote>
<h4><a name="p-989794-api-enablement-in-the-console-4" class="anchor" href="https://discuss.google.dev#p-989794-api-enablement-in-the-console-4" aria-label="Heading link"></a>API enablement in the console</h4>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/b/3/5/b3526ee875976f63a2875e6515439e11c1a3ea15.png" data-download-href="/uploads/short-url/pAm4VZ7ene6CKNOX6BI3o47nOzr.png?dl=1" title="API enablement in the Google Cloud console" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/3/5/b3526ee875976f63a2875e6515439e11c1a3ea15_2_690x479.png" alt="API enablement in the Google Cloud console" data-base62-sha1="pAm4VZ7ene6CKNOX6BI3o47nOzr" width="690" height="479" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/3/5/b3526ee875976f63a2875e6515439e11c1a3ea15_2_690x479.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/3/5/b3526ee875976f63a2875e6515439e11c1a3ea15_2_1035x718.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/3/5/b3526ee875976f63a2875e6515439e11c1a3ea15_2_1380x958.png 2x" data-dominant-color="F6F7F8"></a></div><p></p>
<h3><a name="p-989794-h-2-enable-log-analytics-on-cloud-logging-5" class="anchor" href="https://discuss.google.dev#p-989794-h-2-enable-log-analytics-on-cloud-logging-5" aria-label="Heading link"></a>2. Enable Log Analytics on Cloud Logging</h3>
<p>The Run Diagnostics dashboard uses <a href="https://cloud.google.com/logging/docs/analyze/query-and-view" rel="noopener nofollow ugc">Log Analytics</a> to render interactive time-series charts for model and system metrics. Upgrade your <code>_Default</code> log bucket before running your workload (Log Analytics does not backfill historical logs):</p>
<pre data-code-wrap="bash"><code class="lang-bash">gcloud logging buckets update _Default --location=global --enable-analytics --project=YOUR_PROJECT_ID
</code></pre>
<h3><a name="p-989794-h-3-set-up-a-service-account-and-cloud-storage-bucket-6" class="anchor" href="https://discuss.google.dev#p-989794-h-3-set-up-a-service-account-and-cloud-storage-bucket-6" aria-label="Heading link"></a>3. Set up a service account and Cloud Storage bucket</h3>
<p>Create a dedicated service account for your Cloud TPU VM and a <a href="https://cloud.google.com/storage/docs/creating-buckets" rel="noopener nofollow ugc">Cloud Storage bucket</a> to store XProf trace files:</p>
<ol>
<li>
<p><strong>Create a service account</strong>:</p>
<pre data-code-wrap="bash"><code class="lang-bash">gcloud iam service-accounts create diagon-walkthrough-sa --display-name "ML Diagnostics Walkthrough Service Account"
</code></pre>
</li>
<li>
<p><strong>Grant required IAM roles</strong>:</p>
<pre data-code-wrap="bash"><code class="lang-bash">export PROJECT_ID=$(gcloud config get-value project)
export SA_EMAIL="diagon-walkthrough-sa@${PROJECT_ID}.iam.gserviceaccount.com"

for role in roles/hypercomputecluster.editor roles/logging.logWriter roles/storage.objectUser; do
  gcloud projects add-iam-policy-binding ${PROJECT_ID} --member="serviceAccount:${SA_EMAIL}" --role="$role"
done
</code></pre>
</li>
<li>
<p><strong>Create a Cloud Storage bucket</strong>:</p>
<pre data-code-wrap="bash"><code class="lang-bash">export BUCKET_NAME="${PROJECT_ID}-diagon-profiles"
gcloud storage buckets create gs://${BUCKET_NAME} --location=us-central1
</code></pre>
</li>
</ol>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/light_bulb.png?v=15" title=":light_bulb:" class="emoji" alt=":light_bulb:" loading="lazy" width="20" height="20"> <strong>Tip:</strong> If your organization restricts <code>roles/hypercomputecluster.editor</code>, create a custom IAM role with only the required <code>hypercomputecluster.machineLearningRuns.*</code> permissions. See the <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/overview#iam-permissions" rel="noopener nofollow ugc">ML Diagnostics IAM guide</a>.</p>
</blockquote>
<h2><a name="p-989794-step-1-provision-and-connect-to-your-cloud-tpu-vm-7" class="anchor" href="https://discuss.google.dev#p-989794-step-1-provision-and-connect-to-your-cloud-tpu-vm-7" aria-label="Heading link"></a>Step 1: Provision and connect to your Cloud TPU VM</h2>
<p>Provision a single-host <a href="https://docs.cloud.google.com/tpu/docs/v5e" rel="noopener nofollow ugc">Cloud TPU <code>v5e</code></a> VM (<code>v5litepod-4</code>) in <code>us-central1-a</code>, attaching your service account and enabling the <code>cloud-platform</code> OAuth scope:</p>
<pre data-code-wrap="bash"><code class="lang-bash">gcloud compute tpus tpu-vm create my-diagon-tpu \
  --zone=us-central1-a \
  --accelerator-type=v5litepod-4 \
  --version=v2-alpha-tpuv5-lite \
  --service-account=${SA_EMAIL} \
  --scopes=https://www.googleapis.com/auth/cloud-platform
</code></pre>
<p>Connect to your Cloud TPU VM over SSH:</p>
<pre data-code-wrap="bash"><code class="lang-bash">gcloud compute tpus tpu-vm ssh my-diagon-tpu --zone=us-central1-a
</code></pre>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/light_bulb.png?v=15" title=":light_bulb:" class="emoji" alt=":light_bulb:" loading="lazy" width="20" height="20"> <strong>Tip:</strong> If you encounter SSH timeouts or firewall blocks, see <a href="https://cloud.google.com/compute/docs/troubleshooting/troubleshooting-ssh" rel="noopener nofollow ugc">Troubleshooting SSH on Compute Engine</a>.</p>
</blockquote>
<h2><a name="p-989794-step-2-isolate-dependencies-with-venv-8" class="anchor" href="https://discuss.google.dev#p-989794-step-2-isolate-dependencies-with-venv-8" aria-label="Heading link"></a>Step 2: Isolate dependencies with venv</h2>
<p>Create and activate an isolated Python virtual environment (Python 3.10+ recommended):</p>
<pre data-code-wrap="bash"><code class="lang-bash">python3 -m venv diagon-sdk-env
source diagon-sdk-env/bin/activate
</code></pre>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/light_bulb.png?v=15" title=":light_bulb:" class="emoji" alt=":light_bulb:" loading="lazy" width="20" height="20"> <strong>Tip:</strong> If <code>python3 -m venv</code> fails with a missing <code>ensurepip</code> error on Debian or Ubuntu images, run <code>sudo apt-get update &amp;&amp; sudo apt-get install -y python3-venv</code>, or install packages in user space with <code>pip install --user</code>.</p>
</blockquote>
<h2><a name="p-989794-step-3-install-the-ml-diagnostics-sdk-and-jax-9" class="anchor" href="https://discuss.google.dev#p-989794-step-3-install-the-ml-diagnostics-sdk-and-jax-9" aria-label="Heading link"></a>Step 3: Install the ML Diagnostics SDK and JAX</h2>
<p>Install <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/sdk" rel="noopener nofollow ugc"><code>google-cloud-mldiagnostics</code></a> (version <strong>1.0.6 or higher</strong>), <a href="https://cloud.google.com/python/docs/reference/logging/latest" rel="noopener nofollow ugc"><code>google-cloud-logging</code></a>, and <a href="https://jax.readthedocs.io/en/latest/installation.html#google-cloud-tpu" rel="noopener nofollow ugc"><code>jax[tpu]</code></a>:</p>
<pre data-code-wrap="bash"><code class="lang-bash">pip install --upgrade pip
pip install "google-cloud-mldiagnostics&gt;=1.0.6" "jax[tpu]" google-cloud-logging \
  -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
</code></pre>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/light_bulb.png?v=15" title=":light_bulb:" class="emoji" alt=":light_bulb:" loading="lazy" width="20" height="20"> <strong>Tip:</strong> In production containers, pin exact versions of JAX (for example, <code>jax==0.4.35</code>) and the SDK (<code>google-cloud-mldiagnostics==1.0.6</code>) in your <code>requirements.txt</code> or Dockerfile for reproducible builds.</p>
</blockquote>
<h2><a name="p-989794-step-4-instrument-your-workload-10" class="anchor" href="https://discuss.google.dev#p-989794-step-4-instrument-your-workload-10" aria-label="Heading link"></a>Step 4: Instrument your workload</h2>
<p>Initializing <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/sdk#initialize-run" rel="noopener nofollow ugc"><code>machinelearning_run</code></a> registers your experiment with the ML Diagnostics control plane and automatically records software metadata (JAX version, XLA compiler flags) and hardware topology (TPU device type, slice count).</p>
<ul>
<li>Setting <code>log_system_metrics=True</code> streams fine-grained TPU hardware counters (<code>TPU TensorCore utilization</code>, <code>TPU duty cycle</code>, <code>HBM utilization</code>) every 10 seconds to <a href="https://cloud.google.com/logging/docs/overview" rel="noopener nofollow ugc">Cloud Logging</a>.</li>
<li>Wrapping critical sections in a programmatic <code>with xprof():</code> context manager captures cycle-accurate XProf hardware traces directly to your Cloud Storage bucket.</li>
</ul>
<p>Create a file named <code>test_workload.py</code> on your Cloud TPU VM:</p>
<pre data-code-wrap="python"><code class="lang-python">import time
import logging
import random
import jax
import jax.numpy as jnp
import google.cloud.logging
from google_cloud_mldiagnostics import machinelearning_run, metrics, xprof, metric_types

# 0. Route Python logs to Cloud Logging
logging_client = google.cloud.logging.Client()
logging_client.setup_logging()

# Initialize JAX distributed runtime (auto-detects multi-host TPU slices; safe no-op if single-host)
try:
    jax.distributed.initialize()
except Exception:
    pass
time.sleep(jax.process_index() * 5)  # Stagger multi-host startup to avoid contention

# 1. Initialize the machine learning run
run_name = f"tpu-v5e-walkthrough-run-{int(time.time())}"
my_run = machinelearning_run(
    name=run_name,
    run_group="tpu-getting-started",
    configs={"epochs": 30, "batch_size": 32, "precision": "bfloat16"},
    gcs_path="gs://YOUR_BUCKET_NAME/profiles",  # Replace with your Cloud Storage bucket name
    log_system_metrics=True,                    # Streams libTPU and host telemetry every 10 seconds
    project="YOUR_PROJECT_ID",                  # Replace with your Google Cloud project ID
    region="us-central1",                       # Region where MLRun metadata is stored
)

logging.info(f"MLRun created: {my_run.name} on Worker {jax.process_index()} (Devices: {jax.devices()})")

# Simulate a memory-bound attention block by allocating bfloat16 matrices on TPU HBM
key = jax.random.PRNGKey(42)
x = jax.random.normal(key, (4096, 4096), dtype=jnp.bfloat16)

# 2. Record training loop metrics and capture profiles
learning_rate = 0.001
total_steps = 30
for step in range(1, total_steps + 1):
    step_start = time.perf_counter()
    x = jnp.dot(x, x)
    x.block_until_ready()

    step_time = time.perf_counter() - step_start + random.uniform(0.05, 0.15)
    loss = 2.5 / step + random.uniform(-0.02, 0.02)
    accuracy = min(0.99, 0.50 + (step * 0.015))
    mfu_percent = min(95.0, 52.0 + (step * 0.5))  # MetricType.MFU expects percentage (0-100)

    # Batch record predefined MetricType keys and custom metrics
    metrics.record_metrics([
        {"metric_name": metric_types.MetricType.LOSS, "value": loss},
        {"metric_name": metric_types.MetricType.LEARNING_RATE, "value": learning_rate},
        {"metric_name": metric_types.MetricType.STEP_TIME, "value": step_time},
        {"metric_name": metric_types.MetricType.THROUGHPUT, "value": 32.0 / step_time},
        {"metric_name": metric_types.MetricType.MFU, "value": mfu_percent},
        {"metric_name": "ACCURACY", "value": accuracy},
    ], step=step)

    print(f"[Worker {jax.process_index()}] Step {step}/{total_steps} | Loss: {loss:.4f} | MFU: {mfu_percent:.1f}% | Step Time: {step_time:.3f}s")

    # 3. Capture a hardware performance profile programmatically at step 5
    if step == 5:
        print(f"[Worker {jax.process_index()}] Capturing programmatic XProf trace at step {step}...")
        with xprof():
            for _ in range(5):
                y = jnp.dot(x, x)
                y.block_until_ready()
            time.sleep(2)
        print(f"[Worker {jax.process_index()}] Programmatic profile uploaded to Cloud Storage! Training loop continuing...")

    learning_rate *= 0.95
    time.sleep(2)
</code></pre>
<p>Run the instrumented script:</p>
<pre data-code-wrap="bash"><code class="lang-bash">python3 test_workload.py
</code></pre>
<h3><a name="p-989794-practical-pro-tips-11" class="anchor" href="https://discuss.google.dev#p-989794-practical-pro-tips-11" aria-label="Heading link"></a>Practical pro tips</h3>
<ul>
<li><strong>Multi-host TPU slices</strong>: When running across multi-host TPU slices, stagger worker startup (<code>time.sleep(jax.process_index() * 5)</code>) and pass <code>run_workload_id="my-shared-run-id"</code> to <code>machinelearning_run()</code> so all workers group cleanly under a single unified run.</li>
<li><strong>Unique run names</strong>: Standalone Cloud TPU VMs require a unique <code>name</code> for each new run (such as appending <code>int(time.time())</code>), whereas GKE workloads automatically append timestamps via the injection webhook.</li>
</ul>
<h2><a name="p-989794-step-5-verify-results-in-the-console-12" class="anchor" href="https://discuss.google.dev#p-989794-step-5-verify-results-in-the-console-12" aria-label="Heading link"></a>Step 5: Verify results in the console</h2>
<p>Once your script runs, inspect your telemetry across Cloud Logging, Cloud Storage, and the Run Diagnostics dashboard. For full details on console features and CLI queries, see <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/view-runs" rel="noopener nofollow ugc"><strong>View machine learning runs with ML Diagnostics</strong></a>.</p>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/memo.png?v=15" title=":memo:" class="emoji" alt=":memo:" loading="lazy" width="20" height="20"> <strong>Note:</strong> While Steps 1–4 provision a single-host <code>v5litepod-4</code> VM for quick testing, the console screenshots below showcase a completed 4-host Cloud TPU v5e slice (<code>tpu-v5e-walkthrough-run-completed</code>, workers <code>t1v-n-fef2b8f2-w-0</code> through <code>w-3</code>) to illustrate how multi-host system metrics, per-worker Cloud Storage artifacts, and synchronized 4-host XProf timelines render across a full TPU slice.</p>
</blockquote>
<h3><a name="p-989794-h-1-check-cloud-logging-and-cloud-storage-13" class="anchor" href="https://discuss.google.dev#p-989794-h-1-check-cloud-logging-and-cloud-storage-13" aria-label="Heading link"></a>1. Check Cloud Logging and Cloud Storage</h3>
<ul>
<li><strong>Cloud Logging</strong>: Open <a href="https://console.cloud.google.com/logs" rel="noopener nofollow ugc"><strong>Logs Explorer</strong></a> and confirm the <code>MLRun created</code> entry alongside structured metric payloads under the <code>ml_diagnostics_metric</code> log stream.</li>
<li><strong>Cloud Storage</strong>: Browse to your profile bucket path (<code>gs://YOUR_BUCKET_NAME/.../plugins/profile/</code>) and verify that compressed multi-host XPlane trace files (<code>.xplane.pb</code>, <code>.trace.json.gz</code>, and <code>.op_stats_v2.pb</code>) were uploaded automatically for each TPU worker host alongside pre-indexed <code>.SSTABLE</code> cache files generated by Managed XProf:</li>
</ul>
<h4><a name="p-989794-cloud-storage-profile-artifacts-14" class="anchor" href="https://discuss.google.dev#p-989794-cloud-storage-profile-artifacts-14" aria-label="Heading link"></a>Cloud Storage profile artifacts</h4>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/0/a/6/0a65f8eaa544267eafb5be222e1d275b3da54f26.jpeg" data-download-href="/uploads/short-url/1tZfsKwNaxU1H3n3EfQwvTGzkTs.jpeg?dl=1" title="Cloud Storage profile artifacts" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/a/6/0a65f8eaa544267eafb5be222e1d275b3da54f26_2_690x481.jpeg" alt="Cloud Storage profile artifacts" data-base62-sha1="1tZfsKwNaxU1H3n3EfQwvTGzkTs" width="690" height="481" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/a/6/0a65f8eaa544267eafb5be222e1d275b3da54f26_2_690x481.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/a/6/0a65f8eaa544267eafb5be222e1d275b3da54f26_2_1035x721.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/a/6/0a65f8eaa544267eafb5be222e1d275b3da54f26_2_1380x962.jpeg 2x" data-dominant-color="F2F2F5"></a></div><p></p>
<h3><a name="p-989794-h-2-explore-the-run-diagnostics-dashboard-15" class="anchor" href="https://discuss.google.dev#p-989794-h-2-explore-the-run-diagnostics-dashboard-15" aria-label="Heading link"></a>2. Explore the Run Diagnostics dashboard</h3>
<p>Open the <strong>Run Diagnostics</strong> dashboard in the Google Cloud console via either navigation path:</p>
<ul>
<li><strong>Cluster Director console</strong>: <strong>Cluster Director &gt; Run Diagnostics</strong> (<a href="https://console.cloud.google.com/cluster-director/diagnostics" rel="noopener nofollow ugc">console.cloud.google.com/cluster-director/diagnostics</a>)</li>
<li><strong>GKE console</strong>: <strong>Kubernetes Engine &gt; AI/ML &gt; Run Diagnostics</strong> (<a href="https://console.cloud.google.com/kubernetes/aiml/diagnostics" rel="noopener nofollow ugc">console.cloud.google.com/kubernetes/aiml/diagnostics</a>)</li>
</ul>
<h4><a name="p-989794-runs-list-16" class="anchor" href="https://discuss.google.dev#p-989794-runs-list-16" aria-label="Heading link"></a>Runs list</h4>
<p>Compare all your machine learning runs side-by-side in the <strong>Runs</strong> table. Track run status (active in-progress spinner vs. completed checkmark), creation and update timestamps, hardware labels (<code>accelerator_type : tpu</code>), and direct <code>View profiles</code> shortcuts:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/6/8/8/688280b720d321a1315fa249f6344ff4379d1c82.png" data-download-href="/uploads/short-url/eUxfZgB64Bs8OTsQKKZ3kg3YemC.png?dl=1" title="Runs list in the Run Diagnostics dashboard" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/6/8/8/688280b720d321a1315fa249f6344ff4379d1c82_2_690x146.png" alt="Runs list in the Run Diagnostics dashboard" data-base62-sha1="eUxfZgB64Bs8OTsQKKZ3kg3YemC" width="690" height="146" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/6/8/8/688280b720d321a1315fa249f6344ff4379d1c82_2_690x146.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/6/8/8/688280b720d321a1315fa249f6344ff4379d1c82_2_1035x219.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/6/8/8/688280b720d321a1315fa249f6344ff4379d1c82_2_1380x292.png 2x" data-dominant-color="F5F4F6"></a></div><p></p>
<h4><a name="p-989794-run-details-17" class="anchor" href="https://discuss.google.dev#p-989794-run-details-17" aria-label="Heading link"></a>Run details</h4>
<p>Click your run (<code>tpu-v5e-walkthrough-run-completed</code>) to inspect the <strong>Details</strong> tab. Review run metadata (<code>Run group: tpu-getting-started</code>, <code>Orchestrator: GCE</code>), auto-attached SDK labels (<code>accelerator_type : tpu</code>, <code>diagon_sdk_version : 1-0-7</code>, <code>framework : jax</code>), and auto-collected software configurations (<code>libtpu_version: 0.0.17</code>, <code>framework: JAX</code>, <code>framework_version: 0.6.2</code>):</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/a/4/9/a495cc502807d7d085556aff04cbab1ae84d2589.png" data-download-href="/uploads/short-url/ntZfg0c9akkmV5xHZBkKIioCjpv.png?dl=1" title="Run details metadata and configurations" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/4/9/a495cc502807d7d085556aff04cbab1ae84d2589_2_690x445.png" alt="Run details metadata and configurations" data-base62-sha1="ntZfg0c9akkmV5xHZBkKIioCjpv" width="690" height="445" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/4/9/a495cc502807d7d085556aff04cbab1ae84d2589_2_690x445.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/4/9/a495cc502807d7d085556aff04cbab1ae84d2589_2_1035x667.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/4/9/a495cc502807d7d085556aff04cbab1ae84d2589_2_1380x890.png 2x" data-dominant-color="F9F7F7"></a></div><p></p>
<h4><a name="p-989794-model-metrics-18" class="anchor" href="https://discuss.google.dev#p-989794-model-metrics-18" aria-label="Heading link"></a>Model metrics</h4>
<p>Switch to the <strong>Model metrics</strong> tab to analyze training convergence curves side-by-side. Every metric recorded via <code>metrics.record_metrics()</code> (such as <code>Learning Rate</code> and <code>Loss</code>) is plotted both <strong>over Time</strong> (left column) and <strong>over Steps</strong> (right column). In this completed 42-step run, the charts capture schedule transitions including the initial linear warmup ramp (<code>0.0002</code> to <code>0.001</code> over steps 1–4), smooth exponential decay (<code>0.95x</code> per step over steps 4–42), and monotonic loss reduction (<code>2.5</code> down to <code>0.38</code>):</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/a/0/5/a05a98f4413f87f0cc5cca00683bb7d3ff010212.png" data-download-href="/uploads/short-url/mSyuXXYbuQnZKzxsyXGPMGAKH1o.png?dl=1" title="Model metrics convergence charts" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/0/5/a05a98f4413f87f0cc5cca00683bb7d3ff010212_2_690x377.png" alt="Model metrics convergence charts" data-base62-sha1="mSyuXXYbuQnZKzxsyXGPMGAKH1o" width="690" height="377" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/0/5/a05a98f4413f87f0cc5cca00683bb7d3ff010212_2_690x377.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/0/5/a05a98f4413f87f0cc5cca00683bb7d3ff010212_2_1035x565.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/a/0/5/a05a98f4413f87f0cc5cca00683bb7d3ff010212_2_1380x754.png 2x" data-dominant-color="FBF8F9"></a></div><p></p>
<h4><a name="p-989794-performance-metrics-19" class="anchor" href="https://discuss.google.dev#p-989794-performance-metrics-19" aria-label="Heading link"></a>Performance metrics</h4>
<p>Open the <strong>Performance metrics</strong> tab to track training speed and stability. Interactive charts for <code>Step Time (in seconds)</code> and <code>Throughput (per second)</code> are plotted over Time and over Steps, with automatic <strong>Mean</strong> and <strong>StdDev</strong> dashed horizontal reference lines that highlight step-time jitter at a glance:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/4/5/0/4505d831422d6e0ce30961542ee472dc2723a94e.png" data-download-href="/uploads/short-url/9QBsY6gWWJzArGVkC0aUvYwI5dQ.png?dl=1" title="Performance metrics step time and throughput charts" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/5/0/4505d831422d6e0ce30961542ee472dc2723a94e_2_690x377.png" alt="Performance metrics step time and throughput charts" data-base62-sha1="9QBsY6gWWJzArGVkC0aUvYwI5dQ" width="690" height="377" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/5/0/4505d831422d6e0ce30961542ee472dc2723a94e_2_690x377.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/5/0/4505d831422d6e0ce30961542ee472dc2723a94e_2_1035x565.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/5/0/4505d831422d6e0ce30961542ee472dc2723a94e_2_1380x754.png 2x" data-dominant-color="F9F5F6"></a></div><p></p>
<h4><a name="p-989794-system-metrics-20" class="anchor" href="https://discuss.google.dev#p-989794-system-metrics-20" aria-label="Heading link"></a>System metrics</h4>
<p>Select the <strong>System metrics</strong> tab to inspect fine-grained hardware counters streamed every 10 seconds across all TPU hosts in your slice (<code>t1v-n-fef2b8f2-w-0</code> through <code>w-3</code>). Correlate per-host <code>Top 5 TPU Duty Cycle (%)</code> (peaking at <code>100%</code> during active matrix multiplications), <code>Top 5 TPU TensorCore Utilization (%)</code> (peaking around <code>~2.8%</code> for this lightweight synthetic benchmark), <code>Top 5 HBM Utilization (%)</code> (<code>~41%</code> peak), and <code>Top 5 Host CPU Utilization (%)</code> against Mean and StdDev baselines:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/c/2/d/c2db565f62a69347efa6965fb90390c7dc70dc3c.png" data-download-href="/uploads/short-url/rNMyyTlbAkGEEQUvwV2wAhlA3xy.png?dl=1" title="System metrics multi-host TPU utilization charts" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/2/d/c2db565f62a69347efa6965fb90390c7dc70dc3c_2_690x380.png" alt="System metrics multi-host TPU utilization charts" data-base62-sha1="rNMyyTlbAkGEEQUvwV2wAhlA3xy" width="690" height="380" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/2/d/c2db565f62a69347efa6965fb90390c7dc70dc3c_2_690x380.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/2/d/c2db565f62a69347efa6965fb90390c7dc70dc3c_2_1035x570.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/2/d/c2db565f62a69347efa6965fb90390c7dc70dc3c_2_1380x760.png 2x" data-dominant-color="F6F2F5"></a></div><p></p>
<h4><a name="p-989794-captured-profiles-programmatic-xprof-capture-21" class="anchor" href="https://discuss.google.dev#p-989794-captured-profiles-programmatic-xprof-capture-21" aria-label="Heading link"></a>Captured profiles (programmatic XProf capture)</h4>
<p>The <strong>Profiles</strong> tab lists every profile session captured programmatically during the run via <code>with xprof():</code> (such as <code>2026_09_12_10_36_04</code>), displaying capture timestamps and tracer levels (<code>Host tracer level: Info</code>, <code>Device tracer level: Enabled</code>). Click any session link to launch the interactive Managed XProf Trace Viewer directly in your browser:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/5/f/5/5f5031b8e2222588e1203b0e9b3f8a2babbf131d.png" data-download-href="/uploads/short-url/dBbaQP6Ju3QsNGBCXpFhnvKhfhb.png?dl=1" title="Captured profiles list in Run Diagnostics" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/f/5/5f5031b8e2222588e1203b0e9b3f8a2babbf131d_2_690x281.png" alt="Captured profiles list in Run Diagnostics" data-base62-sha1="dBbaQP6Ju3QsNGBCXpFhnvKhfhb" width="690" height="281" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/f/5/5f5031b8e2222588e1203b0e9b3f8a2babbf131d_2_690x281.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/f/5/5f5031b8e2222588e1203b0e9b3f8a2babbf131d_2_1035x421.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/f/5/5f5031b8e2222588e1203b0e9b3f8a2babbf131d_2_1380x562.png 2x" data-dominant-color="F4F0F1"></a></div><p></p>
<blockquote>
<p><img src="https://emoji.discourse-cdn.com/noto/memo.png?v=15" title=":memo:" class="emoji" alt=":memo:" loading="lazy" width="20" height="20"> <strong>Note:</strong> On standalone Cloud TPU VMs, profile sessions are captured programmatically in your script using the <code>with xprof():</code> context manager. Live UI-triggered profiling (<strong><code>+ Capture new profile session</code></strong>) is supported on <strong>GKE clusters</strong> (covered in Part 2).</p>
</blockquote>
<h4><a name="p-989794-managed-xprof-trace-viewer-22" class="anchor" href="https://discuss.google.dev#p-989794-managed-xprof-trace-viewer-22" aria-label="Heading link"></a>Managed XProf trace viewer</h4>
<p>Clicking any profile session link opens the <strong>Managed XProf Trace Viewer</strong> (<code>XProf v2.23.1</code>) directly in your browser. Powered by a distributed worker-aggregator backend, Managed XProf loads multi-gigabyte multi-host TPU traces <strong>up to 10x faster</strong> than self-hosted TensorBoard servers (~1.7 minutes vs. 17 minutes for an 8-host 1.4GB profile) and enables instant link sharing across your team:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/2/8/c/28cbf533a8508f5fa67fcabec3b5277a464ead0b.png" data-download-href="/uploads/short-url/5OU4JNCmFrbtv4gEvRcAmrZzTm3.png?dl=1" title="Managed XProf trace viewer timeline" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/8/c/28cbf533a8508f5fa67fcabec3b5277a464ead0b_2_690x372.png" alt="Managed XProf trace viewer timeline" data-base62-sha1="5OU4JNCmFrbtv4gEvRcAmrZzTm3" width="690" height="372" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/8/c/28cbf533a8508f5fa67fcabec3b5277a464ead0b_2_690x372.png, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/8/c/28cbf533a8508f5fa67fcabec3b5277a464ead0b_2_1035x558.png 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/8/c/28cbf533a8508f5fa67fcabec3b5277a464ead0b_2_1380x744.png 2x" data-dominant-color="E9E9F3"></a></div><p></p>
<p>Inside Managed XProf, switch between all 4 TPU hosts (<code>Hosts (4)</code>) and 10 profiling tools (<code>Tools (10)</code>) to pinpoint hardware bottlenecks:</p>
<ul>
<li><a href="https://openxla.org/xprof" rel="noopener nofollow ugc"><strong>Trace Viewer</strong></a>: Inspect a cycle-accurate timeline of host CPU PJRT dispatch threads (<code>host:CPU</code>), TPU TensorCore execution streams across chips (<code>device:TPU:0</code> through <code>device:TPU:3</code>), XLA High-Level Optimizer (HLO) modules (<code>XLA Modules</code>, <code>XLA Ops</code>, <code>XLA TraceMe</code>), and framework operations.</li>
<li><a href="https://openxla.org/xprof" rel="noopener nofollow ugc"><strong>Roofline Analysis</strong></a>: Identify whether operations are memory-bound or compute-bound based on operational intensity (<code>FLOPs/Byte</code>) vs. achieved <code>TFLOPs/s</code>.</li>
<li><a href="https://openxla.org/xprof" rel="noopener nofollow ugc"><strong>Memory Viewer</strong></a>: Track High Bandwidth Memory (HBM) usage over time and inspect exact tensor buffer shapes at peak memory allocation to resolve Out-Of-Memory (OOM) errors.</li>
</ul>
<h2><a name="p-989794-conclusion-23" class="anchor" href="https://discuss.google.dev#p-989794-conclusion-23" aria-label="Heading link"></a>Conclusion</h2>
<p>In just a few minutes, you provisioned a Cloud TPU VM, instrumented a JAX workload with the Google Cloud ML Diagnostics SDK, streamed real-time hardware telemetry to Cloud Logging, and analyzed TPU execution traces in the zero-cost Managed XProf viewer.</p>
<p>Ready to try it on your own models? Replace the synthetic loop in <code>test_workload.py</code> with your actual JAX training step to start profiling your Cloud TPU workloads today. If you have questions or run into issues setting this up, drop a comment below!</p>
<h3><a name="p-989794-whats-next-scaling-diagnostics-to-gke-clusters-24" class="anchor" href="https://discuss.google.dev#p-989794-whats-next-scaling-diagnostics-to-gke-clusters-24" aria-label="Heading link"></a>What’s next: Scaling diagnostics to GKE clusters</h3>
<p>While standalone Cloud TPU VMs are ideal for interactive prototyping and single-slice workloads, large-scale foundation model training often spans multi-slice TPU clusters orchestrated by <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/tpus" rel="noopener nofollow ugc"><strong>Google Kubernetes Engine (GKE)</strong></a>.</p>
<p>In <strong>Part 2</strong> of this series, we will cover using <strong>ML Diagnostics with GKE clusters</strong> (including one-command cluster setup via <code>xpk cluster create --managed-mldiagnostics</code>), featuring:</p>
<ul>
<li><strong>Live UI-triggered on-demand profiling</strong>: Trigger interactive multi-host XProf trace sessions on the fly directly from the Google Cloud console (<code>+ Capture new profile session</code>) without modifying training code or restarting jobs.</li>
<li><strong>Automated GKE workload correlation</strong>: Automatically map TPU slices and GKE pods to Kubernetes <code>JobSet</code> and <code>LeaderWorkerSet</code> hierarchies via the ML Diagnostics GKE webhook.</li>
<li><strong>Multi-slice observability</strong>: Stream cluster-wide TPU duty cycle, TensorCore utilization, and HBM telemetry across multi-host GKE workloads in the Run Diagnostics dashboard.</li>
</ul>
<h2><a name="p-989794-resources-and-further-reading-25" class="anchor" href="https://discuss.google.dev#p-989794-resources-and-further-reading-25" aria-label="Heading link"></a>Resources and further reading</h2>
<ul>
<li><strong>ML Diagnostics Platform Overview</strong>: <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/overview" rel="noopener nofollow ugc">Cloud TPU ML Diagnostics Overview</a></li>
<li><strong>ML Diagnostics SDK Guide</strong>: <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/sdk" rel="noopener nofollow ugc">Get started with the ML Diagnostics SDK</a></li>
<li><strong>Viewing ML Runs &amp; Dashboard Guide</strong>: <a href="https://docs.cloud.google.com/tpu/docs/ml-diagnostics/view-runs" rel="noopener nofollow ugc">View machine learning runs with ML Diagnostics</a></li>
<li><strong>Cloud TPU v5e Architecture &amp; Guide</strong>: <a href="https://docs.cloud.google.com/tpu/docs/v5e" rel="noopener nofollow ugc">Cloud TPU v5e Documentation</a></li>
<li><strong>Google I/O 2025 Technical Session</strong>: <a href="https://io.google/2025/explore/technical-session-30" rel="noopener nofollow ugc">Supercharge ML performance on xPUs with XProf</a></li>
<li><strong>ML Diagnostics SDK GitHub Repository</strong>: <a href="https://github.com/AI-Hypercomputer/google-cloud-mldiagnostics" rel="noopener nofollow ugc">AI-Hypercomputer/google-cloud-mldiagnostics</a></li>
<li><strong>ML Diagnostics SDK on PyPI</strong>: <a href="https://pypi.org/project/google-cloud-mldiagnostics/" rel="noopener nofollow ugc">google-cloud-mldiagnostics</a></li>
<li><strong>OpenXLA XProf Documentation</strong>: <a href="https://openxla.org/xprof" rel="noopener nofollow ugc">openxla.org/xprof</a></li>
<li><strong>JAX Documentation</strong>: <a href="https://docs.jax.dev/" rel="noopener nofollow ugc">docs.jax.dev</a></li>
<li><strong>TensorBoard Profiler Guide</strong>: <a href="https://www.tensorflow.org/tensorboard" rel="noopener nofollow ugc">tensorflow.org/tensorboard</a></li>
</ul>
            <p><small>1 post - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/zero-infrastructure-managed-xprof-profiling-ml-workloads-on-cloud-tpu-with-ml-diagnostics/397203">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/zero-infrastructure-managed-xprof-profiling-ml-workloads-on-cloud-tpu-with-ml-diagnostics/397203</link>
          <pubDate>Mon, 14 Sep 2026 20:32:30 +0000</pubDate>
          <discourse:topicPinned>Yes</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397203</guid>
          <source url="https://discuss.google.dev/t/zero-infrastructure-managed-xprof-profiling-ml-workloads-on-cloud-tpu-with-ml-diagnostics/397203.rss">Zero-infrastructure managed XProf: Profiling ML workloads on Cloud TPU with ML Diagnostics</source>
        </item>
        <item>
          <title>Are TPU power metrics available on v6e</title>
          <dc:creator><![CDATA[Winnie]]></dc:creator>
          <category>TPUs</category>
          <description><![CDATA[
            <p>I’m trying to collect power consumption metrics from a v6e TPU VM created through the Cloud TPU API.</p>
<p>The <a href="https://docs.cloud.google.com/monitoring/api/metrics_gcp_c#compute" rel="noopener nofollow ugc">Cloud Monitoring metrics documentation</a> lists these metrics as BETA:</p>
<pre><code class="lang-auto">compute.googleapis.com/instance/tpu/accelerator/power_draw
compute.googleapis.com/instance/tpu/accelerator/hbm_power_draw
compute.googleapis.com/instance/tpu/accelerator/tray_power
</code></pre>
<p>I queried the Cloud Monitoring <code>projects.timeSeries.list</code> API for the past 48 hours, using a filter like this:</p>
<pre><code class="lang-auto">metric.type="compute.googleapis.com/instance/tpu/accelerator/power_draw"
AND resource.type="gce_instance"
AND resource.labels.instance_id="&lt;INSTANCE_ID&gt;"
</code></pre>
<p>The request succeeds with <strong>HTTP 200</strong>, but returns no time series or data points for any of these three metrics. For comparison, I can retrieve <code>tpu.googleapis.com/accelerator/duty_cycle</code> data for the same TPU.</p>
<p>Could someone clarify whether:</p>
<ul>
<li>There is a problem with my query or resource filter;</li>
<li>These power metrics are not yet available for TPU VMs created through the Cloud TPU API;</li>
<li>Additional configuration is required?</li>
</ul>
<p>My goal is to measure TPU power consumption during inference. If these metrics are not currently supported on this deployment, is there another supported way to obtain that measurement?</p>
<p>Thank you!</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/are-tpu-power-metrics-available-on-v6e/397202">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/are-tpu-power-metrics-available-on-v6e/397202</link>
          <pubDate>Mon, 14 Sep 2026 20:18:53 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397202</guid>
          <source url="https://discuss.google.dev/t/are-tpu-power-metrics-available-on-v6e/397202.rss">Are TPU power metrics available on v6e</source>
        </item>
        <item>
          <title>Building enterprise AI agents with ADK and the Gmail MCP Server</title>
          <dc:creator><![CDATA[Gary_Wang]]></dc:creator>
          <category>Community Articles</category>
          <description><![CDATA[
            <p>Authors: <a class="mention" href="https://discuss.google.dev/u/gary_wang">@Gary_Wang</a>  <a class="mention" href="https://discuss.google.dev/u/constance_li">@Constance_Li</a></p>
<p><strong>Early Access Notice:</strong> In order to get early access to certain features and managed endpoints of the Gmail MCP server (`<a href="https://gmailmcp.googleapis.com/mcp/v1%5C%60" rel="noopener nofollow ugc">https://gmailmcp.googleapis.com/mcp/v1\`</a>), apply to join the <a href="https://developers.google.com/workspace/preview" rel="noopener nofollow ugc">Google Workspace Developer Preview Program</a>.</p>
<h2><a name="p-989785-introduction-1" class="anchor" href="https://discuss.google.dev#p-989785-introduction-1" aria-label="Heading link"></a>Introduction</h2>
<p>Have you ever tried building an autonomous AI agent to triage customer inboxes, summarize urgent email threads, or draft responses, only to spend days writing brittle REST API wrappers and wrestling with token refresh edge cases?</p>
<p>Connecting Large Language Models (LLMs) to enterprise communication hubs like <strong>Google Workspace</strong> and <strong>Gmail</strong> is one of the highest-value opportunities for generative AI automation. However, enterprise developers often face two fundamental roadblocks:</p>
<ol>
<li>
<p><strong>Tool orchestration overhead:</strong> How do models discover and reliably call email actions without maintaining custom function schemas?</p>
</li>
<li>
<p><strong>Enterprise identity and delegation:</strong> How to securely authenticate interactive user-facing assistants versus headless 24/7 background worker bots across one or many mailboxes?</p>
</li>
</ol>
<p>In this post, we explore how to build production-grade Gmail agents using the <strong>Google Agent Development Kit (ADK)</strong> and the managed <strong>Model Context Protocol (MCP)</strong> endpoint. We’ll walk through two distinct authentication architectures—<strong>OAuth 2.0 User Consent</strong> and <strong>Service Account Domain-Wide Delegation (DWD)</strong>—and share a blueprint for deploying on <strong>Google Cloud Run</strong>.</p>
<hr>
<h2><a name="p-989785-the-architectural-shift-why-mcp-and-google-adk-2" class="anchor" href="https://discuss.google.dev#p-989785-the-architectural-shift-why-mcp-and-google-adk-2" aria-label="Heading link"></a>The architectural shift: Why MCP and Google ADK?</h2>
<p>Historically, integrating Gemini with Google Workspace APIs meant manually crafting OpenAPI specs or Python function-calling dictionaries for every Gmail endpoint, along with custom error handling, schema serialization, and pagination logic.</p>
<p>The <strong>Model Context Protocol (MCP)</strong> standardizes how AI applications connect to external tools and data sources. Google Workspace now provides managed, remote Streamable HTTP MCP endpoints such as <code>https://gmailmcp.googleapis.com/mcp/v1</code>.</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/5/1/f/51fe45cf98438a6f0fa33d36dc7dcf7fc1d90605.jpeg" data-download-href="/uploads/short-url/bHls0UOdNhU1fELahIM3dofUIux.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/1/f/51fe45cf98438a6f0fa33d36dc7dcf7fc1d90605_2_267x500.jpeg" alt="image" data-base62-sha1="bHls0UOdNhU1fELahIM3dofUIux" width="267" height="500" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/1/f/51fe45cf98438a6f0fa33d36dc7dcf7fc1d90605_2_267x500.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/1/f/51fe45cf98438a6f0fa33d36dc7dcf7fc1d90605_2_400x750.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/5/1/f/51fe45cf98438a6f0fa33d36dc7dcf7fc1d90605_2_534x1000.jpeg 2x" data-dominant-color="F3F3F5"></a></div><p></p>
<h3><a name="p-989785-key-benefits-of-this-architecture-3" class="anchor" href="https://discuss.google.dev#p-989785-key-benefits-of-this-architecture-3" aria-label="Heading link"></a>Key benefits of this architecture</h3>
<ul>
<li><strong>Standardized JSON-RPC 2.0 discovery:</strong> The agent queries available tools (such as <code>list_threads</code>, <code>get_message</code>, <code>send_message</code>, and <code>modify_labels</code>) dynamically via <code>tools/list</code>.</li>
<li><strong>Zero custom tool wrappers:</strong> No need to hand-code parameter parsing or function schemas for the LLM.</li>
<li><strong>Native ADK toolset integration:</strong> Google ADK’s <code>McpToolset</code> class connects Gemini models to remote Streamable HTTP MCP endpoints with just a few lines of configuration.</li>
</ul>
<hr>
<h2><a name="p-989785-choosing-between-interactive-user-flow-and-service-account-domain-wide-delegation-dwd-4" class="anchor" href="https://discuss.google.dev#p-989785-choosing-between-interactive-user-flow-and-service-account-domain-wide-delegation-dwd-4" aria-label="Heading link"></a>Choosing between interactive user flow and service account Domain-wide Delegation (DWD)</h2>
<p>The most critical architectural decision when designing an enterprise email agent is <strong>identity and credential delegation</strong>. Here we list two options that can be used for this purpose:</p>
<h3><a name="p-989785-authentication-comparison-matrix-5" class="anchor" href="https://discuss.google.dev#p-989785-authentication-comparison-matrix-5" aria-label="Heading link"></a>Authentication comparison matrix</h3>
<blockquote>
<p>[!NOTE]<br>
Enterprise compliance note: Because the Service Account DWD pattern and internal OAuth client flows are scoped strictly to your organization’s Google Workspace domain, they are exempt from Google’s public OAuth app verification and external CASA Tier 2/3 assessments. The organization’s Workspace Super Admin maintains full sovereign control over which scopes are authorized via the Google Workspace Admin console.</p>
</blockquote>
<div class="md-table">
<table>
<thead>
<tr>
<th style="text-align:left">Feature / Dimension</th>
<th style="text-align:left">Option 1: Interactive User Flow</th>
<th style="text-align:left">Option 2: Service Account DWD</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><strong>Primary Identity</strong></td>
<td style="text-align:left">End user’s Google Account</td>
<td style="text-align:left">Service Account impersonating a target Workspace user</td>
</tr>
<tr>
<td style="text-align:left"><strong>Personal <code>@gmail.com</code> Support</strong></td>
<td style="text-align:left"><strong>Yes</strong></td>
<td style="text-align:left"><strong>No</strong> (Google Workspace domains only)</td>
</tr>
<tr>
<td style="text-align:left"><strong>Workspace <code>@domain.com</code> Support</strong></td>
<td style="text-align:left"><strong>Yes</strong></td>
<td style="text-align:left"><strong>Yes</strong></td>
</tr>
<tr>
<td style="text-align:left"><strong>User Sign-in Prompt Required?</strong></td>
<td style="text-align:left"><strong>Yes</strong> (One-time interactive browser consent)</td>
<td style="text-align:left"><strong>No</strong> (100% Headless &amp; automated)</td>
</tr>
<tr>
<td style="text-align:left"><strong>Workspace Admin Approval Needed?</strong></td>
<td style="text-align:left"><strong>No</strong> (Unless organization restricts 3rd party apps)</td>
<td style="text-align:left"><strong>Yes</strong> (Super Admin authorization in <code>admin.google.com</code>)</td>
</tr>
<tr>
<td style="text-align:left"><strong>Server Token Storage</strong></td>
<td style="text-align:left">Must store per-user Refresh Tokens (Secret Manager / DB)</td>
<td style="text-align:left"><strong>No user refresh tokens needed</strong> (Dynamic ADC token minting)</td>
</tr>
<tr>
<td style="text-align:left"><strong>Security Scope</strong></td>
<td style="text-align:left">User grants access strictly to their own inbox</td>
<td style="text-align:left">Admin delegates authority across specified domain scopes</td>
</tr>
<tr>
<td style="text-align:left"><strong>Best Production Use Case</strong></td>
<td style="text-align:left">Multi-tenant SaaS apps, interactive user-facing assistants</td>
<td style="text-align:left">Headless triage bots, 24/7 enterprise background workflows</td>
</tr>
</tbody>
</table>
</div><hr>
<h2><a name="p-989785-step-by-step-implementation-6" class="anchor" href="https://discuss.google.dev#p-989785-step-by-step-implementation-6" aria-label="Heading link"></a>Step-by-step implementation</h2>
<p>Let’s walk through configuring both methods, solving the token refresh challenge, and implementing the agents in Python.</p>
<h3><a name="p-989785-h-1-required-oauth-scopes-7" class="anchor" href="https://discuss.google.dev#p-989785-h-1-required-oauth-scopes-7" aria-label="Heading link"></a>1. Required OAuth scopes</h3>
<p>When connecting generative AI models to enterprise communication hubs, the fundamental security principle is least privilege. We intentionally configure our scopes to use gmail.compose rather than gmail.send for security concerns.</p>
<pre data-code-wrap="python"><code class="lang-python">SCOPES = [
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/gmail.modify",
    "https://www.googleapis.com/auth/gmail.compose", # Draft-only (Recommended)# 
    "https://www.googleapis.com/auth/gmail.labels",
]
</code></pre>
<h4><a name="p-989785-why-you-should-avoid-granting-direct-gmailsend-to-llms-8" class="anchor" href="https://discuss.google.dev#p-989785-why-you-should-avoid-granting-direct-gmailsend-to-llms-8" aria-label="Heading link"></a>Why you should avoid granting direct gmail.send to LLMs</h4>
<ol>
<li>Indirect prompt injection: Untrusted inbound emails could hijack the model into sending unauthorized outbound emails.</li>
<li>Irreversibility and brand liability: Sent emails cannot be recalled; hallucinations create instant damage.</li>
<li>Restricted OAuth compliance: Minimizes enterprise blast radius.</li>
</ol>
<p>The recommended pattern is “agent drafts, human approves”, which implements a human-in-the-loop workflow using create_draft and review labels.</p>
<hr>
<h3><a name="p-989785-h-2-setting-up-option-1-interactive-user-flow-9" class="anchor" href="https://discuss.google.dev#p-989785-h-2-setting-up-option-1-interactive-user-flow-9" aria-label="Heading link"></a>2. Setting up option 1: Interactive user flow</h3>
<p>Option 1 is ideal when building interactive assistants where end users grant access to their individual accounts. Refer to <a href="https://codelabs.developers.google.com/google-workspace-mcp-adk" rel="noopener nofollow ugc">Google Workspace MCP &amp; ADK Codelab</a> for a step-by-step guide on how to set up Option 1.</p>
<h4><a name="p-989785-gcp-console-setup-10" class="anchor" href="https://discuss.google.dev#p-989785-gcp-console-setup-10" aria-label="Heading link"></a>GCP Console setup:</h4>
<ol>
<li>In the <a href="https://console.cloud.google.com/apis/credentials" rel="noopener nofollow ugc">Google Cloud Console Credentials Page</a>, configure the <strong>OAuth consent screen</strong> (Internal or External).</li>
<li>Create an <strong>OAuth 2.0 Client ID</strong> (select <em>Desktop App</em> for local testing or <em>Web Application</em> for production).</li>
<li>Save the <strong>Client ID</strong> and <strong>Client Secret</strong> in <code>.env</code>.</li>
</ol>
<pre data-code-wrap="env"><code class="lang-env">GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=your_project_id
GOOGLE_CLOUD_LOCATION=us-central1
OAUTH_CLIENT_ID=your_client_id.apps.googleusercontent.com
OAUTH_CLIENT_SECRET=your_client_secret
</code></pre>
<h4><a name="p-989785-running-interactive-authorization-11" class="anchor" href="https://discuss.google.dev#p-989785-running-interactive-authorization-11" aria-label="Heading link"></a>Running interactive authorization:</h4>
<p>Run the following <code>auth.py</code> to trigger the local consent flow and store the authorized credentials in <code>token.json</code> and Application Default Credentials (ADC):</p>
<pre data-code-wrap="python"><code class="lang-python"># auth.py
import json, os
from google_auth_oauthlib.flow import InstalledAppFlow

def run_oauth_flow():
    client_config = {
        "installed": {
            "client_id": os.environ["OAUTH_CLIENT_ID"],
            "client_secret": os.environ["OAUTH_CLIENT_SECRET"],
            "auth_uri": "https://accounts.google.com/o/oauth2/auth",
            "token_uri": "https://oauth2.googleapis.com/token",
        }
    }
    flow = InstalledAppFlow.from_client_config(client_config, scopes=SCOPES)
    creds = flow.run_local_server(port=0)

    cred_dict = json.loads(creds.to_json())
    cred_dict["type"] = "authorized_user"
    cred_dict["quota_project_id"] = os.environ.get("GOOGLE_CLOUD_PROJECT")

    with open("token.json", "w") as f:
        json.dump(cred_dict, f, indent=2)
    return creds
</code></pre>
<hr>
<h3><a name="p-989785-h-3-setting-up-option-2-service-account-domain-wide-delegation-dwd-12" class="anchor" href="https://discuss.google.dev#p-989785-h-3-setting-up-option-2-service-account-domain-wide-delegation-dwd-12" aria-label="Heading link"></a>3. Setting up option 2: Service account domain-wide delegation (DWD)</h3>
<p>Option 2 allows headless background workers to interact with inboxes on behalf of domain users without any interactive login prompts.</p>
<h4><a name="p-989785-step-1-create-a-service-account-in-gcp-console-13" class="anchor" href="https://discuss.google.dev#p-989785-step-1-create-a-service-account-in-gcp-console-13" aria-label="Heading link"></a>Step 1: Create a Service Account in GCP Console</h4>
<ol>
<li>Navigate to <strong>IAM &amp; Admin</strong> &gt; <strong>Service Accounts</strong> and create a Service Account (e.g., <code>sa-workspace-agent</code>).</li>
<li>Copy the <strong>21-digit Numeric Client ID</strong> (OAuth2 Unique ID) from the service account details.</li>
<li>Grant your caller principal or runtime identity the <strong>Service Account Token Creator</strong> (<code>roles/iam.serviceAccountTokenCreator</code>) role.</li>
</ol>
<h4><a name="p-989785-step-2-authorize-scopes-in-google-workspace-admin-console-14" class="anchor" href="https://discuss.google.dev#p-989785-step-2-authorize-scopes-in-google-workspace-admin-console-14" aria-label="Heading link"></a>Step 2: Authorize scopes in Google Workspace Admin Console</h4>
<ol>
<li>Sign in to <a href="https://admin.google.com/" rel="noopener nofollow ugc">admin.google.com</a> as a <strong>Super Admin</strong>.</li>
<li>Go to <strong>Security</strong> &gt; <strong>Access and data control</strong> &gt; <strong>API controls</strong> &gt; <strong>Manage Domain Wide Delegation</strong>.</li>
<li>Click <strong>Add new</strong>, paste the <strong>Numeric Client ID</strong>, and add the comma-delimited OAuth scopes.</li>
<li>Click <strong>Authorize</strong>.<br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/4/a/7/4a753c239c6cfbd6c24da8b8f7d2d056216845e2.jpeg" data-download-href="/uploads/short-url/aCGvsHHElWW9hf8vO2Oa2awtk54.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/a/7/4a753c239c6cfbd6c24da8b8f7d2d056216845e2_2_690x372.jpeg" alt="image" data-base62-sha1="aCGvsHHElWW9hf8vO2Oa2awtk54" width="690" height="372" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/a/7/4a753c239c6cfbd6c24da8b8f7d2d056216845e2_2_690x372.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/a/7/4a753c239c6cfbd6c24da8b8f7d2d056216845e2_2_1035x558.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/4/a/7/4a753c239c6cfbd6c24da8b8f7d2d056216845e2_2_1380x744.jpeg 2x" data-dominant-color="F9F8F9"></a></div></li>
</ol>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/0/6/e/06ed1fb84af8f0e70b50e769dfeed5a912d65d96.jpeg" data-download-href="/uploads/short-url/ZgTPjWUcpgbCby2pZiovhu2zYi.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/6/e/06ed1fb84af8f0e70b50e769dfeed5a912d65d96_2_690x288.jpeg" alt="image" data-base62-sha1="ZgTPjWUcpgbCby2pZiovhu2zYi" width="690" height="288" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/6/e/06ed1fb84af8f0e70b50e769dfeed5a912d65d96_2_690x288.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/6/e/06ed1fb84af8f0e70b50e769dfeed5a912d65d96_2_1035x432.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/0/6/e/06ed1fb84af8f0e70b50e769dfeed5a912d65d96_2_1380x576.jpeg 2x" data-dominant-color="F2F3F5"></a></div><p></p>
<h4><a name="p-989785-step-3-configure-environment-env-15" class="anchor" href="https://discuss.google.dev#p-989785-step-3-configure-environment-env-15" aria-label="Heading link"></a>Step 3: Configure environment (<code>.env</code>)</h4>
<pre data-code-wrap="env"><code class="lang-env">GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=your_project_id
GOOGLE_CLOUD_LOCATION=us-central1
SERVICE_ACCOUNT_EMAIL=sa-workspace-agent@your_project.iam.gserviceaccount.com
TARGET_USER_EMAIL=target_employee@yourcompany.com
</code></pre>
<hr>
<h3><a name="p-989785-h-4-resilient-in-memory-token-caching-tokenrelay-16" class="anchor" href="https://discuss.google.dev#p-989785-h-4-resilient-in-memory-token-caching-tokenrelay-16" aria-label="Heading link"></a>4. Resilient in-memory token caching (<code>TokenRelay</code>)</h3>
<p>When an LLM agent executes complex, multi-step tool calls in rapid succession, refreshing tokens synchronously within tool execution hooks can trigger redundant requests and infinite retry loops. Refer to <a href="https://codelabs.developers.google.com/google-workspace-mcp-adk" rel="noopener nofollow ugc">Google Workspace MCP &amp; ADK Codelab</a> for the detailed source code.</p>
<p>The <code>TokenRelay</code> cache solves this by managing proactive refreshes with thread-safe in-memory caching:</p>
<pre data-code-wrap="python"><code class="lang-python">import datetime
from google.auth.transport.requests import Request

class TokenRelay:
    """Manages in-memory caching of Google OAuth access tokens for Gmail MCP.
    
    Proactively refreshes access tokens 5 minutes prior to expiration.
    """

    def __init__(self, credentials):
        self._creds = credentials
        self._cached_token: str | None = None
        self._expiry: datetime.datetime | None = None

    def get_token(self) -&gt; str:
        """Returns a valid access token, proactively refreshing when needed."""
        now = datetime.datetime.now()
        if (
            self._cached_token is None
            or self._expiry is None
            or now &gt;= (self._expiry - datetime.timedelta(minutes=5))
        ):
            try:
                self._creds.refresh(Request())
                self._cached_token = self._creds.token
                self._expiry = now + datetime.timedelta(minutes=50)
            except Exception as e:
                print(f"[TokenRelay] Token refresh failed: {e}")
        return self._cached_token or ""
</code></pre>
<hr>
<h3><a name="p-989785-h-5-assembling-the-agents-with-google-adk-17" class="anchor" href="https://discuss.google.dev#p-989785-h-5-assembling-the-agents-with-google-adk-17" aria-label="Heading link"></a>5. Assembling the agents with Google ADK</h3>
<p>Now, let’s assemble both agents using Google ADK’s <code>LlmAgent</code> and <code>McpToolset</code>.</p>
<h4><a name="p-989785-option-1-interactive-user-agent-18" class="anchor" href="https://discuss.google.dev#p-989785-option-1-interactive-user-agent-18" aria-label="Heading link"></a>Option 1: Interactive user agent</h4>
<p>Refer to <a href="https://codelabs.developers.google.com/google-workspace-mcp-adk" rel="noopener nofollow ugc">Google Workspace MCP &amp; ADK Codelab</a> for a step-by-step guide and source code on how to implement Option 1.</p>
<pre data-code-wrap="python"><code class="lang-python">import os
from google.oauth2.credentials import Credentials
from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams

os.environ["ADK_ENABLE_MCP_GRACEFUL_ERROR_HANDLING"] = "1"

# 1. Load user credentials and wrap with TokenRelay
creds = Credentials.from_authorized_user_file("token.json", scopes=SCOPES)
token_relay = TokenRelay(creds)

# 2. Define dynamic header provider for quota &amp; auth
def auth_header_provider(tool_context=None) -&gt; dict[str, str]:
    return {
        "Authorization": f"Bearer {token_relay.get_token()}",
        "X-Goog-User-Project": os.environ.get("GOOGLE_CLOUD_PROJECT", "your-project-id"),
    }

# 3. Connect to managed Gmail MCP endpoint
gmail_mcp = McpToolset(
    connection_params=StreamableHTTPConnectionParams(
        url="https://gmailmcp.googleapis.com/mcp/v1",
        timeout=60,
    ),
    header_provider=auth_header_provider,
)

# 4. Initialize the ADK Agent
root_agent = LlmAgent(
    model="gemini-3.7-flash",
    name="gmail_oauth_agent",
    instruction="You are an AI email assistant. Help the user search, summarize, and draft emails using Gmail MCP tools.",
    tools=[gmail_mcp],
)
</code></pre>
<h4><a name="p-989785-option-2-enterprise-headless-dwd-agent-19" class="anchor" href="https://discuss.google.dev#p-989785-option-2-enterprise-headless-dwd-agent-19" aria-label="Heading link"></a>Option 2: Enterprise headless DWD agent</h4>
<pre data-code-wrap="python"><code class="lang-python">import os
import google.auth
from google.auth import impersonated_credentials
from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams

os.environ["ADK_ENABLE_MCP_GRACEFUL_ERROR_HANDLING"] = "1"

# 1. Obtain base Application Default Credentials (e.g., Cloud Run Workload Identity)
base_credentials, _ = google.auth.default(scopes=SCOPES)

# 2. Impersonate Service Account and delegate domain authority
creds = impersonated_credentials.Credentials(
    source_credentials=base_credentials,
    target_principal=os.environ["SERVICE_ACCOUNT_EMAIL"],
    target_scopes=SCOPES,
    subject=os.environ["TARGET_USER_EMAIL"],  # Target employee mailbox
)

token_relay = TokenRelay(creds)

def auth_header_provider(tool_context=None) -&gt; dict[str, str]:
    return {
        "Authorization": f"Bearer {token_relay.get_token()}",
        "X-Goog-User-Project": os.environ.get("GOOGLE_CLOUD_PROJECT", "your-project-id"),
    }

gmail_mcp = McpToolset(
    connection_params=StreamableHTTPConnectionParams(
        url="https://gmailmcp.googleapis.com/mcp/v1",
        timeout=60,
    ),
    header_provider=auth_header_provider,
)

root_agent = LlmAgent(
    model="gemini-3.7-flash",
    name="gmail_dwd_agent",
    instruction="You are an autonomous enterprise operations assistant performing automated inbox triage on behalf of the designated mailbox.",
    tools=[gmail_mcp],
)
</code></pre>
<hr>
<h2><a name="p-989785-production-deployment-blueprint-on-google-cloud-run-20" class="anchor" href="https://discuss.google.dev#p-989785-production-deployment-blueprint-on-google-cloud-run-20" aria-label="Heading link"></a>Production deployment blueprint on Google Cloud Run</h2>
<p>To scale your agent in production, deploy the application container to <strong>Google Cloud Run</strong> utilizing <strong>Workload Identity</strong>. Pay attention to the following best practices to ensure security and reliability:</p>
<ol>
<li><strong>Never hardcode JSON keys:</strong> In Cloud Run, authenticate your service container using Workload Identity attached to the runtime service account.</li>
<li><strong>Always supply <code>X-Goog-User-Project</code>:</strong> This header ensures API quotas and metrics route accurately to your GCP project.</li>
<li><strong>Configure timeout and error resiliency:</strong> Remote Streamable HTTP MCP connections should specify <code>timeout=60</code> and <code>ADK_ENABLE_MCP_GRACEFUL_ERROR_HANDLING="1"</code> to avoid dropping conversational context during network spikes.</li>
<li><strong>Follow the principle of least privilege:</strong> Scope permissions to the minimal set required (e.g., <code>gmail.readonly</code> for analysis bots, <code>gmail.modify</code> for categorization and triage).</li>
</ol>
<hr>
<h2><a name="p-989785-testing-and-local-verification-with-adk-web-server-21" class="anchor" href="https://discuss.google.dev#p-989785-testing-and-local-verification-with-adk-web-server-21" aria-label="Heading link"></a>Testing and local verification with ADK web server</h2>
<p>You can test the agents locally using the built-in ADK developer UI. To understand how this architecture operates in production, let’s ground it in an enterprise scenario: Automating cross-functional project updates and draft generation.</p>
<h3><a name="p-989785-real-world-application-scenario-autonomous-inbox-triage-for-project-updates-22" class="anchor" href="https://discuss.google.dev#p-989785-real-world-application-scenario-autonomous-inbox-triage-for-project-updates-22" aria-label="Heading link"></a>Real-world application scenario: autonomous inbox triage for project updates</h3>
<p>An engineering operations team receives dozens of daily emails regarding an initiative called “Forge Project”. Manual triage requires someone to read each thread, identify blocking items, draft updates, and update labels.</p>
<p>In our test inbox, we have active emails regarding the Forge Project in the inbox:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/2/9/2/292ec2fbcd416c26a18710f5fbaf50e34afb8863.jpeg" data-download-href="/uploads/short-url/5SjLhHYMZUGivgeJsSANKjcV8DV.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/9/2/292ec2fbcd416c26a18710f5fbaf50e34afb8863_2_690x194.jpeg" alt="image" data-base62-sha1="5SjLhHYMZUGivgeJsSANKjcV8DV" width="690" height="194" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/9/2/292ec2fbcd416c26a18710f5fbaf50e34afb8863_2_690x194.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/9/2/292ec2fbcd416c26a18710f5fbaf50e34afb8863_2_1035x291.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/9/2/292ec2fbcd416c26a18710f5fbaf50e34afb8863_2_1380x388.jpeg 2x" data-dominant-color="EDF0F6"></a></div><p></p>
<h3><a name="p-989785-execution-walkthrough-with-adk-23" class="anchor" href="https://discuss.google.dev#p-989785-execution-walkthrough-with-adk-23" aria-label="Heading link"></a>Execution walkthrough with ADK</h3>
<p>We ask our headless DWD agent:</p>
<blockquote>
<p>“Search for recent emails about the Forge Project, summarize the current blockers, and draft a response to the latest update acknowledging the timeline.”</p>
</blockquote>
<p>The execution unfolds across three coordinated phases:</p>
<ol>
<li>Dynamic tool discovery: Gemini inspects the live Gmail MCP schema and executes list_threads(q=‘Forge Project’).</li>
<li>Context extraction &amp; synthesis: The agent fetches message contents via get_thread, extracts timeline updates, and identifies pending deliverables.</li>
<li>Safe drafting (HITL): Instead of executing an irreversible send, the agent calls create_draft to prepare a response and applies the FORGE_TRIAGED label.</li>
</ol>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/d/d/7/dd776040903ade35ed563736a82d57d95ca42e9a.jpeg" data-download-href="/uploads/short-url/vBbhxebB4l1vfC3YqmuTl9dzEYq.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/d/7/dd776040903ade35ed563736a82d57d95ca42e9a_2_690x432.jpeg" alt="image" data-base62-sha1="vBbhxebB4l1vfC3YqmuTl9dzEYq" width="690" height="432" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/d/7/dd776040903ade35ed563736a82d57d95ca42e9a_2_690x432.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/d/7/dd776040903ade35ed563736a82d57d95ca42e9a_2_1035x648.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/d/d/7/dd776040903ade35ed563736a82d57d95ca42e9a_2_1380x864.jpeg 2x" data-dominant-color="EEF1F5"></a></div><p></p>
<p>The screenshot above illustrates how the agent’s MCP tool output accurately matches the live Gmail inbox state. The agent was able to successfully retrieve and summarize emails related to the ‘Forge Project’.</p>
<hr>
<h2><a name="p-989785-conclusion-and-next-steps-24" class="anchor" href="https://discuss.google.dev#p-989785-conclusion-and-next-steps-24" aria-label="Heading link"></a>Conclusion and next steps</h2>
<p>Integrating <strong>Google Agent Development Kit (ADK)</strong> with the <strong>Google Workspace Gmail MCP Server</strong> unlocks a robust, standardized foundation for enterprise AI automation. By pairing MCP’s standard tool discovery with the appropriate authentication model:</p>
<ul>
<li><strong>Interactive User Flow</strong> for multi-tenant and interactive assistants</li>
<li><strong>Service Account Domain-Wide Delegation</strong> for 24/7 autonomous background triage</li>
</ul>
<p>You will be able to achieve both the security compliance required by enterprise IT and the seamless developer experience of modern agent frameworks.</p>
<h3><a name="p-989785-ready-to-build-25" class="anchor" href="https://discuss.google.dev#p-989785-ready-to-build-25" aria-label="Heading link"></a>Ready to build?</h3>
<ul>
<li>Apply to join the <a href="https://developers.google.com/workspace/preview" rel="noopener nofollow ugc">Google Workspace Developer Preview Program</a> to access managed MCP endpoints.</li>
<li>Work through the hands-on <a href="https://codelabs.developers.google.com/google-workspace-mcp-adk#0" rel="noopener nofollow ugc">Google Workspace MCP &amp; ADK Codelab</a>.</li>
</ul>
            <p><small>1 post - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/building-enterprise-ai-agents-with-adk-and-the-gmail-mcp-server/397198">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/building-enterprise-ai-agents-with-adk-and-the-gmail-mcp-server/397198</link>
          <pubDate>Mon, 14 Sep 2026 20:02:25 +0000</pubDate>
          <discourse:topicPinned>Yes</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397198</guid>
          <source url="https://discuss.google.dev/t/building-enterprise-ai-agents-with-adk-and-the-gmail-mcp-server/397198.rss">Building enterprise AI agents with ADK and the Gmail MCP Server</source>
        </item>
        <item>
          <title>URGENT: Super admin locked out of cancelled Workspace tenant with data still in storage</title>
          <dc:creator><![CDATA[Alok_Mishra1]]></dc:creator>
          <category>Q&amp;A</category>
          <description><![CDATA[
            <p>Hello,</p>
<p>I am the super admin for a defunct company workspace domain (<code>wesense.ai</code>). Our subscription was cancelled, and the admin console now blocks us from reactivating the plan or accessing data export tools because it states the account is being wiped out.</p>
<p>However, the Admin Console Storage dashboard still displays 128GB of data (primarily Google Drive files) actively residing on Google’s servers. These files contain vital legal compliance and shareholder documents that we urgently need to recover.</p>
<p>Because the standard UI blocks subscription reactivation and gives a “Not available to purchase” error due to the deletion queue, is there is a way to manually request to pause the automated deletion/purge process so we can export this data?</p>
<p>I can provide our super admin email and verification details privately.</p>
<p>Any help is greatly appreciated!</p>
            <p><small>2 posts - 3 participants</small></p>
            <p><a href="https://discuss.google.dev/t/urgent-super-admin-locked-out-of-cancelled-workspace-tenant-with-data-still-in-storage/397193">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/urgent-super-admin-locked-out-of-cancelled-workspace-tenant-with-data-still-in-storage/397193</link>
          <pubDate>Mon, 14 Sep 2026 19:47:25 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397193</guid>
          <source url="https://discuss.google.dev/t/urgent-super-admin-locked-out-of-cancelled-workspace-tenant-with-data-still-in-storage/397193.rss">URGENT: Super admin locked out of cancelled Workspace tenant with data still in storage</source>
        </item>
        <item>
          <title>Gemini 3.5 Flash-Lite on Vertex: does maxOutputTokens bound response + thinking?</title>
          <dc:creator><![CDATA[은철_허]]></dc:creator>
          <category>Generative AI &amp; Foundational Models</category>
          <description><![CDATA[
            <p>I was referred here from the Google AI Developers Forum because this question concerns the Vertex API:</p><aside class="onebox discoursetopic" data-onebox-src="https://discuss.ai.google.dev/t/gemini-3-5-flash-lite-on-vertex-does-maxoutputtokens-bound-response-thinking/181203">
  <header class="source">
      <img src="https://d2yds90mtvelsl.cloudfront.net/original/3X/d/d/ddf6ff71e5ff9ec51191610a737fb173f26e58b2.png" class="site-icon" alt="" data-dominant-color="97A7B1" width="32" height="32">

      <a href="https://discuss.ai.google.dev/t/gemini-3-5-flash-lite-on-vertex-does-maxoutputtokens-bound-response-thinking/181203" target="_blank" rel="noopener nofollow ugc" title="04:28AM - 07 September 2026">Google AI Developers Forum – 7 Sep 26</a>
  </header>

  <article class="onebox-body">
    <img src="https://d2yds90mtvelsl.cloudfront.net/original/3X/7/1/71f4db208a7684ec15a4262b4b4f0256d2effa2c.png" class="thumbnail onebox-avatar" data-dominant-color="CFCEC8" width="192" height="192">

<div class="title-wrapper">
  <h3><a href="https://discuss.ai.google.dev/t/gemini-3-5-flash-lite-on-vertex-does-maxoutputtokens-bound-response-thinking/181203" target="_blank" rel="noopener nofollow ugc">Gemini 3.5 Flash-Lite on Vertex: does maxOutputTokens bound response + thinking?</a></h3>
  <div class="topic-category">
      <span class="badge-wrapper bullet">
        <span class="badge-category-bg" style="background-color: #406AFB;"></span>
        <span class="badge-category clear-badge">
          <span class="category-name">Gemini API</span>
        </span>
      </span>
      <span class="badge-wrapper bullet">
        <span class="badge-category-bg" style="background-color: #aedbda;"></span>
        <span class="badge-category clear-badge">
          <span class="category-name">Documentation</span>
        </span>
      </span>
    <div class="topic-header-extra">
      <div class="list-tags">
        <div class="discourse-tags">
          <svg class="fa d-icon d-icon-tag svg-icon svg-string"><use href="#tag"></use></svg>
            <span class="discourse-tag simple">vertexai</span>
        </div>
      </div>
    </div>
  </div>
</div>

  <p>For the managed gemini-3.5-flash-lite publisher model on Vertex/Agent Platform v1 generateContent (not the Developer API, Live API or a tuned endpoint), does generationConfig.maxOutputTokens = G with thinkingConfig.thinkingLevel = MINIMAL enforce...</p>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>For the managed <code>gemini-3.5-flash-lite</code> publisher model on Vertex/Agent Platform v1 <code>generateContent</code> (not the Developer API, Live API, or a tuned endpoint), could you clarify the provider-enforced token limit for this configuration?</p>
<ul>
<li><code>generationConfig.maxOutputTokens = G</code></li>
<li><code>thinkingConfig.thinkingLevel = MINIMAL</code></li>
<li>Single-turn, non-streaming text/JSON response</li>
<li>Input: silent video plus text; no tools, grounding, or explicit cache</li>
</ul>
<ol>
<li>Does this enforce <code>usageMetadata.thoughtsTokenCount + usageMetadata.candidatesTokenCount &lt;= G</code>? Please cite the official specification applicable to this exact model and API.</li>
<li>If thinking tokens are outside that limit, what provider-enforced maximum bounds all chargeable thinking tokens per request under this configuration?</li>
<li>If the client times out or disconnects while generation continues server-side, does the same bound still apply, and how can the final billable usage be obtained?</li>
</ol>
<p>We have not enabled inference to test this assumption. We need a documented per-request bound before enabling it, rather than relying on an observed sample or a client timeout as a spending limit. If any model or configuration identifier above is not applicable, please identify the supported equivalent explicitly.</p>
<p>Thank you.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/gemini-3-5-flash-lite-on-vertex-does-maxoutputtokens-bound-response-thinking/397162">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/gemini-3-5-flash-lite-on-vertex-does-maxoutputtokens-bound-response-thinking/397162</link>
          <pubDate>Mon, 14 Sep 2026 18:19:03 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397162</guid>
          <source url="https://discuss.google.dev/t/gemini-3-5-flash-lite-on-vertex-does-maxoutputtokens-bound-response-thinking/397162.rss">Gemini 3.5 Flash-Lite on Vertex: does maxOutputTokens bound response + thinking?</source>
        </item>
        <item>
          <title>Google OAuth returns redirect_uri_mismatch for a persisted URI while Drive and Calendar work on the same client</title>
          <dc:creator><![CDATA[MARWAR_RI_MAHIMA]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Hello Google Cloud Community,</p>
<p>I am troubleshooting a Google OAuth redirect_uri_mismatch issue in a production application.</p>
<p>The same OAuth 2.0 Web application client is used for three integrations:</p>
<ul>
<li>Google Drive</li>
<li>Google Calendar</li>
<li>Google Contacts</li>
</ul>
<p>The problem occurs only with the Google Contacts redirect URI.</p>
<p>OAuth Client ID:<br>
(PII Removed by Staff)</p>
<p>Project:<br>
(PII Removed by Staff)</p>
<p>Redirect URIs:</p>
<p>Drive:<br>
<a href="https://api.davidcomputer.online/api/integrations/google-drive/callback" class="onebox" target="_blank" rel="noopener nofollow ugc">https://api.davidcomputer.online/api/integrations/google-drive/callback</a></p>
<p>Calendar:<br>
<a href="https://api.davidcomputer.online/api/integrations/google-calendar/callback" class="onebox" target="_blank" rel="noopener nofollow ugc">https://api.davidcomputer.online/api/integrations/google-calendar/callback</a></p>
<p>Contacts:<br>
<a href="https://api.davidcomputer.online/api/integrations/google-contacts/callback" class="onebox" target="_blank" rel="noopener nofollow ugc">https://api.davidcomputer.online/api/integrations/google-contacts/callback</a></p>
<p>Current findings:</p>
<ol>
<li>
<p>The Contacts redirect URI is saved and persisted under Google Auth Platform → Clients for the exact Web application OAuth client.</p>
</li>
<li>
<p>The same URI remains present after closing and reopening the OAuth client.</p>
</li>
<li>
<p>The URI is also visible in the legacy OAuth Credentials UI.</p>
</li>
<li>
<p>The production ERP generates the Contacts redirect URI exactly as registered.</p>
</li>
<li>
<p>A byte-for-byte comparison found zero differences:</p>
<ul>
<li>same length</li>
<li>no whitespace differences</li>
<li>no hidden/control characters</li>
<li>no trailing slash difference</li>
</ul>
</li>
<li>
<p>Drive authorization request:<br>
MATCH / HTTP 200</p>
</li>
<li>
<p>Calendar authorization request:<br>
MATCH / HTTP 200</p>
</li>
<li>
<p>Contacts authorization request:<br>
HTTP 400 redirect_uri_mismatch</p>
</li>
<li>
<p>A manually constructed OAuth authorization request using the exact same Contacts redirect URI also returns:<br>
HTTP 400 redirect_uri_mismatch</p>
</li>
<li>
<p>All three integrations use the exact same OAuth Client ID.</p>
</li>
<li>
<p>The OAuth client is active and no duplicate client was found.</p>
</li>
<li>
<p>Google Auth Platform shows no blocking configuration warning.</p>
</li>
</ol>
<p>Therefore, the registered Contacts URI and the URI sent in the authorization request are identical, but Google’s live OAuth authorization endpoint rejects the Contacts URI while accepting the Drive and Calendar URIs on the same OAuth client.</p>
<p>Has anyone encountered a situation where a redirect URI is visibly persisted in Google Auth Platform but the live OAuth authorization endpoint still returns redirect_uri_mismatch specifically for that URI?</p>
<p>I would appreciate guidance on how to diagnose or reconcile this Google-side OAuth configuration/runtime inconsistency.</p>
<p>No client secret, access token, refresh token, authorization code, cookies, or other credentials are included here.</p>
<p>Thank you.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/google-oauth-returns-redirect-uri-mismatch-for-a-persisted-uri-while-drive-and-calendar-work-on-the-same-client/397156">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/google-oauth-returns-redirect-uri-mismatch-for-a-persisted-uri-while-drive-and-calendar-work-on-the-same-client/397156</link>
          <pubDate>Mon, 14 Sep 2026 18:13:28 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397156</guid>
          <source url="https://discuss.google.dev/t/google-oauth-returns-redirect-uri-mismatch-for-a-persisted-uri-while-drive-and-calendar-work-on-the-same-client/397156.rss">Google OAuth returns redirect_uri_mismatch for a persisted URI while Drive and Calendar work on the same client</source>
        </item>
        <item>
          <title>[Action Advised] Manage your unused OAuth clients</title>
          <dc:creator><![CDATA[Azeem_Cv]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>This is my website. (URL Removed by Staff)</p>
<p>I use Mindmaps (from Google Console) for this project.</p>
<p>This is used for saving and loading files from Google Drive.</p>
<p>To achieve this, follow the below steps.</p>
<ol>
<li>Goto (URL Removed by Staff)</li>
<li>You can see the ‘Document’ dropdown menu on the upper right.</li>
<li>Click ‘Document’-&gt;‘Open…’-&gt;‘Open’ beneath ‘Google Drive’</li>
</ol>
<p>Recently I got a message from Google that, “[Action Advised] Manage your unused OAuth clients and protect your information”</p>
<p>It states that “the following projects that you manage have OAuth clients that have been inactive for at least 5 months, and will be deleted in 30 days unless you take action.”</p>
<p>But I get a lot of traffic to my website and many people use ‘Open/Save’ for Google Drive.</p>
<p>Please check the picture below about the traffic I get (it is retrieved from Google Console).</p>
<p>There you can see the visitor stats.</p>
<p>You can see that it is very much active.</p>
<p>Then, why did Google send me this message?</p>
<p>Do I need to do anything?</p>
<p>Thanks</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/action-advised-manage-your-unused-oauth-clients/397145">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/action-advised-manage-your-unused-oauth-clients/397145</link>
          <pubDate>Mon, 14 Sep 2026 17:09:20 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397145</guid>
          <source url="https://discuss.google.dev/t/action-advised-manage-your-unused-oauth-clients/397145.rss">[Action Advised] Manage your unused OAuth clients</source>
        </item>
        <item>
          <title>Format rules: icons render but text/highlight colors don&#39;t (web client)</title>
          <dc:creator><![CDATA[Milad_Akoula]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>Hello, I’m experiencing an issue with format rules in my app (MA app - Paramount Inventory, currently an undeployed prototype).</p>
<p>I have 4 format rules on the Inventory table (Expired, Expiring Soon, Low Stock, New Lot - Calibration Required). Each rule has a condition, an icon, a text color and a highlight (background) color.</p>
<p><strong>What works:</strong> the conditions evaluate correctly — the correct icon appears on each row.</p>
<p><strong>What doesn’t work:</strong> the text color and highlight color never render. Rows show default black text on white background, and even the icons render in black instead of the rule’s text color. This happens in the editor’s app preview (mobile and desktop modes), the app opened directly in a browser tab, and in both Deck and Detail views.</p>
<p><strong>What I tried:</strong></p>
<ul>
<li>Verified “Format these columns and actions” has the display columns selected.</li>
<li>Changed the highlight color to FF0000 and to the preset “red”, saved — still no color. Reverted afterwards.</li>
<li>Created a brand-new rule from scratch with identical settings — same behavior (icon only, no colors). Deleted the test rule afterwards.</li>
<li>Saved multiple times; no editor errors.</li>
</ul>
<p>Is this a known web-client issue, or is something wrong with my rule setup? Screenshots attached.</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/1/a/c/1ace9ee3e2c16f1cf6be983cb92b16b62792035b.jpeg" data-download-href="/uploads/short-url/3P960JiZLompNzARvhqxIp6xo5d.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/1/a/c/1ace9ee3e2c16f1cf6be983cb92b16b62792035b_2_690x346.jpeg" alt="image" data-base62-sha1="3P960JiZLompNzARvhqxIp6xo5d" width="690" height="346" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/1/a/c/1ace9ee3e2c16f1cf6be983cb92b16b62792035b_2_690x346.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/1/a/c/1ace9ee3e2c16f1cf6be983cb92b16b62792035b_2_1035x519.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/1/a/c/1ace9ee3e2c16f1cf6be983cb92b16b62792035b_2_1380x692.jpeg 2x" data-dominant-color="F1F2F3"></a></div><br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/c/c/d/ccd2b9a8083aafd9950d531424847a1c39cadb08.jpeg" data-download-href="/uploads/short-url/tdWSBjcZFh86tjAmHBwD92tTr04.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/c/d/ccd2b9a8083aafd9950d531424847a1c39cadb08_2_690x363.jpeg" alt="image" data-base62-sha1="tdWSBjcZFh86tjAmHBwD92tTr04" width="690" height="363" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/c/d/ccd2b9a8083aafd9950d531424847a1c39cadb08_2_690x363.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/c/d/ccd2b9a8083aafd9950d531424847a1c39cadb08_2_1035x544.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/c/c/d/ccd2b9a8083aafd9950d531424847a1c39cadb08_2_1380x726.jpeg 2x" data-dominant-color="EFF0F1"></a></div><br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://d2yds90mtvelsl.cloudfront.net/original/4X/b/4/0/b409f01a0ac8cf4bba355989eea3b13da3e4defd.jpeg" data-download-href="/uploads/short-url/pGHeFdbw1bssUkTuWD2GJ0T2Yqx.jpeg?dl=1" title="image" rel="noopener nofollow ugc"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/4/0/b409f01a0ac8cf4bba355989eea3b13da3e4defd_2_689x356.jpeg" alt="image" data-base62-sha1="pGHeFdbw1bssUkTuWD2GJ0T2Yqx" width="689" height="356" srcset="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/4/0/b409f01a0ac8cf4bba355989eea3b13da3e4defd_2_689x356.jpeg, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/4/0/b409f01a0ac8cf4bba355989eea3b13da3e4defd_2_1033x534.jpeg 1.5x, https://d2yds90mtvelsl.cloudfront.net/optimized/4X/b/4/0/b409f01a0ac8cf4bba355989eea3b13da3e4defd_2_1378x712.jpeg 2x" data-dominant-color="F3F3F4"></a></div><p></p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/format-rules-icons-render-but-text-highlight-colors-dont-web-client/397137">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/format-rules-icons-render-but-text-highlight-colors-dont-web-client/397137</link>
          <pubDate>Mon, 14 Sep 2026 16:30:56 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397137</guid>
          <source url="https://discuss.google.dev/t/format-rules-icons-render-but-text-highlight-colors-dont-web-client/397137.rss">Format rules: icons render but text/highlight colors don&#39;t (web client)</source>
        </item>
        <item>
          <title>Verification Center stuck: &quot;Prepare for verification&quot; disabled, Branding page has no &quot;Verify Branding&quot; or &quot;Publish branding&quot; button (PII Removed by Staff)</title>
          <dc:creator><![CDATA[동윤_황]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p><strong>Project ID:</strong> (PII Removed by Staff)<br>
<strong>OAuth client:</strong> (PII Removed by Staff)<br>
<strong>User type:</strong> External · <strong>Publishing status:</strong> In production</p>
<h2><a name="p-989692-the-problem-1" class="anchor" href="https://discuss.google.dev#p-989692-the-problem-1" aria-label="Heading link"></a>The problem</h2>
<p>The Verification Center will not let me submit. “Data access status” says:</p>
<blockquote>
<p>Your app’s data access is not verified. Verification is required because your app requests sensitive or restricted scopes.<br>
You must verify and publish your branding before you can request verification.</p>
</blockquote>
<p>and the <strong>Prepare for verification</strong> button is disabled (<code>disabled: true</code> in the DOM, not merely styled that way).</p>
<p>The documented next step is the Branding page. Per</p><aside class="onebox allowlistedgeneric" data-onebox-src="https://developers.google.com/identity/protocols/oauth2/production-readiness/brand-verification">
  <header class="source">
      <img src="https://d2yds90mtvelsl.cloudfront.net/original/3X/b/2/b2a2be7cc9c7442d916d15b4c40049e353cd51bf.png" class="site-icon" alt="" data-dominant-color="D9D8D3" width="24" height="24">

      <a href="https://developers.google.com/identity/protocols/oauth2/production-readiness/brand-verification" target="_blank" rel="noopener nofollow ugc">Google for Developers</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:690/387;"><img src="https://d2yds90mtvelsl.cloudfront.net/optimized/4X/2/d/4/2d4ee727fbd4ce07b35878f1f07931572766866c_2_690x388.png" class="thumbnail" alt="" data-dominant-color="0A8BD2" width="690" height="388"></div>

<h3><a href="https://developers.google.com/identity/protocols/oauth2/production-readiness/brand-verification" target="_blank" rel="noopener nofollow ugc">Submit for brand verification &nbsp;|&nbsp; App verification to use Google...</a></h3>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>
<p>
that page should offer a <strong>Verify Branding</strong> button, and then a <strong>Publish branding</strong> button once the automated review finishes.</p>
<p><strong>Neither button exists on my Branding page.</strong> I enumerated every <code>button</code> and <code>a</code> element on <code>console.cloud.google.com/auth/branding? (PII Removed by Staff)</code>. The complete list of actionable controls is:</p>
<pre><code>제거 (Remove logo) · 로고 변경 (Change logo) · 도메인 추가 (Add domain)
저장 (Save) · 변경사항 취소 (Cancel changes)
</code></pre>
<p>There is no Verify, no Publish, and no submit control of any kind. So the Verification Center points at a button that the Branding page does not render — the two pages disagree, and there is no way forward from either.</p>
<h2><a name="p-989692-configuration-all-complete-2" class="anchor" href="https://discuss.google.dev#p-989692-configuration-all-complete-2" aria-label="Heading link"></a>Configuration (all complete)</h2>
<div class="md-table">
<table>
<thead>
<tr>
<th>Item</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>App name</td>
<td>LazyMax</td>
</tr>
<tr>
<td>User support email</td>
<td>set</td>
</tr>
<tr>
<td>App logo</td>
<td>uploaded, displays in the console</td>
</tr>
<tr>
<td>Application home page</td>
<td><a href="https://lazymax.doongs116.workers.dev/" rel="noopener nofollow ugc">https://lazymax.doongs116.workers.dev/</a></td>
</tr>
<tr>
<td>Privacy policy</td>
<td><a href="https://lazymax.doongs116.workers.dev/privacy" class="inline-onebox" rel="noopener nofollow ugc">LazyMax</a></td>
</tr>
<tr>
<td>Terms of service</td>
<td><a href="https://lazymax.doongs116.workers.dev/terms" class="inline-onebox" rel="noopener nofollow ugc">LazyMax</a></td>
</tr>
<tr>
<td>Authorized domain</td>
<td>doongs116.workers.dev</td>
</tr>
<tr>
<td>Developer contact email</td>
<td>set</td>
</tr>
<tr>
<td>Publishing status</td>
<td>In production</td>
</tr>
<tr>
<td>User type</td>
<td>External</td>
</tr>
<tr>
<td>Cloud Billing</td>
<td>linked</td>
</tr>
<tr>
<td>Search Console</td>
<td>doongs116.workers.dev verified by the same account that owns the project</td>
</tr>
</tbody>
</table>
</div><p>All three pages return HTTP 200, are publicly reachable with no login, describe the app, and link to each other. Scopes requested are <code>calendar.events</code> and <code>calendar.readonly</code>, with the usage justification filled in on the Data access page and saved.</p>
<p>Saving the Branding form works — I added the terms-of-service URL, saved, reloaded, and the value persisted. So the form itself is functional; it simply never offers a verification action.</p>
<h2><a name="p-989692-same-report-from-other-developers-3" class="anchor" href="https://discuss.google.dev#p-989692-same-report-from-other-developers-3" aria-label="Heading link"></a>Same report from other developers</h2>
<p>This does not look project-specific:</p>
<ul>
<li><a href="https://discuss.google.dev/t/prepare-for-verification-disabled-no-verify-branding-button-external-in-production-branding-complete-strobedesk/390823" class="inline-onebox">Prepare for verification disabled, no Verify Branding button — External + In production, branding complete (StrobeDesk)</a></li>
<li><a href="https://discuss.google.dev/t/prepare-for-verification-disabled-no-verify-branding-button-external-in-production-branding-complete/387601" class="inline-onebox">"Prepare for verification" disabled, no "Verify Branding" button — External + In production, branding complete</a></li>
<li><a href="https://discuss.google.dev/t/verification-center-stuck-prepare-for-verification-disabled-branding-has-no-publish-verify-button-project-realtyworld-crm/390969" class="inline-onebox">Verification Center stuck: "Prepare for verification" disabled, Branding has no publish/verify button (Project: realtyworld-crm)</a></li>
<li><a href="https://discuss.google.dev/t/verification-center-stuck-prepare-for-verification-disabled-branding-page-has-no-publish-button-pii-removed-by-staff/393040">https://discuss.google.dev/t/verification-center-stuck-prepare-for-verification-disabled-branding-page-has-no-publish-button-pii-removed-by-staff/393040</a></li>
</ul>
<p>None of them has a posted resolution.</p>
<h2><a name="p-989692-what-i-am-asking-for-4" class="anchor" href="https://discuss.google.dev#p-989692-what-i-am-asking-for-4" aria-label="Heading link"></a>What I am asking for</h2>
<ol>
<li>Could the OAuth verification / Trust &amp; Safety team either trigger the branding review for this project manually, or say what condition actually unlocks the <strong>Verify Branding</strong> button? If it is a rollout gate rather than a missing setting, saying so would save a lot of people a lot of guessing.</li>
<li>A secondary question while I am here: my home page is on <code>*.workers.dev</code>, a Cloudflare-provided subdomain on the Public Suffix List. Search Console accepted it as a URL-prefix property. <strong>Is a <code>workers.dev</code> subdomain acceptable for branding verification</strong>, or will review re-flag domain ownership and require a domain I have registered myself? I would rather buy a domain now than after a rejection.</li>
</ol>
<p>Happy to share anything else needed. Thanks.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/verification-center-stuck-prepare-for-verification-disabled-branding-page-has-no-verify-branding-or-publish-branding-button-pii-removed-by-staff/397135">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/verification-center-stuck-prepare-for-verification-disabled-branding-page-has-no-verify-branding-or-publish-branding-button-pii-removed-by-staff/397135</link>
          <pubDate>Mon, 14 Sep 2026 16:27:36 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397135</guid>
          <source url="https://discuss.google.dev/t/verification-center-stuck-prepare-for-verification-disabled-branding-page-has-no-verify-branding-or-publish-branding-button-pii-removed-by-staff/397135.rss">Verification Center stuck: &quot;Prepare for verification&quot; disabled, Branding page has no &quot;Verify Branding&quot; or &quot;Publish branding&quot; button (PII Removed by Staff)</source>
        </item>
        <item>
          <title>Allow setting the first visible hour in AppSheet Calendar day view</title>
          <dc:creator><![CDATA[Tamás_Dobra]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>Hello AppSheet team,</p>
<p>Could you add a setting to define the first visible hour in Calendar day and week views?</p>
<p>Our workday starts at 07:00, but the AppSheet Calendar often opens around 13:00/current time. Users must scroll up every time to see the morning schedule. A configurable “First visible hour” (for example 07:00) would make the calendar much more practical for field-service and work-scheduling apps.</p>
<p>The calendar events and start times are correct; this is only about the initial visible scroll position.</p>
<p>Thank you!</p>
            <p><small>3 posts - 3 participants</small></p>
            <p><a href="https://discuss.google.dev/t/allow-setting-the-first-visible-hour-in-appsheet-calendar-day-view/397109">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/allow-setting-the-first-visible-hour-in-appsheet-calendar-day-view/397109</link>
          <pubDate>Mon, 14 Sep 2026 15:47:11 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397109</guid>
          <source url="https://discuss.google.dev/t/allow-setting-the-first-visible-hour-in-appsheet-calendar-day-view/397109.rss">Allow setting the first visible hour in AppSheet Calendar day view</source>
        </item>
        <item>
          <title>OAuth branding verification blocked — no Trust &amp; Safety email received</title>
          <dc:creator><![CDATA[TapTapp_HQ]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Our OAuth branding verification is stuck. Homepage and privacy policy checks passed, but the logo was flagged as not uniquely identifying our brand.</p>
<p>The Verification Center instructs us to reply to the Trust &amp; Safety email thread, but no email has arrived.</p>
<p>How can we contact the verification team privately to have the email resent and the logo finding reviewed? We can provide project details and supporting evidence through a private support channel.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/oauth-branding-verification-blocked-no-trust-safety-email-received/397090">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/oauth-branding-verification-blocked-no-trust-safety-email-received/397090</link>
          <pubDate>Mon, 14 Sep 2026 15:04:01 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397090</guid>
          <source url="https://discuss.google.dev/t/oauth-branding-verification-blocked-no-trust-safety-email-received/397090.rss">OAuth branding verification blocked — no Trust &amp; Safety email received</source>
        </item>
        <item>
          <title>Iraq missing from Google Cloud signup country list</title>
          <dc:creator><![CDATA[محمد_العكيدي]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Hello,</p>
<p>I’m located in Iraq and want to configure Google Sign-In for my application, Al-Akidi Orders, using Supabase Auth.</p>
<p>The Google Cloud welcome dialog requires me to select a country, but Iraq is missing from the dropdown, so I cannot complete registration.</p>
<p>Is Google Cloud registration currently available for developers residing in Iraq? What is the supported way to create an OAuth client using my actual country information?</p>
<p>Thank you</p>
            <p><small>1 post - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/iraq-missing-from-google-cloud-signup-country-list/397083">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/iraq-missing-from-google-cloud-signup-country-list/397083</link>
          <pubDate>Mon, 14 Sep 2026 14:59:11 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397083</guid>
          <source url="https://discuss.google.dev/t/iraq-missing-from-google-cloud-signup-country-list/397083.rss">Iraq missing from Google Cloud signup country list</source>
        </item>
        <item>
          <title>Intermittent Ref columns changing to 1900 dates and causing “Invalid request provided to AppSheet database”</title>
          <dc:creator><![CDATA[Sherin_Premkumar]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>Hello,</p>
<p>I’m experiencing an intermittent issue with an AppSheet app using <strong>AppSheet Database</strong> as the data source.</p>
<p>Occasionally, while a user is editing a record through the <strong>standard AppSheet Detail → Edit form</strong>, values in unrelated <strong>Ref columns</strong> unexpectedly become dates such as:</p>
<p><code>02/14/1900</code><br>
<code>01/04/1900</code></p>
<p>For example, in one occurrence:</p>
<p><strong>Referral Source</strong> → Ref to <code>ReferralSourcesMaster</code><br>
Referenced key: <code>Source ID</code> (Text)</p>
<p><strong>Primary Insurance Name</strong> → Ref to <code>InsuranceMaster</code><br>
Referenced key: <code>Insurance Master ID</code> (Text)</p>
<p>Both Ref columns are physical columns. They have:</p>
<ul>
<li>No App Formula</li>
<li>No Initial Value</li>
<li>No Valid If</li>
<li>No Suggested Values</li>
<li>Reset on edit OFF</li>
<li>Correct Text keys in their referenced tables</li>
</ul>
<p>The issue is intermittent and has occurred in different Ref columns. It does not happen on every edit.</p>
<p>Audit History shows the 1900 date values in the <strong>Edit row Start payload</strong>, and the subsequent update fails with:</p>
<p><code>Unable to update row in table 'Referrals'. → Invalid request provided to AppSheet database</code></p>
<p>The stack trace includes:</p>
<p><code>AsdbProvider.AsdbTable.UpdateRowsAsync</code></p>
<p>The affected users are using the browser and editing through the normal AppSheet form. There are no Quick Edit columns involved.</p>
<p>Current sync settings:</p>
<ul>
<li>Server caching: ON</li>
<li>Delta sync: OFF</li>
<li>Quick sync: ON</li>
<li>Sync on start: ON</li>
<li>Delayed sync: OFF</li>
<li>Automatic updates: ON</li>
</ul>
<p>We have also cleared AppSheet browser/site data for an affected user, but the issue occurred again.</p>
<p>In one failed request, Audit History showed two unrelated Ref fields containing 1900 dates in the same submitted row.</p>
<p>Has anyone experienced Ref values intermittently being converted/interpreted as 1900-era dates when using <strong>AppSheet Database</strong>?</p>
<p>Could this be related to Quick Sync/client row state, or is there another AppSheet Database/Ref configuration I should investigate?</p>
<p>Any suggestions for additional Audit History information I should capture would be appreciated.</p>
            <p><small>4 posts - 2 participants</small></p>
            <p><a href="https://discuss.google.dev/t/intermittent-ref-columns-changing-to-1900-dates-and-causing-invalid-request-provided-to-appsheet-database/397078">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/intermittent-ref-columns-changing-to-1900-dates-and-causing-invalid-request-provided-to-appsheet-database/397078</link>
          <pubDate>Mon, 14 Sep 2026 14:52:31 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397078</guid>
          <source url="https://discuss.google.dev/t/intermittent-ref-columns-changing-to-1900-dates-and-causing-invalid-request-provided-to-appsheet-database/397078.rss">Intermittent Ref columns changing to 1900 dates and causing “Invalid request provided to AppSheet database”</source>
        </item>
        <item>
          <title>Will the New Explore UI Eventually Replace the Classic UI? If So, When?</title>
          <dc:creator><![CDATA[Jjimi]]></dc:creator>
          <category>Looker</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>We noticed that the new Explore UI is now available in Looker.</p>
<p>We understand that both the classic and new versions are currently available. Will both continue to be supported, or is the new UI expected to replace the classic version in the future?</p>
<p>If the classic version will eventually be retired, do you know when that change is planned?</p>
<p>Thank you!</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/will-the-new-explore-ui-eventually-replace-the-classic-ui-if-so-when/397072">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/will-the-new-explore-ui-eventually-replace-the-classic-ui-if-so-when/397072</link>
          <pubDate>Mon, 14 Sep 2026 14:27:37 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397072</guid>
          <source url="https://discuss.google.dev/t/will-the-new-explore-ui-eventually-replace-the-classic-ui-if-so-when/397072.rss">Will the New Explore UI Eventually Replace the Classic UI? If So, When?</source>
        </item>
        <item>
          <title>Send Email automation only delivers to app creator&#39;s own address, even on paid Starter plan</title>
          <dc:creator><![CDATA[Q_M]]></dc:creator>
          <category>AppSheet Q&amp;A</category>
          <description><![CDATA[
            <p>Setup:</p>
<ul>
<li>Plan: AppSheet Starter (paid, $5/user/month)</li>
<li>App status: Deployed (not Prototype)</li>
<li>Account: personal Google account using a public domain (<a href="http://gmail.com" rel="noopener nofollow ugc">gmail.com</a>)</li>
</ul>
<p>What I’m doing:<br>
I have a bot that triggers on “Adds” to a table and runs a “Send an email” task. The To field is set to a column ([Email]) that gets populated by an external script writing rows into the connected Google Sheet via the Sheets API.</p>
<p>What I’m seeing:</p>
<ul>
<li>When the row’s email address is my own account address, the email is delivered successfully.</li>
<li>When the row’s email address is any other address (including other real addresses I personally control and monitor), no email is ever received - no bounce, not in spam/junk.</li>
<li>Automation Monitor always shows the bot run and the “Send an email” step as “Complete,” regardless of recipient.</li>
</ul>
<p>I came across this help article (<a href="https://support.google.com/appsheet/answer/17017639" class="inline-onebox" rel="noopener nofollow ugc">Sending out of domain email from automations not supported - AppSheet Help</a>) stating that as of May 4, 2026, accounts using a public email domain can only send automation emails to their own address unless the account predates that date or belongs to an existing Workspace org.</p>
<p>Questions for the community:</p>
<ol>
<li>Has anyone else hit this on a paid Starter plan? Does upgrading to Core or Enterprise actually lift this restriction, or is it tied strictly to using a public domain (<a href="http://gmail.com" rel="noopener nofollow ugc">gmail.com</a>) account regardless of plan?</li>
<li>Is switching to a Google Workspace account (custom domain) the only real workaround, or is there a way to get a public-domain account added to an allowlist?</li>
<li>Was this limitation something existing Starter subscribers were notified about, or is it a case of the plan being sold without this restriction being clearly disclosed?</li>
</ol>
<p>Any guidance from people who’ve run into and solved this would be much appreciated.</p>
            <p><small>4 posts - 4 participants</small></p>
            <p><a href="https://discuss.google.dev/t/send-email-automation-only-delivers-to-app-creators-own-address-even-on-paid-starter-plan/397069">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/send-email-automation-only-delivers-to-app-creators-own-address-even-on-paid-starter-plan/397069</link>
          <pubDate>Mon, 14 Sep 2026 14:24:38 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397069</guid>
          <source url="https://discuss.google.dev/t/send-email-automation-only-delivers-to-app-creators-own-address-even-on-paid-starter-plan/397069.rss">Send Email automation only delivers to app creator&#39;s own address, even on paid Starter plan</source>
        </item>
        <item>
          <title>FacelessShorts OAuth verification delayed for weeks at Privacy policy requirements, requesting escalation</title>
          <dc:creator><![CDATA[et]]></dc:creator>
          <category>Cloud Foundations &amp; Onboarding</category>
          <description><![CDATA[
            <p>Hello Google team and moderators,</p>
<p>I am requesting help escalating the OAuth verification review for FacelessShorts. We have been waiting for several weeks, and repeated email follow-ups from 25 August through 10 September 2026 have not received a response.</p>
<p>As of 13 September 2026, the Verification Centre shows homepage and branding complete, last reviewed on 8 September. Privacy policy requirements remains in progress and says it is currently under review. App functionality, Appropriate data access, and Request minimum scopes are also in progress.</p>
<p>The delay is blocking us from fully enabling YouTube scheduling and publishing for our customers. We need this resolved as soon as possible and are ready to address any specific outstanding requirement promptly.</p>
<p>Could a Google staff member or moderator please help route this to the OAuth Trust and Safety verification team for urgent manual review? Please confirm whether the submission is actively assigned, identify any exact policy issue or action required from us, and provide an estimated completion time. If all requirements are satisfied, we would appreciate approval as soon as possible.</p>
<p>The Cloud support portal says OAuth is ineligible under our current Basic support plan, so I am seeking an alternative to the unanswered review emails. I can provide the project ID, review correspondence, and other account details through an official private support channel.</p>
<p>Thank you.</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://discuss.google.dev/t/facelessshorts-oauth-verification-delayed-for-weeks-at-privacy-policy-requirements-requesting-escalation/397063">Read full topic</a></p>
          ]]></description>
          <link>https://discuss.google.dev/t/facelessshorts-oauth-verification-delayed-for-weeks-at-privacy-policy-requirements-requesting-escalation/397063</link>
          <pubDate>Mon, 14 Sep 2026 14:05:16 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">discuss.google.dev-topic-397063</guid>
          <source url="https://discuss.google.dev/t/facelessshorts-oauth-verification-delayed-for-weeks-at-privacy-policy-requirements-requesting-escalation/397063.rss">FacelessShorts OAuth verification delayed for weeks at Privacy policy requirements, requesting escalation</source>
        </item>
  </channel>
</rss>
