关于 setting-up-a-data-warehouse-source
这项 PostHog 技能指导将外部数据源接入数据仓库,涵盖安全收集凭据和单步设置,也提供手动选择表与同步方式的流程。
主要功能
- 01通过安全浏览器链接交接凭据
- 02单次调用创建数据源
- 03发现数据表并应用同步默认值
- 04手动选择数据表和同步方式
- 05Webhook 与 CDC 配置指引
适用场景
- 01接入新的 Stripe 或 Postgres 数据源
- 02选择要同步的数据表
- 03为数据表设置非默认同步方式
- 04注册 Webhook 或配置 Postgres CDC
MCP 相关
该技能指导使用 PostHog MCP 工具发现、验证和创建数据仓库数据源,并配置数据表、Webhook 和 CDC。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ skills --skill setting-up-a-data-warehouse-source安装后在 Claude Code 中输入/setting-up-a-data-warehouse-source确认已加载。
附带文件references/sync-types.md
详细介绍
设置数据仓库数据源
当用户想首次将外部数据源连接到 PostHog 数据仓库时,使用此技能。
默认使用一步式流程: data-warehouse-source-setup 会验证凭据、发现所有表、使用合理的同步默认设置(尽可能采用增量同步)启用这些表,并在一次调用中创建数据源,无需组装 schemas 数组。对于凭据,使用 data-warehouse-source-connect-link 为用户提供安全的浏览器链接,而不是在聊天中收集机密信息。只有当用户想手动挑选要同步的表,或为每张表设置非默认同步类型时,才使用手动的 wizard → db-schema → create 流程。
何时使用此技能
- 用户想连接新的数据源:“连接 Stripe”“导入我的 Postgres 订单表”“同步 Hubspot 联系人”
- 用户不确定 PostHog 支持哪些数据源类型
- 用户有凭据,但不知道如何构造
schemas载荷 - 用户想了解每张表应选择哪种同步方式
可用工具
| 工具 | 用途 |
|---|---|
data-warehouse-source-connect-link | 凭据首选方式 — 获取安全的浏览器/OAuth 链接,让用户完成身份验证,而无需在聊天中粘贴机密信息 |
data-warehouse-source-setup | 创建首选方式 — 一次调用即可验证凭据、发现表、应用同步默认设置并创建数据源 |
external-data-sources-wizard | 发现现有的数据源类型及各类型所需的字段(高级流程) |
external-data-sources-db-schema | 验证凭据并列出各表可用的同步方式(高级流程) |
external-data-sources-create | 高级创建方式 — 需要根据 db-schema 响应构建 schemas 数组 |
external-data-sources-check-cdc-prerequisites-create | Postgres CDC 预检(可选,仅用于 Postgres CDC) |
external-data-sources-webhook-info-retrieve | 检查数据源是否支持 Webhook,以及是否已注册 Webhook |
external-data-sources-create-webhook-create | 创建数据源后,向外部服务注册 Webhook |
external-data-sources-update-webhook-inputs-create | 自动注册失败时,手动提供签名密钥 |
external-data-sources-list | 创建后,确认数据源已列出并查看其初始状态 |
external-data-schemas-list | 创建数据源后,查看各表的同步状态 |
准备工作:导致大多数失败的凭据注意事项
收集凭据之前,请先说明这些注意事项——它们是首次设置失败的主要原因。提前检查这些问题,可以避免重试时反复提示用户输入凭据。
- PostHog 的网络必须能够访问该主机。
localhost、127.0.0.1和私有/RFC-1918 主机(10.x、192.168.x、172.16–31.x)都会被拒绝——PostHog 会从自己的基础设施发起连接,而不是从用户的机器发起。无服务器/托管式 Postgres(Neon、Supabase、受严格规则限制的 RDS)通常也需要先将 PostHog 的出口 IP 加入允许列表。如果数据库无法通过公网访问,请改用浏览器深层链接(data-warehouse-source-connect-link)或 SSH 隧道,而不要收集无法通过验证的凭据。 - Supabase 就是 Postgres——不要重复收集。 使用 Session pooler 连接,而不要使用直连主机(直连主机仅支持 IPv6)。连接池主机格式类似
aws-0-<region>.pooler.supabase.com,用户名必须是postgres.<project-ref>,端口为 6543(而不是 5432)。密码是数据库密码(Settings → Database),与anon/service_roleJWT 密钥以及 Supabase 账户密码不同。如果项目环境中有SUPABASE_URL,请从db.<ref>.supabase.co提取项目 ref 并预先填入这些信息,而不要让用户猜测。 - 许多 SaaS 数据源需要特定类型的密钥或套餐——请在创建调用失败之前获取正确的信息:
- Stripe — 使用 restricted 密钥(
rk_live_…),而不是标准的 secret 密钥(sk_live_…)。 - RevenueCat — 使用启用了读取权限范围的 v2 secret 密钥(
sk_…)。 - Sentry — 使用内部集成令牌,而不是 DSN 或个人身份验证令牌。
- Convex — 需要 Professional 套餐。
- Twilio — 使用 API Key SID + Secret,而不是账户身份验证令牌。
- Mailchimp — 密钥包含数据中心后缀(
key-usX)。 - 对于仅发送服务(Resend、Mailgun),项目环境中已有的密钥通常受限;数据仓库导入需要具有完整/读取访问权限的密钥。
- Stripe — 使用 restricted 密钥(
- 绝不要传递尚未解析的密钥引用。 如果凭据字段仍是
{"secretRef": ...}对象,PostHog 就无法解析它——create/db-schema/setup 调用会报出明确错误并拒绝请求。请先将其解析为实际值,或者通过data-warehouse-source-connect-link收集凭据,并传递得到的credential_id。
推荐:一步完成设置
大多数设置都应使用此路径 — 它可以避免最常见的失败情况(跳过 db-schema、schemas 格式错误、缺少必填字段)。
-
发现数据源类型及其字段(可选):
external-data-sources-wizard会列出所有数据源类型及其所需的凭据字段。用它来了解需要向用户询问哪些信息;如果数据源类型显而易见,则跳过此步骤。 -
安全收集凭据:调用
data-warehouse-source-connect-link({source_type})。它会返回一个connect_url,指向一个精简的连接页面,该页面会显示数据源的完整连接表单 — 用户可通过 OAuth 授权,或在页面中输入凭据,具体取决于数据源提供的方式(响应中的auth_method会告知你预期的方式)。页面会通过实时连接验证信息,并将其加密后存入临时存储 — 它不会创建数据源。用户确认完成后,通过data-warehouse-stored-credentials-list查找已存储凭据的 ID(按source_type筛选,最新的排在最前;页面也会向用户显示该 ID),并将{"credential_id": <id>}传给设置流程。已存储的凭据只能使用一次 — 设置流程使用后会立即删除 — 并会在 24 小时后过期。切勿要求用户在聊天中粘贴原始数据库密码、API 密钥或 OAuth 令牌。
-
一次调用即可创建:
data-warehouse-source-setup({source_type, payload, prefix})。服务会验证凭据、发现所有表、按同步默认值启用这些表(存在跟踪列时使用增量同步,否则使用追加同步,再否则使用 full_refresh — 绝不使用 CDC)、设置created_via=mcp,并创建数据源。payload中包含凭据引用({"credential_id": ...}或 OAuth 集成 ID 键)— 也可以用于无头自动化的内联凭据;不需要schemas数组。成功后会返回新数据源的id;调用external-data-schemas-list,向用户展示已启用的表及各表的同步方式。
此路径的注意事项:
- **所有发现的表都会启用。**这是有意为之(增量默认设置可降低持续成本),但对于非常大的表,应提示其行数,并在用户只想同步部分表时提供高级流程。
- 支持 Webhook 的数据源会自动注册 Webhook(目前为 Stripe)。检查设置响应中的
webhook键:成功时,支持 Webhook 的表会实时同步,仅支持 Webhook 的表(例如 Stripe Discount)也会启用;失败时(例如 API 密钥无法创建 Webhook),表会保留轮询默认设置,仅支持 Webhook 的表会保持禁用 — 向用户转达webhook.error,并提供第 6 步以手动注册。如果webhook.pending_inputs非空,请收集这些值并通过external-data-sources-update-webhook-inputs-create提交。不会自动选择 CDC;对于近实时 Postgres,请使用高级流程和 CDC 步骤。 payload中仍可使用内联凭据进行无头操作或自动化,但优先使用上述连接链接交接方式。
高级:手动选择表(三步流程)
当用户想精确选择要同步的表,或设置非默认同步类型时,请使用此流程。不要尝试跳过步骤,直接调用 external-data-sources-create — 你需要 db-schema 响应才能构建有效的 schemas 载荷。
┌────────────────────┐
│ 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.
└────────────────────┘
工作流
步骤 1 — 发现源类型
调用 external-data-sources-wizard,并将 source_type 设为你需要的类型(用逗号分隔,例如
Postgres,Stripe)。未筛选的响应会描述所有受支持的源,大小达数百 KB,足以耗尽上下文预算。只有在确实需要枚举所有可用类型时才省略 source_type;此时请传入 fields: ['*.name', '*.caption'],这样响应只包含名称,而不是每个源的所有配置字段定义。响应是一个以源类型为键的字典。每个条目描述:
name— 规范的source_type字符串,供后续调用传入(例如"Postgres"、"Stripe"、"Hubspot")。caption— 面向用户的描述。fields— 所需的配置字段(host、port、database、api_key、client_id/secret 等)。每个字段都有name、type(input、password、switch、select、file-upload)和required。featured、unreleasedSource— 用于判断就绪情况。跳过标记为unreleasedSource: true的源,除非用户明确要求预览版。
根据用户的请求匹配源。如果他们说“Postgres”,就查找 Postgres。如果他们说的内容含糊,例如“数据库”,就列出最相关的选项(Postgres、MySQL、MongoDB、BigQuery、Snowflake、Redshift),让他们选择。
对于基于 OAuth 的源(Hubspot、Salesforce、Google Ads),向导条目会提示 OAuth 流程。这类源通常需要用户在 PostHog UI 中授权,而不是粘贴凭据——请说明这一点,并引导他们前往源设置页面,而不要尝试在聊天中收集令牌。OAuth 关乎_身份验证_,而非数据流动方式;OAuth 源仍使用轮询批量同步,而不是 Webhook。
向用户收集所需凭据。不要询问超出向导条目所列必需项的字段——如果源不需要 port,询问这个字段只会让用户困惑。
步骤 2 — 验证凭据并发现表
调用 external-data-sources-db-schema,并传入 source_type 和所有凭据字段。此调用会同时完成两件事:
- 根据实时源验证凭据。如果有误(主机错误、密码错误、权限被拒绝),则返回带有
message的 400 错误。原样展示错误信息——它通常能提供可采取行动的提示(“用户 'x' 的密码身份验证失败”)。 - 如果凭据有效,则返回一个表条目数组。每个条目:
{
"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": "..."
}
将这些信息呈现给用户。不要直接输出原始 JSON,而要概述:发现了哪些表、行数,以及每张表推荐的默认同步方法(参见同步类型决策指南)。
步骤 3 — 确认每个表的同步配置
对于用户想要同步的每个表,选择一种 sync_type。详细规则请参阅 sync-type 决策指南,简而言之:
- 小型/维度表(<50k 行,且没有自然排序列):
full_refresh— 简单且始终正确。 - 包含
updated_at/modified_at的大型表:incremental— 每次同步的成本低得多。 - 只追加且不可变的表(日志、事件): 如果可用,使用
append— 保留历史记录。 - 启用了 CDC 的 Postgres,且需要近实时同步:
cdc— 需要主键和 Postgres 前置条件。 - 支持 Webhook 的数据源(目前为 Stripe): 若要实现近实时摄取,请对
supports_webhooks: true的表设置sync_type: "webhook",然后将 Webhook 注册为创建后的步骤(见下文步骤 6)。 同一数据源中不支持 Webhook 的表仍需要使用批量 sync_type。
对于将使用 incremental / append / cdc 的每个 schema,还需要:
incremental_field— 用于跟踪高水位标记排序的列。从 db-schema 返回的incremental_fields列表中选择。优先选择updated_at而非created_at(updated_at能捕获延迟到达的更新;created_at则会漏掉这些更新)。对于只有整数列的表,使用单调递增的主键。incremental_field_type— 必须与所选字段的类型匹配(datetime、timestamp、date、integer、numeric、objectid)。primary_key_columns— CDC 必填。使用 db-schema 中的detected_primary_keys。
步骤 4 — 选择合适的前缀
数据源的 prefix 会添加到 HogQL 中的表名之前。表名最终为 {prefix}_{table_name}。
- 如果只有一个该类型的数据源,默认使用小写的数据源类型:
stripe、postgres。 - 如果用户已有一个 Postgres 数据源,请选择有区分度的名称:
postgres_prod、postgres_analytics。 - 使用小写字母并以下划线分隔。该前缀会成为用户编写的每个 HogQL 查询的一部分。
创建前请与用户确认前缀——之后可以更改,但会重命名每个表。
步骤 5 — 创建数据源
使用以下参数调用 external-data-sources-create:
{
"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
}
]
}
}
schemas 数组的规则:
- 必须包含 db-schema 返回的每个表,包括用户不想同步的表(将
should_sync: false)。用户未提及的表默认设置为should_sync: false。 - 仅当
should_sync: true时才需要sync_type。 - 当
sync_type为incremental或append时,必须提供incremental_field/incremental_field_type。 - 当
sync_type为cdc时,必须提供primary_key_columns。
成功后,你会获得一个带有新 id 的数据源。首次同步会自动触发。
步骤 6 — 注册 webhook(仅当某个 schema 的 sync_type 为 "webhook" 时)
Webhook 类型的 schema 不会仅凭存在就开始接收数据——外部服务需要知道要向哪里 POST 事件,PostHog 也需要知道如何验证这些事件。这是在创建数据源后进行的第二次调用,不属于 external-data-sources-create 载荷的一部分。务必在告知用户设置已完成之前执行此操作,否则用户会听到“同步正在运行”,但推送通道其实尚未注册。
仅当数据源上至少有一个 schema 的 sync_type 为 "webhook" 且 should_sync: true 时,才需要执行此步骤。目前只有 Stripe 支持此流程;其他情况均跳过此步骤。
调用 create-webhook 前,先检查 external-data-sources-webhook-info-retrieve({id})。如果返回 exists: true,请勿再次调用 create-webhook——每次成功调用都会注册一个新的外部端点,从而导致重复投递。
-
调用
external-data-sources-create-webhook-create({id})。PostHog 会:- 创建用于接收 webhook POST 请求的 HogFunction,
- 根据外部事件类型和 PostHog schema ID 构建 schema_mapping,
- 调用数据源的 API(例如 Stripe),注册 webhook URL 并订阅相关事件,
- 在 Stripe 上自动捕获
signing_secret并安全存储。
返回
{success, webhook_url, error}。如果成功,请将webhook_url告知用户以供记录——但他们无需在任何地方粘贴此 URL;注册已完成。 -
如果
success: false且返回类似“API key doesn't have permission to create webhooks”的权限错误:- HogFunction 仍会创建,但处于禁用状态。
- 请用户在数据源的控制面板中使用返回的
webhook_url手动创建 webhook。 - 请用户从数据源的 webhook 设置中复制 signing secret。
- 调用
external-data-sources-update-webhook-inputs-create({id}, {inputs: {signing_secret: "whsec_..."}})进行存储。HogFunction 会获取此密钥并验证传入的载荷。
-
使用
external-data-sources-webhook-info-retrieve({id})验证。运行正常的 webhook 应满足:exists: true、external_status.status: "enabled",且没有error。
Webhook 是批量同步的补充。启用 webhook 的 schema 首次加载仍通过轮询完成(完成后 initial_sync_complete 会变为 true);此后,webhook 会成为主要的数据接入方式。Webhook schema 仍会有一个 sync_frequency,用于安排定期批量刷新作为安全保障。这是预期行为——无需“修复”。
步骤 7 — 确认并说明后续情况
创建完成后(对于 webhook schema,则在完成步骤 6 后):
- 调用
external-data-schemas-list,向用户展示初始状态。 - 说明:每个已启用的 schema 都会进入
Running状态,然后在首次同步完成后变为Completed。首次同步可能需要几秒到几小时,具体取决于行数——数百万行的表也可以,只是速度较慢。 - 告知用户如何查询:在 HogQL 中执行
SELECT * FROM {prefix}_{table_name} LIMIT 10。 - 询问用户是否希望你几分钟后再检查一次,以确认首次同步成功。
Postgres 的 CDC 设置(可选,按需执行)
如果用户希望从 Postgres 进行近实时复制:
- 调用 db-schema 前,使用用户的 Postgres 凭据运行
external-data-sources-check-cdc-prerequisites-create。它会返回{valid, errors[]},列出所有缺失项(wal_level、复制槽、发布、权限)。 - 如果
valid: false,请列出错误并让用户在 Postgres 端修复。不要尝试创建一个会立即失败的 CDC 数据源。 - 前置条件通过后,继续执行 db-schema 并创建数据源。对需要 CDC 的表设置
sync_type: "cdc",并为每张表提供primary_key_columns(CDC 必须包含这些列)。
重要说明
- 创建前务必使用 db-schema 验证凭证。 创建端点会接受无效凭证,随后异步失败——数据源会以
Error状态出现在列表中,且没有任何表。跳过验证步骤,只是把失败推到了后台。 - 创建前先展示表列表。 大型数据库可能有数百张表。不要自动全选——行数和相关性会影响计费。让用户明确选择。
- 不要虚构架构。
schemas数组中的每个条目都必须对应 db-schema 响应中的真实表。除非 db-schema 找到了订单表,否则不能“顺便添加一个订单表”。 - 新数据源会同步到 PostHog 数据仓库。 这是默认设置,无需配置:未配置目标位置的数据源只会写入此处,不会写入其他位置。部分项目也可以将数据源的表发送到自己的数据库(如果项目启用了此功能,
external-data-sources-destinations-retrieve会显示数据源写入的位置)。这需要单独设置,绝不能作为创建数据源的一部分——向已完成同步的数据源添加目标位置后,在重新同步表之前,该目标位置不会有任何历史数据;重新同步会对数据源写入的每个目标位置计费。 - 前缀至关重要。 用户今后针对这些表编写的每条 HogQL 查询都会用到它。请选一个简短、描述性强且尚未被占用的前缀。
- 凭证优先使用安全的连接链接。 使用
data-warehouse-source-connect-link,让用户在浏览器中完成身份验证——连接页面会呈现数据源的完整连接表单(包括 OAuth 和凭证选项),并保存结果,而不会创建数据源。不要在聊天中收集 OAuth 令牌或数据库密码;将credential_id引用传递给 setup——数据源始终通过 setup 创建,而不是通过 UI 创建。(也可以直接通过其 id 键传入已连接的 OAuth 集成,例如{"hubspot_integration_id": 123}。) - Webhook 需要在创建后单独设置。 在架构上设置
sync_type: "webhook"不会注册 webhook——需要调用create-webhook。对于 webhook 类型的架构,务必依次执行 create → create-webhook → webhook-info;绝不能让 webhook 架构处于未注册状态(否则不会收到事件)。 - Webhook 支持因数据源而异,且覆盖范围有限。 目前只有 Stripe 实现了
WebhookSource。不要承诺 Hubspot、Salesforce 或 Postgres 支持 webhook——它们会使用轮询同步。 - 行数决定计费。 数据仓库同步按同步的行数计费。每小时同步一个频繁产生数据、包含 5 亿行的 events 表,与每天同步一个包含 1 万行的维度表,成本截然不同。请标记大型表,并默认提供更长的同步频率(
sync_frequency: "24hour")。