Read the story

Architecture

Lets Claude query marketing data.Each person signs in once.

People on the list add the connector in Claude and sign in with Google once. Each question runs as one SELECT against that person's own BigQuery dataset of views, built from the boxes an owner ticked, and Claude ends every answer with where the numbers came from.

3 hours

from the first connector code at 12:06 PM on Oct 23 to the live service

13 boxes

an owner ticks per person; each set of boxes gets its own dataset of views

469 calls

from 3 people in the first seven days, Oct 23 to 29, 364 of them queries

39 of 40

golden questions passed through Claude on the main branch code, Oct 27; all 40 answers were correct

New York --:-- simulated

A question in Claude
Hybridge Data Connector People on the list add the connector in Claude and sign in with Google once. Each question runs as one SELECT against that person's own BigQuery dataset of views, built from the boxes an owner ticked, and Claude ends every answer with where the numbers came from. Google Ads search and PMax Microsoft Ads Reporting v13 Meta Ads Graph v21 Facebook, Instagram organic insights CallRail calls and forms Monday boards leads, patients GA4 website traffic Search Console queries, pages Business Profile listings, keywords TapClicks agency TV, print Monday export Google Drive Data Transfer managed, Google Ads Source pulls 9 Cloud Run jobs, 6 AM Export import Drive to BigQuery BigQuery raw MERGE upserts Staging and marts tested metrics Connector views job, 6:20 AM Per person views one dataset per set Owner page 13 boxes per person Google sign in openid and email Data connector Cloud Run, MCP SQL guard one SELECT only Firestore people, sessions Marketing team asks the question Claude web, desktop, phone load MERGE MERGE SQL models rebuild views scoped SQL boxes once MCP asks GCP hybridge-mktg-data

Hover a part to trace what it touches. Click it for its notes.

  • Built by me
  • Managed by Google
  • Outside system
  • Main data path
  • On demand
  • Credentials cross

When it breaks

What each failure does, and what it does not do.

  1. BigQuery stalls

    Every BigQuery call on the request path has a timeout, 20 to 30 seconds for metadata and job starts, so a stuck API cannot hold a worker thread.

    src/data_connector/datasets.py:30

  2. The service goes down

    An uptime check calls /health every five minutes and emails me when it fails. One instance stays warm for the first question of the day.

    deploy/setup_connector.sh:93

  3. A query asks too much

    Past 25 GB, 90 seconds or 1,000 rows, Claude gets a sentence telling it to filter by date or aggregate first.

    src/data_connector/queries.py:21

What I tuned

Small choices that keep it fast and cheap.

  1. Sign in once

    Access tokens last 7 days and refresh tokens 10 years, kept encrypted in Firestore. Google's own refresh token is the real limit.

    src/data_connector/server.py:61

  2. Views built at 6:20

    After a deploy changes the table rules, the morning job rebuilds every set of views before anyone asks a question.

    src/data_connector/prebuild.py

  3. Google checks cached

    A checked Google token is trusted for five minutes before Google is asked again.

    src/data_connector/server.py:66

Guards

Rules the code enforces, not rules people remember.

  1. Boxes enforced in BigQuery

    Each set of boxes is its own dataset of authorized views. The query identities can read those datasets and cannot read marts, staging or raw directly.

    src/data_connector/datasets.py:1

  2. One SELECT, own dataset

    The guard parses every query, refuses anything but a single SELECT, and points each table at the person's own dataset.

    src/data_connector/sql_guard.py:69

  3. New tables start hidden

    Every warehouse table needs a rule in the catalog before anyone sees it. Names and phone numbers need the patient box.

    src/data_connector/catalog.py:1