[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-posthog-auditing-warehouse-data-health":3,"mdc-qp7c7x-key":37,"related-repo-posthog-auditing-warehouse-data-health":1139,"related-org-posthog-auditing-warehouse-data-health":1242},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":26,"repoUrl":27,"updatedAt":28,"license":29,"forks":30,"topics":31,"repo":32,"sourceUrl":35,"mdContent":36},"auditing-warehouse-data-health","audit PostHog data warehouse health","Audit the health of a PostHog project's data warehouse — find every broken or degraded pipeline item across sources, sync schemas, materialized views, batch exports, and transformations. Use when the user asks \"what's broken in my warehouse?\", \"give me a health check\", \"audit my data pipeline\", \"why are some dashboards stale?\", or wants a one-shot triage summary before deciding where to spend time. Produces a prioritized report of issues grouped by severity and type, with recommended next steps.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"posthog","PostHog","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fposthog.png",[12,16,17,20,23],{"name":13,"slug":14,"type":15},"Observability","observability","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"Data Quality","data-quality",{"name":21,"slug":22,"type":15},"Data Engineering","data-engineering",{"name":24,"slug":25,"type":15},"Audit","audit",56,"https:\u002F\u002Fgithub.com\u002FPostHog\u002Fskills","2026-06-21T08:19:05.85849",null,4,[],{"repoUrl":27,"stars":26,"forks":30,"topics":33,"description":34},[],"PostHog skills (under construction)","https:\u002F\u002Fgithub.com\u002FPostHog\u002Fskills\u002Ftree\u002FHEAD\u002Fskills\u002Fomnibus\u002Fauditing-warehouse-data-health","---\nname: auditing-warehouse-data-health\ndescription: >\n  Audit the health of a PostHog project's data warehouse — find every broken or degraded pipeline item across\n  sources, sync schemas, materialized views, batch exports, and transformations. Use when the user asks \"what's\n  broken in my warehouse?\", \"give me a health check\", \"audit my data pipeline\", \"why are some dashboards stale?\",\n  or wants a one-shot triage summary before deciding where to spend time. Produces a prioritized report of issues\n  grouped by severity and type, with recommended next steps.\n---\n\n# Auditing data warehouse health\n\nThis skill produces a project-wide audit of the data warehouse pipeline. Use it when the user wants a **summary of\neverything broken**, not a deep-dive on one sync. The deep-dive on individual failures is\n`diagnosing-failed-warehouse-syncs`; this skill is the scan that tells them where to look first.\n\n## When to use this skill\n\n- \"What's broken in my warehouse?\" \u002F \"Give me a health check\"\n- \"Audit my data pipeline\"\n- The user is new to a project and wants to know what they've inherited\n- Weekly or monthly review of pipeline health\n- Dashboards are stale and the user isn't sure which source is at fault\n\n## Available tools\n\n| Tool                                          | Purpose                                                             |\n| --------------------------------------------- | ------------------------------------------------------------------- |\n| `data-warehouse-data-health-issues-retrieve`  | One-shot: all failed\u002Fdegraded items across the whole pipeline       |\n| `external-data-sources-list`                  | All sources with status and latest error                            |\n| `external-data-schemas-list`                  | All schemas with status, last_synced_at, latest_error               |\n| `view-list`                                   | All saved queries \u002F materialized views with status and latest_error |\n| `view-run-history`                            | Run history for a specific materialized view                        |\n| `external-data-sources-webhook-info-retrieve` | Check per-source webhook state (not covered by data-health-issues)  |\n\nThe `data-health-issues` endpoint already aggregates across materializations, sync schemas, sources, batch export\ndestinations, and transformations — it's the fastest path to a summary. Use the list endpoints when you need more\ncontext than the summary provides (row counts, non-failing items, schema-level detail).\n\n## What counts as an \"issue\"\n\nThe data-health endpoint returns items from five categories:\n\n| `type`               | Trigger                                                                                                                                       | Typical urgency |\n| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |\n| `source`             | `ExternalDataSource.status = Error` — whole source connection broken                                                                          | High            |\n| `external_data_sync` | schema in Failed or BillingLimitReached state (the data-health endpoint returns `status: \"failed\"` or `status: \"billing_limit\"` respectively) | Medium–High     |\n| `materialized_view`  | `DataWarehouseSavedQuery.is_materialized=true, status=Failed`                                                                                 | Medium          |\n| `destination`        | Batch export's latest run is FAILED \u002F FAILED_RETRYABLE \u002F TIMEDOUT \u002F TERMINATED                                                                | Medium          |\n| `transformation`     | HogFunction transformation in DISABLED \u002F DEGRADED \u002F FORCEFULLY\\_\\* state                                                                      | Low–Medium      |\n\nEach entry includes `id`, `name`, `type`, `status`, `error`, `failed_at`, `url`, and (for syncs\u002Fsources)\n`source_type`.\n\nNote the data-health endpoint only reports _active failures_. It doesn't flag:\n\n- Schemas paused by the user (`should_sync = false`)\n- Non-materialized views with errors (only materialized views are reported)\n- Schemas that are slow or stale but technically `Completed`\n- **Webhook problems on `sync_type: \"webhook\"` schemas.** The bulk-sync safety net can succeed while the webhook\n  push channel is silently broken (deregistered, disabled on the remote side, failing signature verification).\n  These don't surface in `data-health-issues` — check per-source with `webhook-info-retrieve`.\n\nIf the user asks about staleness or unused items, reach beyond this endpoint — see Step 4.\n\n## Workflow\n\n### Step 1 — One-shot pull\n\nCall `data-warehouse-data-health-issues-retrieve`. This returns every actively failing item in one request.\n\nIf the response is empty, tell the user their pipeline is healthy and stop. Don't invent problems.\n\n### Step 2 — Group and prioritize\n\nGroup the issues by `type` and sort within each group by severity:\n\n1. **Sources in Error first.** A source failure cascades — every schema under it is effectively dead until the\n   source reconnects. Fix these first.\n2. **Sync schemas next**, in this order:\n   - `status: \"billing_limit\"` entries (billing issue, non-technical — flag and route to billing)\n   - `Failed` on heavily-used tables (user asks \u002F check row counts via schemas-list if needed)\n   - `Failed` on less-used tables\n3. **Materialized views.** Usually independent of sources — a view failure is a HogQL or data issue in the view\n   itself.\n4. **Batch export destinations.** Affect data going _out_ of PostHog — important but generally not blocking reads.\n5. **Transformations.** Affect ingestion. Flag separately since these are HogFunction issues, not warehouse syncs.\n\n### Step 3 — Present the audit\n\nRender a prioritized report. Don't dump the raw JSON — human-readable table per category:\n\n```text\n## Data warehouse health — 7 issues\n\n### 🔴 Sources (1)\n- Stripe — authentication failed (failed 2h ago)\n  → `diagnosing-failed-warehouse-syncs` on this source\n\n### 🟠 Sync schemas (3)\n- postgres_prod.orders (Failed 6h ago) — column \"updated_at\" does not exist\n- postgres_prod.invoices (Failed 6h ago) — column \"updated_at\" does not exist\n- hubspot.contacts (BillingLimitReached) — team quota exceeded\n\n### 🟠 Materialized views (2)\n- monthly_revenue — view failed (syntax error in HogQL)\n- active_users_30d — view failed (missing table reference)\n\n### 🟡 Destinations (1)\n- S3 export \"daily-events\" (FAILED_RETRYABLE 3 runs in a row)\n\nRecommended order:\n1. Stripe auth (everything under it is dead)\n2. Schema-drift on postgres_prod.orders \u002F invoices — looks like upstream renamed a column\n3. Billing limit on hubspot\n4. Materialized views (independent — can be tackled any time)\n```\n\nThe exact format is less important than: prioritized, grouped, actionable, and hinting at the right next skill.\n\n### Step 4 — Go beyond active failures (when asked)\n\nIf the user wants more than just \"what's on fire\" — e.g. \"what else should I look at?\" — cross-check:\n\n**Stale but \"Completed\" schemas:**\nCall `external-data-schemas-list` and look for schemas with old `last_synced_at` relative to their `sync_frequency`.\nA schema on `1hour` frequency that last synced 3 days ago is effectively broken even if status says `Completed`.\n\n**Unused materialized views:**\nCall `view-list`. Materialized views cost storage and compute every run. If any are marked materialized but haven't\nbeen queried lately, surface them — `cleaning-up-stale-warehouse-views` territory (not yet implemented, but the data\nis available).\n\n**Sources with zero sync activity:**\nSources where every schema has `should_sync: false` or `status = Paused`. These were set up and then abandoned —\ncandidates for cleanup via `external-data-sources-destroy`.\n\n**Broken webhooks on webhook-type schemas:**\nIterate the sources that have any schema with `sync_type: \"webhook\"` (visible via `external-data-schemas-list`). For\neach, call `external-data-sources-webhook-info-retrieve({source_id})`:\n\n- `exists: false` while a schema is `sync_type: \"webhook\"` → webhook was never registered, or was deleted. Push\n  channel is dead; only the bulk fallback is ingesting.\n- `external_status.error` present → remote service is reporting a problem (permission revoked, endpoint\n  deleted on their dashboard).\n- `external_status.status` not `\"enabled\"` → remote has disabled the endpoint (often after repeated delivery\n  failures).\n\nReport these separately from the primary audit — they're a different shape of problem than the other categories,\nand the fix is a different skill (`diagnosing-failed-warehouse-syncs` scenario I, or\n`setting-up-a-data-warehouse-source` step 5.5).\n\nOnly run these extra checks if the user explicitly asks for a broader audit — they involve more tool calls and\nheuristics.\n\n### Step 5 — Offer the next step\n\nEnd the audit with a clear hand-off:\n\n- \"Want me to dig into the Stripe failure?\" → hands off to `diagnosing-failed-warehouse-syncs`\n- \"Want me to fix the schema drift on orders?\" → hands off to `tuning-incremental-sync-config`\n- \"Want to disable the billing-capped schemas?\" → one-click via `external-data-schemas-partial-update`\n\nNever start applying fixes autonomously from an audit — the audit's job is to report and recommend, not remediate.\nAny fix should be confirmed explicitly before executing.\n\n## Example interaction\n\n```text\nUser: \"Check the health of our data warehouse\"\n\nAgent:\n- data-warehouse-data-health-issues-retrieve → 4 items\n   [{type: \"source\", name: \"Stripe\", error: \"401 Unauthorized\", ...},\n    {type: \"external_data_sync\", name: \"postgres_prod.orders\",\n     error: \"column \\\"updated_at\\\" does not exist\", ...},\n    {type: \"materialized_view\", name: \"monthly_revenue\",\n     error: \"syntax error at or near \\\"FORM\\\"\", ...},\n    {type: \"destination\", name: \"S3 daily-events\", error: \"AccessDenied\", ...}]\n\n- Report:\n  \"Found 4 issues in your data warehouse:\n\n   🔴 Sources (1)\n   - Stripe — auth failure 2h ago (401). All 8 tables under it are currently dead.\n\n   🟠 Sync schemas (1)\n   - postgres_prod.orders — column `updated_at` was dropped on the source side,\n     incremental sync can't find it.\n\n   🟠 Materialized views (1)\n   - monthly_revenue — HogQL syntax error ('FORM' instead of 'FROM').\n\n   🟡 Destinations (1)\n   - S3 export 'daily-events' — access denied on write.\n\n   Suggest fixing in this order:\n   1. Stripe credentials (unblocks everything under it)\n   2. orders incremental-field drift\n   3. monthly_revenue typo\n   4. S3 permissions\n\n   Want me to start on Stripe?\"\n```\n\n## Important notes\n\n- **The audit is read-only.** Never call destructive tools from the audit flow. Hand off to the diagnosis\u002Ftuning\n  skills — which in turn confirm before acting.\n- **Empty = healthy.** Don't pad an empty audit with hypothetical issues. \"No issues found\" is a good answer.\n- **Source failures cascade.** When reporting a source in Error, also mention which schemas under it are affected\n  (or will be, once they try to sync again). The user needs to understand the blast radius.\n- **Billing limits aren't technical problems.** Flag them but route to billing \u002F quota discussion, not to a\n  recovery action.\n- **Transformation issues are separate.** HogFunctions aren't warehouse syncs — they show up in the audit because\n  they're part of the broader pipeline, but they live in the `posthog` ingestion side. Route those to pipeline\n  skills rather than trying to fix in-place here.\n- **`data-health-issues` only surfaces active failures.** For staleness, unused views, or abandoned sources, you\n  need to cross-check the list endpoints. Only do this when the user explicitly asks for a deeper audit.\n- **Webhook health is separate from schema health.** The data-health endpoint doesn't know about webhook state.\n  When a user's request mentions \"real-time\", \"Stripe webhook\", or \"why is data hours behind on a webhook\n  source\", go straight to `webhook-info-retrieve` rather than inferring from schema status.\n",{"data":38,"body":39},{"name":4,"description":6},{"type":40,"children":41},"root",[42,51,74,81,111,117,247,260,266,271,437,500,513,577,582,588,595,607,612,618,630,725,731,736,748,753,759,764,811,835,867,899,950,970,975,981,986,1021,1026,1032,1041,1047],{"type":43,"tag":44,"props":45,"children":47},"element","h1",{"id":46},"auditing-data-warehouse-health",[48],{"type":49,"value":50},"text","Auditing data warehouse health",{"type":43,"tag":52,"props":53,"children":54},"p",{},[55,57,63,65,72],{"type":49,"value":56},"This skill produces a project-wide audit of the data warehouse pipeline. Use it when the user wants a ",{"type":43,"tag":58,"props":59,"children":60},"strong",{},[61],{"type":49,"value":62},"summary of\neverything broken",{"type":49,"value":64},", not a deep-dive on one sync. The deep-dive on individual failures is\n",{"type":43,"tag":66,"props":67,"children":69},"code",{"className":68},[],[70],{"type":49,"value":71},"diagnosing-failed-warehouse-syncs",{"type":49,"value":73},"; this skill is the scan that tells them where to look first.",{"type":43,"tag":75,"props":76,"children":78},"h2",{"id":77},"when-to-use-this-skill",[79],{"type":49,"value":80},"When to use this skill",{"type":43,"tag":82,"props":83,"children":84},"ul",{},[85,91,96,101,106],{"type":43,"tag":86,"props":87,"children":88},"li",{},[89],{"type":49,"value":90},"\"What's broken in my warehouse?\" \u002F \"Give me a health check\"",{"type":43,"tag":86,"props":92,"children":93},{},[94],{"type":49,"value":95},"\"Audit my data pipeline\"",{"type":43,"tag":86,"props":97,"children":98},{},[99],{"type":49,"value":100},"The user is new to a project and wants to know what they've inherited",{"type":43,"tag":86,"props":102,"children":103},{},[104],{"type":49,"value":105},"Weekly or monthly review of pipeline health",{"type":43,"tag":86,"props":107,"children":108},{},[109],{"type":49,"value":110},"Dashboards are stale and the user isn't sure which source is at fault",{"type":43,"tag":75,"props":112,"children":114},{"id":113},"available-tools",[115],{"type":49,"value":116},"Available tools",{"type":43,"tag":118,"props":119,"children":120},"table",{},[121,140],{"type":43,"tag":122,"props":123,"children":124},"thead",{},[125],{"type":43,"tag":126,"props":127,"children":128},"tr",{},[129,135],{"type":43,"tag":130,"props":131,"children":132},"th",{},[133],{"type":49,"value":134},"Tool",{"type":43,"tag":130,"props":136,"children":137},{},[138],{"type":49,"value":139},"Purpose",{"type":43,"tag":141,"props":142,"children":143},"tbody",{},[144,162,179,196,213,230],{"type":43,"tag":126,"props":145,"children":146},{},[147,157],{"type":43,"tag":148,"props":149,"children":150},"td",{},[151],{"type":43,"tag":66,"props":152,"children":154},{"className":153},[],[155],{"type":49,"value":156},"data-warehouse-data-health-issues-retrieve",{"type":43,"tag":148,"props":158,"children":159},{},[160],{"type":49,"value":161},"One-shot: all failed\u002Fdegraded items across the whole pipeline",{"type":43,"tag":126,"props":163,"children":164},{},[165,174],{"type":43,"tag":148,"props":166,"children":167},{},[168],{"type":43,"tag":66,"props":169,"children":171},{"className":170},[],[172],{"type":49,"value":173},"external-data-sources-list",{"type":43,"tag":148,"props":175,"children":176},{},[177],{"type":49,"value":178},"All sources with status and latest error",{"type":43,"tag":126,"props":180,"children":181},{},[182,191],{"type":43,"tag":148,"props":183,"children":184},{},[185],{"type":43,"tag":66,"props":186,"children":188},{"className":187},[],[189],{"type":49,"value":190},"external-data-schemas-list",{"type":43,"tag":148,"props":192,"children":193},{},[194],{"type":49,"value":195},"All schemas with status, last_synced_at, latest_error",{"type":43,"tag":126,"props":197,"children":198},{},[199,208],{"type":43,"tag":148,"props":200,"children":201},{},[202],{"type":43,"tag":66,"props":203,"children":205},{"className":204},[],[206],{"type":49,"value":207},"view-list",{"type":43,"tag":148,"props":209,"children":210},{},[211],{"type":49,"value":212},"All saved queries \u002F materialized views with status and latest_error",{"type":43,"tag":126,"props":214,"children":215},{},[216,225],{"type":43,"tag":148,"props":217,"children":218},{},[219],{"type":43,"tag":66,"props":220,"children":222},{"className":221},[],[223],{"type":49,"value":224},"view-run-history",{"type":43,"tag":148,"props":226,"children":227},{},[228],{"type":49,"value":229},"Run history for a specific materialized view",{"type":43,"tag":126,"props":231,"children":232},{},[233,242],{"type":43,"tag":148,"props":234,"children":235},{},[236],{"type":43,"tag":66,"props":237,"children":239},{"className":238},[],[240],{"type":49,"value":241},"external-data-sources-webhook-info-retrieve",{"type":43,"tag":148,"props":243,"children":244},{},[245],{"type":49,"value":246},"Check per-source webhook state (not covered by data-health-issues)",{"type":43,"tag":52,"props":248,"children":249},{},[250,252,258],{"type":49,"value":251},"The ",{"type":43,"tag":66,"props":253,"children":255},{"className":254},[],[256],{"type":49,"value":257},"data-health-issues",{"type":49,"value":259}," endpoint already aggregates across materializations, sync schemas, sources, batch export\ndestinations, and transformations — it's the fastest path to a summary. Use the list endpoints when you need more\ncontext than the summary provides (row counts, non-failing items, schema-level detail).",{"type":43,"tag":75,"props":261,"children":263},{"id":262},"what-counts-as-an-issue",[264],{"type":49,"value":265},"What counts as an \"issue\"",{"type":43,"tag":52,"props":267,"children":268},{},[269],{"type":49,"value":270},"The data-health endpoint returns items from five categories:",{"type":43,"tag":118,"props":272,"children":273},{},[274,299],{"type":43,"tag":122,"props":275,"children":276},{},[277],{"type":43,"tag":126,"props":278,"children":279},{},[280,289,294],{"type":43,"tag":130,"props":281,"children":282},{},[283],{"type":43,"tag":66,"props":284,"children":286},{"className":285},[],[287],{"type":49,"value":288},"type",{"type":43,"tag":130,"props":290,"children":291},{},[292],{"type":49,"value":293},"Trigger",{"type":43,"tag":130,"props":295,"children":296},{},[297],{"type":49,"value":298},"Typical urgency",{"type":43,"tag":141,"props":300,"children":301},{},[302,330,368,394,415],{"type":43,"tag":126,"props":303,"children":304},{},[305,314,325],{"type":43,"tag":148,"props":306,"children":307},{},[308],{"type":43,"tag":66,"props":309,"children":311},{"className":310},[],[312],{"type":49,"value":313},"source",{"type":43,"tag":148,"props":315,"children":316},{},[317,323],{"type":43,"tag":66,"props":318,"children":320},{"className":319},[],[321],{"type":49,"value":322},"ExternalDataSource.status = Error",{"type":49,"value":324}," — whole source connection broken",{"type":43,"tag":148,"props":326,"children":327},{},[328],{"type":49,"value":329},"High",{"type":43,"tag":126,"props":331,"children":332},{},[333,342,363],{"type":43,"tag":148,"props":334,"children":335},{},[336],{"type":43,"tag":66,"props":337,"children":339},{"className":338},[],[340],{"type":49,"value":341},"external_data_sync",{"type":43,"tag":148,"props":343,"children":344},{},[345,347,353,355,361],{"type":49,"value":346},"schema in Failed or BillingLimitReached state (the data-health endpoint returns ",{"type":43,"tag":66,"props":348,"children":350},{"className":349},[],[351],{"type":49,"value":352},"status: \"failed\"",{"type":49,"value":354}," or ",{"type":43,"tag":66,"props":356,"children":358},{"className":357},[],[359],{"type":49,"value":360},"status: \"billing_limit\"",{"type":49,"value":362}," respectively)",{"type":43,"tag":148,"props":364,"children":365},{},[366],{"type":49,"value":367},"Medium–High",{"type":43,"tag":126,"props":369,"children":370},{},[371,380,389],{"type":43,"tag":148,"props":372,"children":373},{},[374],{"type":43,"tag":66,"props":375,"children":377},{"className":376},[],[378],{"type":49,"value":379},"materialized_view",{"type":43,"tag":148,"props":381,"children":382},{},[383],{"type":43,"tag":66,"props":384,"children":386},{"className":385},[],[387],{"type":49,"value":388},"DataWarehouseSavedQuery.is_materialized=true, status=Failed",{"type":43,"tag":148,"props":390,"children":391},{},[392],{"type":49,"value":393},"Medium",{"type":43,"tag":126,"props":395,"children":396},{},[397,406,411],{"type":43,"tag":148,"props":398,"children":399},{},[400],{"type":43,"tag":66,"props":401,"children":403},{"className":402},[],[404],{"type":49,"value":405},"destination",{"type":43,"tag":148,"props":407,"children":408},{},[409],{"type":49,"value":410},"Batch export's latest run is FAILED \u002F FAILED_RETRYABLE \u002F TIMEDOUT \u002F TERMINATED",{"type":43,"tag":148,"props":412,"children":413},{},[414],{"type":49,"value":393},{"type":43,"tag":126,"props":416,"children":417},{},[418,427,432],{"type":43,"tag":148,"props":419,"children":420},{},[421],{"type":43,"tag":66,"props":422,"children":424},{"className":423},[],[425],{"type":49,"value":426},"transformation",{"type":43,"tag":148,"props":428,"children":429},{},[430],{"type":49,"value":431},"HogFunction transformation in DISABLED \u002F DEGRADED \u002F FORCEFULLY_* state",{"type":43,"tag":148,"props":433,"children":434},{},[435],{"type":49,"value":436},"Low–Medium",{"type":43,"tag":52,"props":438,"children":439},{},[440,442,448,450,456,457,462,463,469,470,476,477,483,484,490,492,498],{"type":49,"value":441},"Each entry includes ",{"type":43,"tag":66,"props":443,"children":445},{"className":444},[],[446],{"type":49,"value":447},"id",{"type":49,"value":449},", ",{"type":43,"tag":66,"props":451,"children":453},{"className":452},[],[454],{"type":49,"value":455},"name",{"type":49,"value":449},{"type":43,"tag":66,"props":458,"children":460},{"className":459},[],[461],{"type":49,"value":288},{"type":49,"value":449},{"type":43,"tag":66,"props":464,"children":466},{"className":465},[],[467],{"type":49,"value":468},"status",{"type":49,"value":449},{"type":43,"tag":66,"props":471,"children":473},{"className":472},[],[474],{"type":49,"value":475},"error",{"type":49,"value":449},{"type":43,"tag":66,"props":478,"children":480},{"className":479},[],[481],{"type":49,"value":482},"failed_at",{"type":49,"value":449},{"type":43,"tag":66,"props":485,"children":487},{"className":486},[],[488],{"type":49,"value":489},"url",{"type":49,"value":491},", and (for syncs\u002Fsources)\n",{"type":43,"tag":66,"props":493,"children":495},{"className":494},[],[496],{"type":49,"value":497},"source_type",{"type":49,"value":499},".",{"type":43,"tag":52,"props":501,"children":502},{},[503,505,511],{"type":49,"value":504},"Note the data-health endpoint only reports ",{"type":43,"tag":506,"props":507,"children":508},"em",{},[509],{"type":49,"value":510},"active failures",{"type":49,"value":512},". It doesn't flag:",{"type":43,"tag":82,"props":514,"children":515},{},[516,529,534,545],{"type":43,"tag":86,"props":517,"children":518},{},[519,521,527],{"type":49,"value":520},"Schemas paused by the user (",{"type":43,"tag":66,"props":522,"children":524},{"className":523},[],[525],{"type":49,"value":526},"should_sync = false",{"type":49,"value":528},")",{"type":43,"tag":86,"props":530,"children":531},{},[532],{"type":49,"value":533},"Non-materialized views with errors (only materialized views are reported)",{"type":43,"tag":86,"props":535,"children":536},{},[537,539],{"type":49,"value":538},"Schemas that are slow or stale but technically ",{"type":43,"tag":66,"props":540,"children":542},{"className":541},[],[543],{"type":49,"value":544},"Completed",{"type":43,"tag":86,"props":546,"children":547},{},[548,561,563,568,570,576],{"type":43,"tag":58,"props":549,"children":550},{},[551,553,559],{"type":49,"value":552},"Webhook problems on ",{"type":43,"tag":66,"props":554,"children":556},{"className":555},[],[557],{"type":49,"value":558},"sync_type: \"webhook\"",{"type":49,"value":560}," schemas.",{"type":49,"value":562}," The bulk-sync safety net can succeed while the webhook\npush channel is silently broken (deregistered, disabled on the remote side, failing signature verification).\nThese don't surface in ",{"type":43,"tag":66,"props":564,"children":566},{"className":565},[],[567],{"type":49,"value":257},{"type":49,"value":569}," — check per-source with ",{"type":43,"tag":66,"props":571,"children":573},{"className":572},[],[574],{"type":49,"value":575},"webhook-info-retrieve",{"type":49,"value":499},{"type":43,"tag":52,"props":578,"children":579},{},[580],{"type":49,"value":581},"If the user asks about staleness or unused items, reach beyond this endpoint — see Step 4.",{"type":43,"tag":75,"props":583,"children":585},{"id":584},"workflow",[586],{"type":49,"value":587},"Workflow",{"type":43,"tag":589,"props":590,"children":592},"h3",{"id":591},"step-1-one-shot-pull",[593],{"type":49,"value":594},"Step 1 — One-shot pull",{"type":43,"tag":52,"props":596,"children":597},{},[598,600,605],{"type":49,"value":599},"Call ",{"type":43,"tag":66,"props":601,"children":603},{"className":602},[],[604],{"type":49,"value":156},{"type":49,"value":606},". This returns every actively failing item in one request.",{"type":43,"tag":52,"props":608,"children":609},{},[610],{"type":49,"value":611},"If the response is empty, tell the user their pipeline is healthy and stop. Don't invent problems.",{"type":43,"tag":589,"props":613,"children":615},{"id":614},"step-2-group-and-prioritize",[616],{"type":49,"value":617},"Step 2 — Group and prioritize",{"type":43,"tag":52,"props":619,"children":620},{},[621,623,628],{"type":49,"value":622},"Group the issues by ",{"type":43,"tag":66,"props":624,"children":626},{"className":625},[],[627],{"type":49,"value":288},{"type":49,"value":629}," and sort within each group by severity:",{"type":43,"tag":631,"props":632,"children":633},"ol",{},[634,644,688,698,715],{"type":43,"tag":86,"props":635,"children":636},{},[637,642],{"type":43,"tag":58,"props":638,"children":639},{},[640],{"type":49,"value":641},"Sources in Error first.",{"type":49,"value":643}," A source failure cascades — every schema under it is effectively dead until the\nsource reconnects. Fix these first.",{"type":43,"tag":86,"props":645,"children":646},{},[647,652,654],{"type":43,"tag":58,"props":648,"children":649},{},[650],{"type":49,"value":651},"Sync schemas next",{"type":49,"value":653},", in this order:\n",{"type":43,"tag":82,"props":655,"children":656},{},[657,667,678],{"type":43,"tag":86,"props":658,"children":659},{},[660,665],{"type":43,"tag":66,"props":661,"children":663},{"className":662},[],[664],{"type":49,"value":360},{"type":49,"value":666}," entries (billing issue, non-technical — flag and route to billing)",{"type":43,"tag":86,"props":668,"children":669},{},[670,676],{"type":43,"tag":66,"props":671,"children":673},{"className":672},[],[674],{"type":49,"value":675},"Failed",{"type":49,"value":677}," on heavily-used tables (user asks \u002F check row counts via schemas-list if needed)",{"type":43,"tag":86,"props":679,"children":680},{},[681,686],{"type":43,"tag":66,"props":682,"children":684},{"className":683},[],[685],{"type":49,"value":675},{"type":49,"value":687}," on less-used tables",{"type":43,"tag":86,"props":689,"children":690},{},[691,696],{"type":43,"tag":58,"props":692,"children":693},{},[694],{"type":49,"value":695},"Materialized views.",{"type":49,"value":697}," Usually independent of sources — a view failure is a HogQL or data issue in the view\nitself.",{"type":43,"tag":86,"props":699,"children":700},{},[701,706,708,713],{"type":43,"tag":58,"props":702,"children":703},{},[704],{"type":49,"value":705},"Batch export destinations.",{"type":49,"value":707}," Affect data going ",{"type":43,"tag":506,"props":709,"children":710},{},[711],{"type":49,"value":712},"out",{"type":49,"value":714}," of PostHog — important but generally not blocking reads.",{"type":43,"tag":86,"props":716,"children":717},{},[718,723],{"type":43,"tag":58,"props":719,"children":720},{},[721],{"type":49,"value":722},"Transformations.",{"type":49,"value":724}," Affect ingestion. Flag separately since these are HogFunction issues, not warehouse syncs.",{"type":43,"tag":589,"props":726,"children":728},{"id":727},"step-3-present-the-audit",[729],{"type":49,"value":730},"Step 3 — Present the audit",{"type":43,"tag":52,"props":732,"children":733},{},[734],{"type":49,"value":735},"Render a prioritized report. Don't dump the raw JSON — human-readable table per category:",{"type":43,"tag":737,"props":738,"children":743},"pre",{"className":739,"code":741,"language":49,"meta":742},[740],"language-text","## Data warehouse health — 7 issues\n\n### 🔴 Sources (1)\n- Stripe — authentication failed (failed 2h ago)\n  → `diagnosing-failed-warehouse-syncs` on this source\n\n### 🟠 Sync schemas (3)\n- postgres_prod.orders (Failed 6h ago) — column \"updated_at\" does not exist\n- postgres_prod.invoices (Failed 6h ago) — column \"updated_at\" does not exist\n- hubspot.contacts (BillingLimitReached) — team quota exceeded\n\n### 🟠 Materialized views (2)\n- monthly_revenue — view failed (syntax error in HogQL)\n- active_users_30d — view failed (missing table reference)\n\n### 🟡 Destinations (1)\n- S3 export \"daily-events\" (FAILED_RETRYABLE 3 runs in a row)\n\nRecommended order:\n1. Stripe auth (everything under it is dead)\n2. Schema-drift on postgres_prod.orders \u002F invoices — looks like upstream renamed a column\n3. Billing limit on hubspot\n4. Materialized views (independent — can be tackled any time)\n","",[744],{"type":43,"tag":66,"props":745,"children":746},{"__ignoreMap":742},[747],{"type":49,"value":741},{"type":43,"tag":52,"props":749,"children":750},{},[751],{"type":49,"value":752},"The exact format is less important than: prioritized, grouped, actionable, and hinting at the right next skill.",{"type":43,"tag":589,"props":754,"children":756},{"id":755},"step-4-go-beyond-active-failures-when-asked",[757],{"type":49,"value":758},"Step 4 — Go beyond active failures (when asked)",{"type":43,"tag":52,"props":760,"children":761},{},[762],{"type":49,"value":763},"If the user wants more than just \"what's on fire\" — e.g. \"what else should I look at?\" — cross-check:",{"type":43,"tag":52,"props":765,"children":766},{},[767,772,774,779,781,787,789,795,797,803,805,810],{"type":43,"tag":58,"props":768,"children":769},{},[770],{"type":49,"value":771},"Stale but \"Completed\" schemas:",{"type":49,"value":773},"\nCall ",{"type":43,"tag":66,"props":775,"children":777},{"className":776},[],[778],{"type":49,"value":190},{"type":49,"value":780}," and look for schemas with old ",{"type":43,"tag":66,"props":782,"children":784},{"className":783},[],[785],{"type":49,"value":786},"last_synced_at",{"type":49,"value":788}," relative to their ",{"type":43,"tag":66,"props":790,"children":792},{"className":791},[],[793],{"type":49,"value":794},"sync_frequency",{"type":49,"value":796},".\nA schema on ",{"type":43,"tag":66,"props":798,"children":800},{"className":799},[],[801],{"type":49,"value":802},"1hour",{"type":49,"value":804}," frequency that last synced 3 days ago is effectively broken even if status says ",{"type":43,"tag":66,"props":806,"children":808},{"className":807},[],[809],{"type":49,"value":544},{"type":49,"value":499},{"type":43,"tag":52,"props":812,"children":813},{},[814,819,820,825,827,833],{"type":43,"tag":58,"props":815,"children":816},{},[817],{"type":49,"value":818},"Unused materialized views:",{"type":49,"value":773},{"type":43,"tag":66,"props":821,"children":823},{"className":822},[],[824],{"type":49,"value":207},{"type":49,"value":826},". Materialized views cost storage and compute every run. If any are marked materialized but haven't\nbeen queried lately, surface them — ",{"type":43,"tag":66,"props":828,"children":830},{"className":829},[],[831],{"type":49,"value":832},"cleaning-up-stale-warehouse-views",{"type":49,"value":834}," territory (not yet implemented, but the data\nis available).",{"type":43,"tag":52,"props":836,"children":837},{},[838,843,845,851,852,858,860,866],{"type":43,"tag":58,"props":839,"children":840},{},[841],{"type":49,"value":842},"Sources with zero sync activity:",{"type":49,"value":844},"\nSources where every schema has ",{"type":43,"tag":66,"props":846,"children":848},{"className":847},[],[849],{"type":49,"value":850},"should_sync: false",{"type":49,"value":354},{"type":43,"tag":66,"props":853,"children":855},{"className":854},[],[856],{"type":49,"value":857},"status = Paused",{"type":49,"value":859},". These were set up and then abandoned —\ncandidates for cleanup via ",{"type":43,"tag":66,"props":861,"children":863},{"className":862},[],[864],{"type":49,"value":865},"external-data-sources-destroy",{"type":49,"value":499},{"type":43,"tag":52,"props":868,"children":869},{},[870,875,877,882,884,889,891,897],{"type":43,"tag":58,"props":871,"children":872},{},[873],{"type":49,"value":874},"Broken webhooks on webhook-type schemas:",{"type":49,"value":876},"\nIterate the sources that have any schema with ",{"type":43,"tag":66,"props":878,"children":880},{"className":879},[],[881],{"type":49,"value":558},{"type":49,"value":883}," (visible via ",{"type":43,"tag":66,"props":885,"children":887},{"className":886},[],[888],{"type":49,"value":190},{"type":49,"value":890},"). For\neach, call ",{"type":43,"tag":66,"props":892,"children":894},{"className":893},[],[895],{"type":49,"value":896},"external-data-sources-webhook-info-retrieve({source_id})",{"type":49,"value":898},":",{"type":43,"tag":82,"props":900,"children":901},{},[902,920,931],{"type":43,"tag":86,"props":903,"children":904},{},[905,911,913,918],{"type":43,"tag":66,"props":906,"children":908},{"className":907},[],[909],{"type":49,"value":910},"exists: false",{"type":49,"value":912}," while a schema is ",{"type":43,"tag":66,"props":914,"children":916},{"className":915},[],[917],{"type":49,"value":558},{"type":49,"value":919}," → webhook was never registered, or was deleted. Push\nchannel is dead; only the bulk fallback is ingesting.",{"type":43,"tag":86,"props":921,"children":922},{},[923,929],{"type":43,"tag":66,"props":924,"children":926},{"className":925},[],[927],{"type":49,"value":928},"external_status.error",{"type":49,"value":930}," present → remote service is reporting a problem (permission revoked, endpoint\ndeleted on their dashboard).",{"type":43,"tag":86,"props":932,"children":933},{},[934,940,942,948],{"type":43,"tag":66,"props":935,"children":937},{"className":936},[],[938],{"type":49,"value":939},"external_status.status",{"type":49,"value":941}," not ",{"type":43,"tag":66,"props":943,"children":945},{"className":944},[],[946],{"type":49,"value":947},"\"enabled\"",{"type":49,"value":949}," → remote has disabled the endpoint (often after repeated delivery\nfailures).",{"type":43,"tag":52,"props":951,"children":952},{},[953,955,960,962,968],{"type":49,"value":954},"Report these separately from the primary audit — they're a different shape of problem than the other categories,\nand the fix is a different skill (",{"type":43,"tag":66,"props":956,"children":958},{"className":957},[],[959],{"type":49,"value":71},{"type":49,"value":961}," scenario I, or\n",{"type":43,"tag":66,"props":963,"children":965},{"className":964},[],[966],{"type":49,"value":967},"setting-up-a-data-warehouse-source",{"type":49,"value":969}," step 5.5).",{"type":43,"tag":52,"props":971,"children":972},{},[973],{"type":49,"value":974},"Only run these extra checks if the user explicitly asks for a broader audit — they involve more tool calls and\nheuristics.",{"type":43,"tag":589,"props":976,"children":978},{"id":977},"step-5-offer-the-next-step",[979],{"type":49,"value":980},"Step 5 — Offer the next step",{"type":43,"tag":52,"props":982,"children":983},{},[984],{"type":49,"value":985},"End the audit with a clear hand-off:",{"type":43,"tag":82,"props":987,"children":988},{},[989,999,1010],{"type":43,"tag":86,"props":990,"children":991},{},[992,994],{"type":49,"value":993},"\"Want me to dig into the Stripe failure?\" → hands off to ",{"type":43,"tag":66,"props":995,"children":997},{"className":996},[],[998],{"type":49,"value":71},{"type":43,"tag":86,"props":1000,"children":1001},{},[1002,1004],{"type":49,"value":1003},"\"Want me to fix the schema drift on orders?\" → hands off to ",{"type":43,"tag":66,"props":1005,"children":1007},{"className":1006},[],[1008],{"type":49,"value":1009},"tuning-incremental-sync-config",{"type":43,"tag":86,"props":1011,"children":1012},{},[1013,1015],{"type":49,"value":1014},"\"Want to disable the billing-capped schemas?\" → one-click via ",{"type":43,"tag":66,"props":1016,"children":1018},{"className":1017},[],[1019],{"type":49,"value":1020},"external-data-schemas-partial-update",{"type":43,"tag":52,"props":1022,"children":1023},{},[1024],{"type":49,"value":1025},"Never start applying fixes autonomously from an audit — the audit's job is to report and recommend, not remediate.\nAny fix should be confirmed explicitly before executing.",{"type":43,"tag":75,"props":1027,"children":1029},{"id":1028},"example-interaction",[1030],{"type":49,"value":1031},"Example interaction",{"type":43,"tag":737,"props":1033,"children":1036},{"className":1034,"code":1035,"language":49,"meta":742},[740],"User: \"Check the health of our data warehouse\"\n\nAgent:\n- data-warehouse-data-health-issues-retrieve → 4 items\n   [{type: \"source\", name: \"Stripe\", error: \"401 Unauthorized\", ...},\n    {type: \"external_data_sync\", name: \"postgres_prod.orders\",\n     error: \"column \\\"updated_at\\\" does not exist\", ...},\n    {type: \"materialized_view\", name: \"monthly_revenue\",\n     error: \"syntax error at or near \\\"FORM\\\"\", ...},\n    {type: \"destination\", name: \"S3 daily-events\", error: \"AccessDenied\", ...}]\n\n- Report:\n  \"Found 4 issues in your data warehouse:\n\n   🔴 Sources (1)\n   - Stripe — auth failure 2h ago (401). All 8 tables under it are currently dead.\n\n   🟠 Sync schemas (1)\n   - postgres_prod.orders — column `updated_at` was dropped on the source side,\n     incremental sync can't find it.\n\n   🟠 Materialized views (1)\n   - monthly_revenue — HogQL syntax error ('FORM' instead of 'FROM').\n\n   🟡 Destinations (1)\n   - S3 export 'daily-events' — access denied on write.\n\n   Suggest fixing in this order:\n   1. Stripe credentials (unblocks everything under it)\n   2. orders incremental-field drift\n   3. monthly_revenue typo\n   4. S3 permissions\n\n   Want me to start on Stripe?\"\n",[1037],{"type":43,"tag":66,"props":1038,"children":1039},{"__ignoreMap":742},[1040],{"type":49,"value":1035},{"type":43,"tag":75,"props":1042,"children":1044},{"id":1043},"important-notes",[1045],{"type":49,"value":1046},"Important notes",{"type":43,"tag":82,"props":1048,"children":1049},{},[1050,1060,1070,1080,1090,1107,1122],{"type":43,"tag":86,"props":1051,"children":1052},{},[1053,1058],{"type":43,"tag":58,"props":1054,"children":1055},{},[1056],{"type":49,"value":1057},"The audit is read-only.",{"type":49,"value":1059}," Never call destructive tools from the audit flow. Hand off to the diagnosis\u002Ftuning\nskills — which in turn confirm before acting.",{"type":43,"tag":86,"props":1061,"children":1062},{},[1063,1068],{"type":43,"tag":58,"props":1064,"children":1065},{},[1066],{"type":49,"value":1067},"Empty = healthy.",{"type":49,"value":1069}," Don't pad an empty audit with hypothetical issues. \"No issues found\" is a good answer.",{"type":43,"tag":86,"props":1071,"children":1072},{},[1073,1078],{"type":43,"tag":58,"props":1074,"children":1075},{},[1076],{"type":49,"value":1077},"Source failures cascade.",{"type":49,"value":1079}," When reporting a source in Error, also mention which schemas under it are affected\n(or will be, once they try to sync again). The user needs to understand the blast radius.",{"type":43,"tag":86,"props":1081,"children":1082},{},[1083,1088],{"type":43,"tag":58,"props":1084,"children":1085},{},[1086],{"type":49,"value":1087},"Billing limits aren't technical problems.",{"type":49,"value":1089}," Flag them but route to billing \u002F quota discussion, not to a\nrecovery action.",{"type":43,"tag":86,"props":1091,"children":1092},{},[1093,1098,1100,1105],{"type":43,"tag":58,"props":1094,"children":1095},{},[1096],{"type":49,"value":1097},"Transformation issues are separate.",{"type":49,"value":1099}," HogFunctions aren't warehouse syncs — they show up in the audit because\nthey're part of the broader pipeline, but they live in the ",{"type":43,"tag":66,"props":1101,"children":1103},{"className":1102},[],[1104],{"type":49,"value":8},{"type":49,"value":1106}," ingestion side. Route those to pipeline\nskills rather than trying to fix in-place here.",{"type":43,"tag":86,"props":1108,"children":1109},{},[1110,1120],{"type":43,"tag":58,"props":1111,"children":1112},{},[1113,1118],{"type":43,"tag":66,"props":1114,"children":1116},{"className":1115},[],[1117],{"type":49,"value":257},{"type":49,"value":1119}," only surfaces active failures.",{"type":49,"value":1121}," For staleness, unused views, or abandoned sources, you\nneed to cross-check the list endpoints. Only do this when the user explicitly asks for a deeper audit.",{"type":43,"tag":86,"props":1123,"children":1124},{},[1125,1130,1132,1137],{"type":43,"tag":58,"props":1126,"children":1127},{},[1128],{"type":49,"value":1129},"Webhook health is separate from schema health.",{"type":49,"value":1131}," The data-health endpoint doesn't know about webhook state.\nWhen a user's request mentions \"real-time\", \"Stripe webhook\", or \"why is data hours behind on a webhook\nsource\", go straight to ",{"type":43,"tag":66,"props":1133,"children":1135},{"className":1134},[],[1136],{"type":49,"value":575},{"type":49,"value":1138}," rather than inferring from schema status.",{"items":1140,"total":1241},[1141,1158,1166,1180,1200,1214,1225],{"slug":1142,"name":1142,"fn":1143,"description":1144,"org":1145,"tags":1146,"stars":26,"repoUrl":27,"updatedAt":1157},"account-handover","draft sales account handover notes","Draft structured handover notes for transitioning a PostHog account from one TAM or CSM to another. Use this skill when a TAM needs to hand over an account, prepare a transition briefing, write handover notes, create an account summary for a new owner, or any request involving account transitions between TAMs or CSMs. Triggers on \"hand over this account\", \"transition account to\", \"draft handover notes\", \"account briefing for new TAM\", \"prepare account transition\", or when a TAM names an account and says they're leaving or reassigning it.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1147,1150,1153,1154],{"name":1148,"slug":1149,"type":15},"Communications","communications",{"name":1151,"slug":1152,"type":15},"CRM","crm",{"name":9,"slug":8,"type":15},{"name":1155,"slug":1156,"type":15},"Sales","sales","2026-04-16T05:13:00.172732",{"slug":4,"name":4,"fn":5,"description":6,"org":1159,"tags":1160,"stars":26,"repoUrl":27,"updatedAt":28},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1161,1162,1163,1164,1165],{"name":24,"slug":25,"type":15},{"name":21,"slug":22,"type":15},{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"slug":1167,"name":1167,"fn":1168,"description":1169,"org":1170,"tags":1171,"stars":26,"repoUrl":27,"updatedAt":1179},"copying-flags-across-projects","copy feature flags across PostHog projects","Copy a feature flag from one PostHog project to one or more target projects in the same organization. Use when the user wants to duplicate a flag, promote a flag from staging to production, sync flags across projects, or replicate a flag configuration in a different workspace. Covers cohort remapping, scheduled-change handling, encrypted payloads, and the safe defaults (disabled in target, no scheduled changes).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1172,1175,1178],{"name":1173,"slug":1174,"type":15},"Deployment","deployment",{"name":1176,"slug":1177,"type":15},"Feature Flags","feature-flags",{"name":9,"slug":8,"type":15},"2026-05-04T05:56:44.484909",{"slug":1181,"name":1181,"fn":1182,"description":1183,"org":1184,"tags":1185,"stars":26,"repoUrl":27,"updatedAt":1199},"diagnosing-experiment-results","diagnose PostHog experiment results and anomalies","Diagnoses bias, anomalies, and strange-looking results on a specific PostHog experiment. Covers empty \u002F 0-exposure experiments, sample ratio mismatch, identity fragmentation, multi-variant exposure, uneven-split exclusion bias, significance traps (peeking, A\u002FA, Bayesian vs Frequentist), PostHog-vs-SQL discrepancies, and surprises after mid-run edits. Symptom-driven dispatch to the right diagnostic.\nTRIGGER when: user asks 'is my experiment biased?' or 'why 0 exposures?', references the bias banner, says a variant looks strange \u002F wrong \u002F off, sees significance flipping, notices PostHog numbers disagreeing with their SQL, sees an A\u002FA test showing significance, or reports surprises after mid-run edits.\nDO NOT TRIGGER when: creating a new experiment (use creating-experiments), only configuring rollout (use configuring-experiment-rollout) or metrics (use configuring-experiment-analytics), or only asking lifecycle questions (use managing-experiment-lifecycle).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1186,1189,1192,1195,1198],{"name":1187,"slug":1188,"type":15},"A\u002FB Testing","a-b-testing",{"name":1190,"slug":1191,"type":15},"Analytics","analytics",{"name":1193,"slug":1194,"type":15},"Data Analysis","data-analysis",{"name":1196,"slug":1197,"type":15},"Debugging","debugging",{"name":9,"slug":8,"type":15},"2026-05-22T06:59:58.103867",{"slug":1201,"name":1201,"fn":1202,"description":1203,"org":1204,"tags":1205,"stars":26,"repoUrl":27,"updatedAt":1213},"diagnosing-missing-recordings","diagnose missing PostHog session recordings","Diagnoses why a session recording is missing or was not captured. Use when a user asks why a session has no replay, why recordings aren't appearing, or wants to troubleshoot session replay capture issues for a specific session ID or across their project. Covers SDK diagnostic signals, project settings, sampling, triggers, ad blockers, and quota\u002Fbilling scenarios.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1206,1207,1208,1211,1212],{"name":1190,"slug":1191,"type":15},{"name":1196,"slug":1197,"type":15},{"name":1209,"slug":1210,"type":15},"Frontend","frontend",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-04-22T05:06:51.989772",{"slug":1215,"name":1215,"fn":1216,"description":1217,"org":1218,"tags":1219,"stars":26,"repoUrl":27,"updatedAt":1224},"diagnosing-sdk-health","diagnose PostHog SDK health","Diagnoses the health of a project's PostHog SDK integrations — which SDKs are out of date and how to fix them. Use when a user asks about PostHog SDK versions, outdated SDKs, upgrade recommendations, \"SDK health\", \"SDK doctor\" (the former name), or when events or features seem off and it might be due to an old SDK.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1220,1221,1222,1223],{"name":1190,"slug":1191,"type":15},{"name":1196,"slug":1197,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-04-27T05:46:14.554016",{"slug":1226,"name":1226,"fn":1227,"description":1228,"org":1229,"tags":1230,"stars":26,"repoUrl":27,"updatedAt":1240},"error-tracking-android","track Android errors with PostHog","PostHog error tracking for Android",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1231,1234,1235,1238,1239],{"name":1232,"slug":1233,"type":15},"Android","android",{"name":1196,"slug":1197,"type":15},{"name":1236,"slug":1237,"type":15},"Mobile","mobile",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-04-06T18:46:26.982494",110,{"items":1243,"total":1406},[1244,1259,1269,1282,1295,1308,1324,1341,1353,1368,1378,1396],{"slug":1245,"name":1245,"fn":1246,"description":1247,"org":1248,"tags":1249,"stars":1256,"repoUrl":1257,"updatedAt":1258},"analyzing-expensive-users","analyze expensive users in AI observability","Analyze the most expensive users in AI observability and explain why they cost so much. Use when the user asks about top spenders, expensive users, per-user LLM cost, user-level cost drivers, or patterns behind high AI observability spend.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1250,1251,1254,1255],{"name":1190,"slug":1191,"type":15},{"name":1252,"slug":1253,"type":15},"Cost Optimization","cost-optimization",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},35568,"https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog","2026-07-28T05:34:11.117757",{"slug":1260,"name":1260,"fn":1261,"description":1262,"org":1263,"tags":1264,"stars":1256,"repoUrl":1257,"updatedAt":1268},"auditing-endpoints","audit PostHog project endpoints","Audit every endpoint in a PostHog project for staleness, failed materialisations, and unused materialised versions. Use when the user asks \"what endpoints can I clean up?\", \"are any of my endpoints broken?\", \"which materialised versions are still being called?\", or wants a one-shot cleanup pass over the Endpoints product. Produces a prioritised report grouped by issue type, with recommended actions but does not modify anything without explicit confirmation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1265,1266,1267],{"name":1190,"slug":1191,"type":15},{"name":24,"slug":25,"type":15},{"name":9,"slug":8,"type":15},"2026-06-08T08:08:33.693989",{"slug":1270,"name":1270,"fn":1271,"description":1272,"org":1273,"tags":1274,"stars":1256,"repoUrl":1257,"updatedAt":1281},"auditing-warehouse-source-health","audit PostHog data warehouse source health","Audit the health of a PostHog project's data warehouse sources and syncs — find every broken or degraded source connection, sync schema, and webhook channel. Use when the user asks \"why are my imports failing?\", \"what's broken with my sources?\", \"why is my warehouse data stale?\", or wants a one-shot triage of source\u002Fsync health before deciding where to dig in. Produces a prioritized report grouped by severity, with recommended next steps. For materialized-view health use `auditing-warehouse-view-health`; for a single failing sync use `diagnosing-failed-warehouse-syncs`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1275,1276,1279,1280],{"name":24,"slug":25,"type":15},{"name":1277,"slug":1278,"type":15},"Data Warehouse","data-warehouse",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-06-18T08:22:57.67984",{"slug":1283,"name":1283,"fn":1284,"description":1285,"org":1286,"tags":1287,"stars":1256,"repoUrl":1257,"updatedAt":1294},"auditing-warehouse-view-health","audit PostHog materialized view health","Audit the health of a PostHog project's materialized views (saved queries) — find every failed materialization and flag unused or stale materialized views that cost storage and compute. Use when the user asks \"which of my views are broken?\", \"why is this materialized view failing?\", \"are any of my views wasting compute?\", or wants a one-shot triage of view health. For source\u002Fsync health use `auditing-warehouse-source-health`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1288,1289,1290,1293],{"name":24,"slug":25,"type":15},{"name":1277,"slug":1278,"type":15},{"name":1291,"slug":1292,"type":15},"Performance","performance",{"name":9,"slug":8,"type":15},"2026-06-18T08:25:10.936787",{"slug":1296,"name":1296,"fn":1297,"description":1298,"org":1299,"tags":1300,"stars":1256,"repoUrl":1257,"updatedAt":1307},"authoring-error-tracking-alerts","author PostHog error tracking alerts","Author error tracking alerts that fire when an issue is created, reopened, or starts spiking. Use when the user asks to set up error notifications, route exceptions to Slack\u002Fwebhook\u002FLinear, or evaluate which error events are worth alerting on. Covers trigger-event selection, integration choice, dedup against existing alerts, and shipping with the canonical message body shape.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1301,1304,1305,1306],{"name":1302,"slug":1303,"type":15},"Alerting","alerting",{"name":1196,"slug":1197,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-06-18T08:24:40.318583",{"slug":1309,"name":1309,"fn":1310,"description":1311,"org":1312,"tags":1313,"stars":1256,"repoUrl":1257,"updatedAt":1323},"authoring-log-alerts","author log alerts in PostHog","Author useful, low-noise log alerts on services in a PostHog project. Use when the user asks to set up alerts for their logs, suggest alerts they should add, or evaluate whether a service is worth monitoring. Covers service triage, baseline characterisation, threshold drafting, back-testing via simulate, and shipping with a notification destination.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1314,1315,1318,1319,1322],{"name":1190,"slug":1191,"type":15},{"name":1316,"slug":1317,"type":15},"Monitoring","monitoring",{"name":13,"slug":14,"type":15},{"name":1320,"slug":1321,"type":15},"Operations","operations",{"name":9,"slug":8,"type":15},"2026-07-18T05:10:54.430898",{"slug":1325,"name":1325,"fn":1326,"description":1327,"org":1328,"tags":1329,"stars":1256,"repoUrl":1257,"updatedAt":1340},"building-workflows","build and edit PostHog workflows","Build, edit, test, enable, and monitor PostHog workflows over MCP. Author the action\u002Fedge graph so it runs and opens cleanly in the visual editor, then change drafts surgically with patch operations. Use when asked to build, set up, automate, change, fix, or debug a workflow, campaign, broadcast, drip sequence, or event-triggered automation in the workflows product.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1330,1333,1336,1337],{"name":1331,"slug":1332,"type":15},"Automation","automation",{"name":1334,"slug":1335,"type":15},"MCP","mcp",{"name":9,"slug":8,"type":15},{"name":1338,"slug":1339,"type":15},"Workflow Automation","workflow-automation","2026-07-28T05:34:12.167015",{"slug":1342,"name":1342,"fn":1343,"description":1344,"org":1345,"tags":1346,"stars":1256,"repoUrl":1257,"updatedAt":1352},"check-posthog-loading","inspect PostHog SDK loading across URLs","Inspect how the PostHog JavaScript SDK is loaded across a list of URLs. Use to confirm consistent installation across pages, find pages missing the snippet, detect mismatched API keys or hosts between pages, and verify the load method (head snippet vs deferred vs array.js).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1347,1348,1349,1350,1351],{"name":1190,"slug":1191,"type":15},{"name":1196,"slug":1197,"type":15},{"name":1209,"slug":1210,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-05-07T05:56:19.828048",{"slug":1354,"name":1354,"fn":1355,"description":1356,"org":1357,"tags":1358,"stars":1256,"repoUrl":1257,"updatedAt":1367},"consuming-endpoints-from-client-code","integrate PostHog endpoints into client applications","Wire a PostHog endpoint into a client app or SDK. Covers fetching the OpenAPI spec, generating a typed client with openapi-generator or @hey-api\u002Fopenapi-ts, sending the right auth header, shaping the variables payload (HogQL code_name vs insight breakdown property), handling rate-limit and materialised-endpoint error responses. Use when the user says \"how do I call my endpoint\", \"generate a client for this\", or \"what auth header do I use\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1359,1362,1363,1364],{"name":1360,"slug":1361,"type":15},"API Development","api-development",{"name":1209,"slug":1210,"type":15},{"name":9,"slug":8,"type":15},{"name":1365,"slug":1366,"type":15},"SDK","sdk","2026-06-08T08:08:34.929454",{"slug":1369,"name":1369,"fn":1370,"description":1371,"org":1372,"tags":1373,"stars":1256,"repoUrl":1257,"updatedAt":1377},"copying-endpoints-across-projects","copy PostHog endpoints across projects","Copy a PostHog endpoint (a saved HogQL\u002Finsight query exposed as an API route) to another project in the same organization, or duplicate it under a new name in the same project. Use when the user wants to duplicate an endpoint, promote an endpoint from staging to production, replicate an endpoint's query\u002Fvariables\u002Ffreshness config in another workspace, or clone an endpoint to iterate on it. Unlike feature flags and experiments, endpoints have NO native cross-project copy tool — this skill covers the read-then-recreate flow (endpoint-get then endpoint-create), the active-project switching it requires, name-collision checks, and the safe defaults (land unmaterialised in the target, verify with endpoint-run). Does not cover editing endpoint versions (see managing-endpoint-versions) or authoring a brand-new endpoint from scratch (see creating-an-endpoint).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1374,1375,1376],{"name":1360,"slug":1361,"type":15},{"name":1320,"slug":1321,"type":15},{"name":9,"slug":8,"type":15},"2026-07-15T05:29:58.442727",{"slug":1379,"name":1379,"fn":1380,"description":1381,"org":1382,"tags":1383,"stars":1256,"repoUrl":1257,"updatedAt":1395},"creating-ai-subscription","schedule recurring AI-generated PostHog reports","Create a recurring AI-generated PostHog report — schedule a free-text prompt to run on a cron, with the LLM-synthesized markdown delivered to email or Slack on each tick. Use when the user wants a recurring AI summary of X on any cadence (daily, weekly, monthly, yearly) rather than a one-off report. (To attach an AI summary to an existing insight\u002Fdashboard subscription instead of a free-text prompt, see `managing-subscriptions` and its `summary_enabled` option.)\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1384,1385,1388,1389,1392],{"name":1331,"slug":1332,"type":15},{"name":1386,"slug":1387,"type":15},"Email","email",{"name":9,"slug":8,"type":15},{"name":1390,"slug":1391,"type":15},"Reporting","reporting",{"name":1393,"slug":1394,"type":15},"Slack","slack","2026-06-09T07:32:27.935712",{"slug":1397,"name":1397,"fn":1398,"description":1399,"org":1400,"tags":1401,"stars":1256,"repoUrl":1257,"updatedAt":1405},"creating-an-endpoint","create PostHog API endpoints","Create a PostHog endpoint with the right shape on the first try — covers query kind choice, name conventions, what to expose as variables (HogQL code_name vs insight breakdown), data_freshness_seconds, and whether to materialise on day one. Use when the user says \"create an endpoint\", \"expose this query as an API\", \"turn this insight into an endpoint\", or asks for help structuring a new endpoint. Steers away from common mistakes: materialising a query with cohort breakdowns or compare mode, inline-only variables on a materialised endpoint, unbounded date ranges, ambiguous names.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1402,1403,1404],{"name":1190,"slug":1191,"type":15},{"name":1360,"slug":1361,"type":15},{"name":9,"slug":8,"type":15},"2026-06-08T08:08:29.624498",231]