Skip to main content

setting-up-a-data-warehouse-source

Guide the user through connecting a new data warehouse source — Postgres, MySQL, Stripe, Hubspot, MongoDB, Salesforce, BigQuery, Snowflake, and so on. Use when the user wants to "connect Stripe", "import data from Postgres", "add a new data source", "sync my warehouse tables", or wants to pick sync methods for each table. Walks through source-type discovery, credential validation, table discovery, per-table sync_type selection, and the final create call. Also covers picking a good prefix and what to do right after creation.

Quellinformationen

Repository
PostHog/ai-plugin
Letzte Quellaktivität
5. Oktober 2026 um 12:50
Erkannte Sprache von SKILL.md
Englisch
Sterne
88
Forks
18

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
setting-up-a-data-warehouse-source
description
Guide the user through connecting a new data warehouse source — Postgres, MySQL, Stripe, Hubspot, MongoDB, Salesforce, BigQuery, Snowflake, and so on. Use when the user wants to "connect Stripe", "import data from Postgres", "add a new data source", "sync my warehouse tables", or wants to pick sync methods for each table. Walks through source-type discovery, credential validation, table discovery, per-table sync_type selection, and the final create call. Also covers picking a good prefix and what to do right after creation.
# Setting up a data warehouse source Use this skill when the user wants to connect an external data source to PostHog's data warehouse for the first time. **Default to the one-step flow:** `data-warehouse-source-setup` validates credentials, discovers every table, enables them with sensible sync defaults (incremental where possible), and creates the source in a single call — no `schemas` array to assemble. For credentials, hand the user a secure browser link with `data-warehouse-source-connect-link` instead of collecting secrets in chat. Only drop to the manual `wizard → db-schema → create` flow when the user wants to hand-pick which tables sync or set non-default sync types per table. ## When to use this skill - The user wants to connect a new source: "connect Stripe", "import my Postgres orders table", "sync Hubspot contacts" - The user isn't sure what source types PostHog supports - The user has credentials but doesn't know how to structure the `schemas` payload - The user wants guidance on which sync method to pick per table ## Available tools | Tool | Purpose | | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | `data-warehouse-source-connect-link` | **Preferred for credentials** — get a secure browser/OAuth link so the user authenticates without pasting secrets in chat | | `data-warehouse-source-setup` | **Preferred to create** — one call: validate creds, discover tables, apply sync defaults, create the source | | `external-data-sources-wizard` | Discover which source types exist and what fields each needs (advanced flow) | | `external-data-sources-db-schema` | Validate credentials and list tables with available sync methods per table (advanced flow) | | `external-data-sources-create` | Advanced create — requires a `schemas` array built from the db-schema response | | `external-data-sources-check-cdc-prerequisites-create` | Postgres CDC pre-flight check (optional, only for Postgres CDC) | | `external-data-sources-webhook-info-retrieve` | Check if a source supports webhooks and whether one has been registered | | `external-data-sources-create-webhook-create` | Register a webhook with the external service after source creation | | `external-data-sources-update-webhook-inputs-create` | Supply the signing secret manually when auto-registration failed | | `external-data-sources-list` | After creation, confirm the source is listed and see its initial status | | `external-data-schemas-list` | See per-table sync status once the source is created | ## Pre-flight: credential gotchas that cause most failures Surface these **before** collecting credentials — they're the top reasons setup fails on the first try. Validating against them up front avoids burning credential prompts on retries. - **The host must be reachable from PostHog's network.** `localhost`, `127.0.0.1`, and private/RFC-1918 hosts (`10.x`, `192.168.x`, `172.16–31.x`) are rejected — PostHog runs the connection from its own infrastructure, not the user's machine. Serverless/managed Postgres (Neon, Supabase, RDS behind strict rules) often also needs PostHog's egress IPs allowlisted first. If the DB isn't publicly reachable, route to the browser deep-link (`data-warehouse-source-connect-link`) or an SSH tunnel rather than collecting credentials that can't validate. - **Supabase is Postgres — don't collect it twice.** Use the **Session pooler** connection, not the direct host (the direct host is IPv6-only). The pooler host looks like `aws-0-<region>.pooler.supabase.com`, the **username** must be `postgres.<project-ref>`, and the **port is 6543** (not 5432). The password is the **database** password (Settings → Database), which is distinct from the `anon`/`service_role` JWT keys and from the Supabase account password. If `SUPABASE_URL` is in the project env, derive the project ref from `db.<ref>.supabase.co` to pre-fill these instead of asking the user to guess. - **Many SaaS sources need a specific key type or plan** — get the right one before the create call fails: - **Stripe** — a _restricted_ key (`rk_live_…`), not the standard secret key (`sk_live_…`). - **RevenueCat** — a v2 secret key (`sk_…`) with the read scopes enabled. - **Sentry** — an internal-integration token, not a DSN and not a personal auth token. - **Convex** — requires the Professional plan. - **Twilio** — API Key SID + Secret, not the account auth token. - **Mailchimp** — the key carries its datacenter suffix (`key-usX`). - For send-only services (Resend, Mailgun), the key already in the project env is often restricted; the warehouse import needs a full/read-access key. - **Never pass an unresolved secret reference.** If a credential field is still a `{"secretRef": ...}` object, PostHog can't resolve it — the create/db-schema/setup calls reject it with a clear error. Resolve it to the real value first, or collect credentials via `data-warehouse-source-connect-link` and pass the resulting `credential_id`. ## Recommended: one-step setup Most setups should use this path — it avoids the most common failures (skipping db-schema, malformed `schemas`, missing required fields). 1. **Discover the source type and its fields** (optional): `external-data-sources-wizard` lists every source type and the credential fields each needs. Use it to know what to ask the user for; skip it if the source type is obvious. 2. **Collect credentials securely**: call `data-warehouse-source-connect-link({source_type})`. It returns a `connect_url` to a minimal connect page rendering the source's full connection form — the user authorizes via OAuth or enters credentials there, whichever the source offers (the response's `auth_method` tells you which to expect). The page validates the details against a live connection and stashes them encrypted in a temporary store — it does NOT create the source. After the user confirms they're done, find the stored credential id via `data-warehouse-stored-credentials-list` (filter by `source_type`, newest first; the page also shows the id to the user) and pass `{"credential_id": <id>}` to setup. Stored credentials are single-use — deleted as soon as setup consumes them — and expire after 24 hours. Never ask the user to paste raw database passwords, API keys, or OAuth tokens into the chat. 3. **Create in one call**: `data-warehouse-source-setup({source_type, payload, prefix})`. The server validates credentials, discovers all tables, enables them with sync defaults (incremental where a tracking column exists, else append, else full_refresh — never CDC), sets `created_via=mcp`, and creates the source. The `payload` carries a credential reference (`{"credential_id": ...}` or the OAuth integration id key) — or inline credentials for headless automation; no `schemas` array is needed. On success you get the new source `id`; call `external-data-schemas-list` to show the user what was enabled and how each table will sync. Notes specific to this path: - **All discovered tables are enabled.** That's intended (incremental defaults keep ongoing cost low), but flag row counts for very large tables and offer the advanced flow if the user wants to sync only a subset. - **Webhooks are auto-registered** for sources that support them (currently Stripe). Check the `webhook` key in the setup response: on success, webhook-capable tables sync in real time and webhook-only tables (e.g. Stripe Discount) are enabled too; on failure (e.g. the API key can't create webhooks), tables keep the polling defaults and webhook-only tables stay disabled — relay the `webhook.error` to the user and offer Step 6 to register manually. If `webhook.pending_inputs` is non-empty, collect those values and submit via `external-data-sources-update-webhook-inputs-create`. CDC is never chosen automatically; use the advanced flow + CDC steps for near-real-time Postgres. - Inline credentials in `payload` still work for headless/automation, but prefer the connect-link handoff above. ## Advanced: hand-pick tables (three-step flow) Use this when the user wants to choose exactly which tables sync or set non-default sync types. Don't try to shortcut to `external-data-sources-create` — you need the db-schema response to build a valid `schemas` payload. ```text ┌────────────────────┐ │ 1. wizard │ What source types exist? What fields does each need? └────────┬───────────┘ ▼ ┌────────────────────┐ │ 2. db-schema │ Validate creds. List tables + available sync methods per table. └────────┬───────────┘ ▼ ┌────────────────────┐ │ 3. create │ Send source_type + credentials + schemas[] to actually create. └────────────────────┘ ``` ## Workflow ### Step 1 — Discover the source type Call `external-data-sources-wizard` **with `source_type` set to the kind(s) you need** (comma-separated, e.g. `Postgres,Stripe`). The unfiltered response describes every supported source and is hundreds of KB — large enough to blow your context budget. Only omit `source_type` when you genuinely need to enumerate every available type, and when you do, pass `fields: ['*.name', '*.caption']` so the response carries just the names instead of every source's config field definitions. The response is a dict keyed by source type. Each entry describes: - `name` — the canonical source_type string you'll pass to later calls (e.g. `"Postgres"`, `"Stripe"`, `"Hubspot"`). - `caption` — human-readable description. - `fields` — the config fields needed (host, port, database, api_key, client_id/secret, ...). Each has `name`, `type` (input, password, switch, select, file-upload), and `required`. - `featured`, `unreleasedSource` — use to gauge readiness. Skip sources marked `unreleasedSource: true` unless the user explicitly asked for a preview. Match the user's request to a source. If they said "Postgres", look up `Postgres`. If they said something ambiguous like "database", present the top relevant matches (Postgres, MySQL, MongoDB, BigQuery, Snowflake, Redshift) and let them pick. For OAuth-based sources (Hubspot, Salesforce, Google Ads), the wizard entry hints at an OAuth flow. These typically need the user to authorize in the PostHog UI rather than pasting credentials — explain this and direct them to the source setup page rather than trying to collect tokens in chat. OAuth is about _authentication_, not about how data flows; OAuth sources still use polling bulk sync, not webhooks. Gather the required credentials from the user. Never ask for more fields than the wizard entry says are required — asking for an unnecessary `port` when the source doesn't need one confuses users. ### Step 2 — Validate credentials and discover tables Call `external-data-sources-db-schema` with `source_type` plus all credential fields. This does two things at once: 1. Validates the credentials against the live source. Returns 400 with a `message` if anything is wrong (bad host, wrong password, permission denied). Show the error verbatim — it's often actionable ("password authentication failed for user 'x'"). 2. If valid, returns an array of table entries. Each entry: ```text { "table": "orders", "should_sync": false, "rows": 1_250_000, "incremental_available": true, # can do sync_type=incremental "append_available": true, # can do sync_type=append "cdc_available": true, # can do sync_type=cdc (null = not enabled for team) "supports_webhooks": false, # can do sync_type=webhook for real-time push "incremental_fields": [ # candidates: usually updated_at, created_at, id {"field": "updated_at", "type": "datetime", "label": "updated_at", ...}, {"field": "created_at", "type": "datetime", ...}, {"field": "id", "type": "integer", ...} ], "detected_primary_keys": ["id"], "available_columns": [{"field": "id", "type": "integer", "nullable": false}, ...], "description": "..." } ``` Present this to the user. Don't dump the raw JSON — summarize: which tables were found, row counts, and the default sync method recommendation per table (see [sync-type decision guide](./references/sync-types.md)). ### Step 3 — Confirm per-table sync configuration For each table the user wants to sync, pick a sync_type. See the [sync-type decision guide](./references/sync-types.md) for detailed rules, but the short version is: - **Small / dimension tables (<50k rows, no natural ordering column):** `full_refresh` — simple and always correct. - **Large tables with an `updated_at` / `modified_at`:** `incremental` — much cheaper per sync. - **Append-only immutable tables (logs, events):** `append` if available — preserves history. - **Postgres with CDC enabled and you need near-real-time:** `cdc` — requires primary keys and Postgres prerequisites. - **Sources that support webhooks (currently Stripe):** for near-real-time ingestion set `sync_type: "webhook"` on the tables where `supports_webhooks: true`, then register the webhook as a post-create step (see step 6 below). Tables that don't support webhooks on the same source still need a bulk sync_type. For each schema that will use `incremental`/`append`/`cdc`, you also need: - `incremental_field` — which column to track for high-water-mark ordering. Pick from the `incremental_fields` list returned by db-schema. Prefer `updated_at` over `created_at` (updated_at catches late-arriving updates; created_at misses them). For integer-only tables, use the monotonically increasing primary key. - `incremental_field_type` — must match the chosen field's type (`datetime`, `timestamp`, `date`, `integer`, `numeric`, `objectid`). - `primary_key_columns` — required for CDC. Use `detected_primary_keys` from db-schema. ### Step 4 — Pick a good prefix The source's `prefix` is prepended to table names in HogQL. Tables end up as `{prefix}_{table_name}`. - Default to the source type lowercased if there's only one source of that type: `stripe`, `postgres`. - If the user already has a Postgres source, pick something distinguishing: `postgres_prod`, `postgres_analytics`. - Use lowercase, underscore-separated. The prefix becomes part of every HogQL query the user writes. Confirm the prefix with the user before creating — changing it later is possible but renames every table. ### Step 5 — Create the source Call `external-data-sources-create` with: ```json { "source_type": "Postgres", "prefix": "postgres_prod", "payload": { "host": "...", "port": "5432", "dbname": "...", "user": "...", "password": "...", "schema": "public", "schemas": [ { "name": "orders", "should_sync": true, "sync_type": "incremental", "incremental_field": "updated_at", "incremental_field_type": "datetime", "primary_key_columns": ["id"] }, { "name": "users", "should_sync": true, "sync_type": "full_refresh" }, { "name": "audit_log", "should_sync": false } ] } } ``` Rules for the `schemas` array: - Every table returned by db-schema should be included, even ones the user doesn't want (set `should_sync: false`). Tables the user didn't mention default to `should_sync: false`. - `sync_type` is required only when `should_sync: true`. - `incremental_field` / `incremental_field_type` must be present when `sync_type` is `incremental` or `append`. - `primary_key_columns` must be present when `sync_type` is `cdc`. On success you'll get back a source with a new `id`. The first sync is triggered automatically. ### Step 6 — Register a webhook (only when any schema is `sync_type: "webhook"`)
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen