[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-posthog-investigating-logs":3,"mdc--kc4yfp-key":52,"related-repo-posthog-investigating-logs":896,"related-org-posthog-investigating-logs":993},{"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":47,"sourceUrl":50,"mdContent":51},"investigating-logs","investigate logs in PostHog projects","Investigate logs in a PostHog project: verify a service or deployment is healthy, explain an error spike, triage an incident, or understand what a log stream is saying. Use when the user asks to \"check the logs\", asks whether a service, deploy, release, or change is working or broke anything, asks why errors are up or what changed, or wants the root cause of failures visible in logs. Routes the logs MCP tools (services overview, pattern mining, before\u002Fafter pattern diffing, bucketed counts, facets, raw rows) so investigations start from summaries instead of raw rows or hand-written SQL over the logs table.\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,19,20,23],{"name":13,"slug":14,"type":15},"Observability","observability","tag",{"name":17,"slug":18,"type":15},"Logs","logs",{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},"Monitoring","monitoring",{"name":24,"slug":25,"type":15},"Debugging","debugging",35568,"https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog","2026-07-28T06:05:59.321254",null,2977,[32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"ab-testing","ai-analytics","analytics","cdp","data-warehouse","experiments","feature-flags","javascript","product-analytics","python","react","session-replay","surveys","typescript","web-analytics",{"repoUrl":27,"stars":26,"forks":30,"topics":48,"description":49},[32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"🦔 PostHog is an all-in-one developer platform for building successful products. We offer product analytics, web analytics, session replay, error tracking, feature flags, experimentation, surveys, data warehouse, a CDP, and an AI product assistant to help debug your code, ship features faster, and keep all your usage and customer data in one stack.","https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog\u002Ftree\u002FHEAD\u002Fproducts\u002Flogs\u002Fskills\u002Finvestigating-logs","---\nname: investigating-logs\ndescription: >\n  Investigate logs in a PostHog project: verify a service or deployment is healthy, explain an error spike,\n  triage an incident, or understand what a log stream is saying. Use when the user asks to \"check the logs\",\n  asks whether a service, deploy, release, or change is working or broke anything, asks why errors are up or\n  what changed, or wants the root cause of failures visible in logs. Routes the logs MCP tools\n  (services overview, pattern mining, before\u002Fafter pattern diffing, bucketed counts, facets, raw rows) so\n  investigations start from summaries instead of raw rows or hand-written SQL over the logs table.\n---\n\n# Investigating logs\n\nInvestigation is a narrowing problem: **summarize before you read**.\nOne `posthog:logs-patterns` call compresses millions of lines into at most 200 templates,\nand one `posthog:logs-patterns-diff` call answers \"what is different about now vs. before\" directly.\nRaw rows (`posthog:query-logs`) are the last step of an investigation, never the first.\n\n## When to use this skill\n\n- \"Check the logs\" \u002F \"is service X healthy?\" \u002F \"did my deploy (or model bump, config change, migration) break anything?\"\n- \"Why are errors up?\" \u002F \"explain this spike\" \u002F incident triage — \"what changed?\"\n- \"What is this service logging?\" — orienting in an unfamiliar or noisy stream.\n- Finding the log evidence for a failure reported elsewhere (an alert, an error-tracking issue, a user complaint).\n\n## When _not_ to use this skill\n\n- Creating or tuning log alerts — that's `authoring-log-alerts`.\n- Analytics over product events, persons, or insights — that's `querying-posthog-data`.\n- HogQL exposes a `logs` table via `posthog:execute-sql`, but do not investigate through it:\n  hand-written SQL over logs routinely hits read-byte caps and re-derives what the tools below do in one cheap call.\n  Reserve SQL for the rare case of joining log-derived facts with non-log data.\n\n## Tools\n\n| Tool                                                                  | Job                                                                                           |\n| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| `posthog:logs-services-create`                                        | Top-25 services with log_count, error_count, error_rate, sparkline. Orientation.              |\n| `posthog:logs-patterns`                                               | Mine one window's message templates, ordered by frequency. \"What is this stream saying?\"      |\n| `posthog:logs-patterns-diff`                                          | Diff templates between two windows: new \u002F rate-shifted \u002F gone. \"What changed?\"                |\n| `posthog:logs-count` \u002F `posthog:logs-count-ranges`                    | Scalar and time-bucketed counts for a filter. Localize volume before pulling rows.            |\n| `posthog:logs-sparkline-query`                                        | Volume over time broken down by severity or service (the one bucketed view with a breakdown). |\n| `posthog:logs-facet-values-create`                                    | Distribution of severity\u002Fservice (or a resource attribute) under a filter.                    |\n| `posthog:logs-attributes-list` \u002F `posthog:logs-attribute-values-list` | Discover attribute keys and values before building filters.                                   |\n| `posthog:query-logs`                                                  | Raw rows. Endpoint of every drill-down, entry point of none.                                  |\n\nEach tool's own description documents its parameters and response shape — read it before calling.\n\n## Pick the workflow by question shape\n\n### \"Is it healthy?\" — post-deploy \u002F post-change verification\n\nThe user changed something (deploy, model bump, config, migration) and wants to know the logs still look right.\n\n1. Pin down the change time and the affected service(s). Ask if the user hasn't said; the diff is meaningless without a boundary.\n2. Orient with `posthog:logs-services-create`: is the service still logging at all, and what is its error_rate now?\n   A service that went silent fails verification just as hard as one that started erroring.\n3. `posthog:logs-patterns-diff` with `query.dateRange` from the change time to now and `baselineDateRange`\n   set to a comparable window just before the change, scoped to `serviceNames`.\n   New error\u002Ffatal templates right after a change are the classic regression signature;\n   large `rate_ratio` shifts on existing error templates are the second thing to check.\n4. Check volume continuity with `posthog:logs-count-ranges` spanning before and after the boundary:\n   a rate discontinuity (crash loop, restart storm, silence) shows up here even when message content looks unchanged.\n5. Drill only the suspects: pivot each suspicious pattern to raw lines via its `match_regex` with `posthog:query-logs`.\n\nA pass verdict needs all three: no new error templates, no large error rate_ratio shifts, and continuous volume.\nSay which windows you compared — \"healthy\" is only as strong as the baseline.\n\n### \"Explain this spike\"\n\n1. Localize it: `posthog:logs-count-ranges` over the user's window, then recurse into the dense bucket(s) — each bucket's\n   `date_from`\u002F`date_to` feeds the next call. Stop after 3–4 levels.\n2. Explain it: `posthog:logs-patterns-diff` with the spike as `query.dateRange` and the window just before as\n   `baselineDateRange`. The top `new` and `rate_shift` entries are the explanation. Do not mine both windows\n   separately and diff by hand — the diff is one call.\n\n### Incident triage — \"what broke?\"\n\n`posthog:logs-patterns-diff` first: incident window vs. a known-good window just before (or omit the baseline for\nsame-window-last-week). Suspects are `new` entries and the biggest `rate_ratio` shifts; pivot each to raw lines.\nIf the failing service is unknown, find it first with `posthog:logs-facet-values-create` faceting `service_name`\nunder `severityLevels: [\"error\", \"fatal\"]`.\n\n### \"What is this stream saying?\" — unfamiliar service\n\n`posthog:logs-patterns` over the last hour, scoped to the service. Scan templates by `estimated_count` and\nnon-zero error share in `severity_counts`. Widen the window or add `searchTerm` only if the answer isn't there.\n\n### Known needle — a specific message, attribute, or person\n\nWhen the target is already precise (an error string, a request id, a distinct_id), skip pattern mining:\ndiscover the right keys with `posthog:logs-attributes-list` \u002F `posthog:logs-attribute-values-list`,\nsize the result with `posthog:logs-count`, then pull rows with `posthog:query-logs`.\n\n## Rules that keep investigations honest and cheap\n\n- Scope `serviceNames` (or a resource-attribute filter) on every call once the target service is known.\n  Unscoped calls scan the whole team's stream and starve the pattern sample budget.\n- `posthog:query-logs` requires an explicit `query.dateRange` — omitting it is a 400, not a default window.\n- Pattern counts are sampled estimates (`sampled: true`); templates rarer than ~1 in 10,000 rows can be invisible.\n  Absence of a rare template is not evidence it stopped.\n- Before trusting a wall of `new` entries in a diff, check `baseline.total_count` —\n  a tiny or empty baseline (logging only just started) makes everything look new.\n- `severityLevels` matches the six canonical lowercase buckets against `severity_text` exactly.\n  Zero rows on a severity filter → check the stored values with `posthog:logs-attribute-values-list { key: \"severity_text\" }`.\n- Budget: one services call, at most one patterns-diff per window pair, 3–4 count-ranges levels,\n  and `query-logs` only for confirmed suspects with `limit` ≤ 100.\n\n## Output\n\nLead with the verdict, then the evidence:\n\n- **Verdict**: healthy \u002F regressed \u002F inconclusive, with the windows compared.\n- **Suspects** (if any): template, classification (`new` \u002F `rate_shift`), estimated counts or `rate_ratio`, services, and 1–2 sample raw lines.\n- **What was checked and what wasn't**: services covered, windows, and any sampling or baseline caveats that limit confidence.\n\nThe user should be able to act on the verdict without re-running the investigation.\n",{"data":53,"body":54},{"name":4,"description":6},{"type":55,"children":56},"root",[57,65,104,111,136,150,198,204,380,385,391,398,403,496,501,507,580,586,632,638,672,678,709,715,827,833,838,891],{"type":58,"tag":59,"props":60,"children":61},"element","h1",{"id":4},[62],{"type":63,"value":64},"text","Investigating logs",{"type":58,"tag":66,"props":67,"children":68},"p",{},[69,71,77,79,86,88,94,96,102],{"type":63,"value":70},"Investigation is a narrowing problem: ",{"type":58,"tag":72,"props":73,"children":74},"strong",{},[75],{"type":63,"value":76},"summarize before you read",{"type":63,"value":78},".\nOne ",{"type":58,"tag":80,"props":81,"children":83},"code",{"className":82},[],[84],{"type":63,"value":85},"posthog:logs-patterns",{"type":63,"value":87}," call compresses millions of lines into at most 200 templates,\nand one ",{"type":58,"tag":80,"props":89,"children":91},{"className":90},[],[92],{"type":63,"value":93},"posthog:logs-patterns-diff",{"type":63,"value":95}," call answers \"what is different about now vs. before\" directly.\nRaw rows (",{"type":58,"tag":80,"props":97,"children":99},{"className":98},[],[100],{"type":63,"value":101},"posthog:query-logs",{"type":63,"value":103},") are the last step of an investigation, never the first.",{"type":58,"tag":105,"props":106,"children":108},"h2",{"id":107},"when-to-use-this-skill",[109],{"type":63,"value":110},"When to use this skill",{"type":58,"tag":112,"props":113,"children":114},"ul",{},[115,121,126,131],{"type":58,"tag":116,"props":117,"children":118},"li",{},[119],{"type":63,"value":120},"\"Check the logs\" \u002F \"is service X healthy?\" \u002F \"did my deploy (or model bump, config change, migration) break anything?\"",{"type":58,"tag":116,"props":122,"children":123},{},[124],{"type":63,"value":125},"\"Why are errors up?\" \u002F \"explain this spike\" \u002F incident triage — \"what changed?\"",{"type":58,"tag":116,"props":127,"children":128},{},[129],{"type":63,"value":130},"\"What is this service logging?\" — orienting in an unfamiliar or noisy stream.",{"type":58,"tag":116,"props":132,"children":133},{},[134],{"type":63,"value":135},"Finding the log evidence for a failure reported elsewhere (an alert, an error-tracking issue, a user complaint).",{"type":58,"tag":105,"props":137,"children":139},{"id":138},"when-not-to-use-this-skill",[140,142,148],{"type":63,"value":141},"When ",{"type":58,"tag":143,"props":144,"children":145},"em",{},[146],{"type":63,"value":147},"not",{"type":63,"value":149}," to use this skill",{"type":58,"tag":112,"props":151,"children":152},{},[153,166,178],{"type":58,"tag":116,"props":154,"children":155},{},[156,158,164],{"type":63,"value":157},"Creating or tuning log alerts — that's ",{"type":58,"tag":80,"props":159,"children":161},{"className":160},[],[162],{"type":63,"value":163},"authoring-log-alerts",{"type":63,"value":165},".",{"type":58,"tag":116,"props":167,"children":168},{},[169,171,177],{"type":63,"value":170},"Analytics over product events, persons, or insights — that's ",{"type":58,"tag":80,"props":172,"children":174},{"className":173},[],[175],{"type":63,"value":176},"querying-posthog-data",{"type":63,"value":165},{"type":58,"tag":116,"props":179,"children":180},{},[181,183,188,190,196],{"type":63,"value":182},"HogQL exposes a ",{"type":58,"tag":80,"props":184,"children":186},{"className":185},[],[187],{"type":63,"value":18},{"type":63,"value":189}," table via ",{"type":58,"tag":80,"props":191,"children":193},{"className":192},[],[194],{"type":63,"value":195},"posthog:execute-sql",{"type":63,"value":197},", but do not investigate through it:\nhand-written SQL over logs routinely hits read-byte caps and re-derives what the tools below do in one cheap call.\nReserve SQL for the rare case of joining log-derived facts with non-log data.",{"type":58,"tag":105,"props":199,"children":201},{"id":200},"tools",[202],{"type":63,"value":203},"Tools",{"type":58,"tag":205,"props":206,"children":207},"table",{},[208,227],{"type":58,"tag":209,"props":210,"children":211},"thead",{},[212],{"type":58,"tag":213,"props":214,"children":215},"tr",{},[216,222],{"type":58,"tag":217,"props":218,"children":219},"th",{},[220],{"type":63,"value":221},"Tool",{"type":58,"tag":217,"props":223,"children":224},{},[225],{"type":63,"value":226},"Job",{"type":58,"tag":228,"props":229,"children":230},"tbody",{},[231,249,265,281,306,323,340,364],{"type":58,"tag":213,"props":232,"children":233},{},[234,244],{"type":58,"tag":235,"props":236,"children":237},"td",{},[238],{"type":58,"tag":80,"props":239,"children":241},{"className":240},[],[242],{"type":63,"value":243},"posthog:logs-services-create",{"type":58,"tag":235,"props":245,"children":246},{},[247],{"type":63,"value":248},"Top-25 services with log_count, error_count, error_rate, sparkline. Orientation.",{"type":58,"tag":213,"props":250,"children":251},{},[252,260],{"type":58,"tag":235,"props":253,"children":254},{},[255],{"type":58,"tag":80,"props":256,"children":258},{"className":257},[],[259],{"type":63,"value":85},{"type":58,"tag":235,"props":261,"children":262},{},[263],{"type":63,"value":264},"Mine one window's message templates, ordered by frequency. \"What is this stream saying?\"",{"type":58,"tag":213,"props":266,"children":267},{},[268,276],{"type":58,"tag":235,"props":269,"children":270},{},[271],{"type":58,"tag":80,"props":272,"children":274},{"className":273},[],[275],{"type":63,"value":93},{"type":58,"tag":235,"props":277,"children":278},{},[279],{"type":63,"value":280},"Diff templates between two windows: new \u002F rate-shifted \u002F gone. \"What changed?\"",{"type":58,"tag":213,"props":282,"children":283},{},[284,301],{"type":58,"tag":235,"props":285,"children":286},{},[287,293,295],{"type":58,"tag":80,"props":288,"children":290},{"className":289},[],[291],{"type":63,"value":292},"posthog:logs-count",{"type":63,"value":294}," \u002F ",{"type":58,"tag":80,"props":296,"children":298},{"className":297},[],[299],{"type":63,"value":300},"posthog:logs-count-ranges",{"type":58,"tag":235,"props":302,"children":303},{},[304],{"type":63,"value":305},"Scalar and time-bucketed counts for a filter. Localize volume before pulling rows.",{"type":58,"tag":213,"props":307,"children":308},{},[309,318],{"type":58,"tag":235,"props":310,"children":311},{},[312],{"type":58,"tag":80,"props":313,"children":315},{"className":314},[],[316],{"type":63,"value":317},"posthog:logs-sparkline-query",{"type":58,"tag":235,"props":319,"children":320},{},[321],{"type":63,"value":322},"Volume over time broken down by severity or service (the one bucketed view with a breakdown).",{"type":58,"tag":213,"props":324,"children":325},{},[326,335],{"type":58,"tag":235,"props":327,"children":328},{},[329],{"type":58,"tag":80,"props":330,"children":332},{"className":331},[],[333],{"type":63,"value":334},"posthog:logs-facet-values-create",{"type":58,"tag":235,"props":336,"children":337},{},[338],{"type":63,"value":339},"Distribution of severity\u002Fservice (or a resource attribute) under a filter.",{"type":58,"tag":213,"props":341,"children":342},{},[343,359],{"type":58,"tag":235,"props":344,"children":345},{},[346,352,353],{"type":58,"tag":80,"props":347,"children":349},{"className":348},[],[350],{"type":63,"value":351},"posthog:logs-attributes-list",{"type":63,"value":294},{"type":58,"tag":80,"props":354,"children":356},{"className":355},[],[357],{"type":63,"value":358},"posthog:logs-attribute-values-list",{"type":58,"tag":235,"props":360,"children":361},{},[362],{"type":63,"value":363},"Discover attribute keys and values before building filters.",{"type":58,"tag":213,"props":365,"children":366},{},[367,375],{"type":58,"tag":235,"props":368,"children":369},{},[370],{"type":58,"tag":80,"props":371,"children":373},{"className":372},[],[374],{"type":63,"value":101},{"type":58,"tag":235,"props":376,"children":377},{},[378],{"type":63,"value":379},"Raw rows. Endpoint of every drill-down, entry point of none.",{"type":58,"tag":66,"props":381,"children":382},{},[383],{"type":63,"value":384},"Each tool's own description documents its parameters and response shape — read it before calling.",{"type":58,"tag":105,"props":386,"children":388},{"id":387},"pick-the-workflow-by-question-shape",[389],{"type":63,"value":390},"Pick the workflow by question shape",{"type":58,"tag":392,"props":393,"children":395},"h3",{"id":394},"is-it-healthy-post-deploy-post-change-verification",[396],{"type":63,"value":397},"\"Is it healthy?\" — post-deploy \u002F post-change verification",{"type":58,"tag":66,"props":399,"children":400},{},[401],{"type":63,"value":402},"The user changed something (deploy, model bump, config, migration) and wants to know the logs still look right.",{"type":58,"tag":404,"props":405,"children":406},"ol",{},[407,412,424,466,478],{"type":58,"tag":116,"props":408,"children":409},{},[410],{"type":63,"value":411},"Pin down the change time and the affected service(s). Ask if the user hasn't said; the diff is meaningless without a boundary.",{"type":58,"tag":116,"props":413,"children":414},{},[415,417,422],{"type":63,"value":416},"Orient with ",{"type":58,"tag":80,"props":418,"children":420},{"className":419},[],[421],{"type":63,"value":243},{"type":63,"value":423},": is the service still logging at all, and what is its error_rate now?\nA service that went silent fails verification just as hard as one that started erroring.",{"type":58,"tag":116,"props":425,"children":426},{},[427,432,434,440,442,448,450,456,458,464],{"type":58,"tag":80,"props":428,"children":430},{"className":429},[],[431],{"type":63,"value":93},{"type":63,"value":433}," with ",{"type":58,"tag":80,"props":435,"children":437},{"className":436},[],[438],{"type":63,"value":439},"query.dateRange",{"type":63,"value":441}," from the change time to now and ",{"type":58,"tag":80,"props":443,"children":445},{"className":444},[],[446],{"type":63,"value":447},"baselineDateRange",{"type":63,"value":449},"\nset to a comparable window just before the change, scoped to ",{"type":58,"tag":80,"props":451,"children":453},{"className":452},[],[454],{"type":63,"value":455},"serviceNames",{"type":63,"value":457},".\nNew error\u002Ffatal templates right after a change are the classic regression signature;\nlarge ",{"type":58,"tag":80,"props":459,"children":461},{"className":460},[],[462],{"type":63,"value":463},"rate_ratio",{"type":63,"value":465}," shifts on existing error templates are the second thing to check.",{"type":58,"tag":116,"props":467,"children":468},{},[469,471,476],{"type":63,"value":470},"Check volume continuity with ",{"type":58,"tag":80,"props":472,"children":474},{"className":473},[],[475],{"type":63,"value":300},{"type":63,"value":477}," spanning before and after the boundary:\na rate discontinuity (crash loop, restart storm, silence) shows up here even when message content looks unchanged.",{"type":58,"tag":116,"props":479,"children":480},{},[481,483,489,490,495],{"type":63,"value":482},"Drill only the suspects: pivot each suspicious pattern to raw lines via its ",{"type":58,"tag":80,"props":484,"children":486},{"className":485},[],[487],{"type":63,"value":488},"match_regex",{"type":63,"value":433},{"type":58,"tag":80,"props":491,"children":493},{"className":492},[],[494],{"type":63,"value":101},{"type":63,"value":165},{"type":58,"tag":66,"props":497,"children":498},{},[499],{"type":63,"value":500},"A pass verdict needs all three: no new error templates, no large error rate_ratio shifts, and continuous volume.\nSay which windows you compared — \"healthy\" is only as strong as the baseline.",{"type":58,"tag":392,"props":502,"children":504},{"id":503},"explain-this-spike",[505],{"type":63,"value":506},"\"Explain this spike\"",{"type":58,"tag":404,"props":508,"children":509},{},[510,538],{"type":58,"tag":116,"props":511,"children":512},{},[513,515,520,522,528,530,536],{"type":63,"value":514},"Localize it: ",{"type":58,"tag":80,"props":516,"children":518},{"className":517},[],[519],{"type":63,"value":300},{"type":63,"value":521}," over the user's window, then recurse into the dense bucket(s) — each bucket's\n",{"type":58,"tag":80,"props":523,"children":525},{"className":524},[],[526],{"type":63,"value":527},"date_from",{"type":63,"value":529},"\u002F",{"type":58,"tag":80,"props":531,"children":533},{"className":532},[],[534],{"type":63,"value":535},"date_to",{"type":63,"value":537}," feeds the next call. Stop after 3–4 levels.",{"type":58,"tag":116,"props":539,"children":540},{},[541,543,548,550,555,557,562,564,570,572,578],{"type":63,"value":542},"Explain it: ",{"type":58,"tag":80,"props":544,"children":546},{"className":545},[],[547],{"type":63,"value":93},{"type":63,"value":549}," with the spike as ",{"type":58,"tag":80,"props":551,"children":553},{"className":552},[],[554],{"type":63,"value":439},{"type":63,"value":556}," and the window just before as\n",{"type":58,"tag":80,"props":558,"children":560},{"className":559},[],[561],{"type":63,"value":447},{"type":63,"value":563},". The top ",{"type":58,"tag":80,"props":565,"children":567},{"className":566},[],[568],{"type":63,"value":569},"new",{"type":63,"value":571}," and ",{"type":58,"tag":80,"props":573,"children":575},{"className":574},[],[576],{"type":63,"value":577},"rate_shift",{"type":63,"value":579}," entries are the explanation. Do not mine both windows\nseparately and diff by hand — the diff is one call.",{"type":58,"tag":392,"props":581,"children":583},{"id":582},"incident-triage-what-broke",[584],{"type":63,"value":585},"Incident triage — \"what broke?\"",{"type":58,"tag":66,"props":587,"children":588},{},[589,594,596,601,603,608,610,615,617,623,625,631],{"type":58,"tag":80,"props":590,"children":592},{"className":591},[],[593],{"type":63,"value":93},{"type":63,"value":595}," first: incident window vs. a known-good window just before (or omit the baseline for\nsame-window-last-week). Suspects are ",{"type":58,"tag":80,"props":597,"children":599},{"className":598},[],[600],{"type":63,"value":569},{"type":63,"value":602}," entries and the biggest ",{"type":58,"tag":80,"props":604,"children":606},{"className":605},[],[607],{"type":63,"value":463},{"type":63,"value":609}," shifts; pivot each to raw lines.\nIf the failing service is unknown, find it first with ",{"type":58,"tag":80,"props":611,"children":613},{"className":612},[],[614],{"type":63,"value":334},{"type":63,"value":616}," faceting ",{"type":58,"tag":80,"props":618,"children":620},{"className":619},[],[621],{"type":63,"value":622},"service_name",{"type":63,"value":624},"\nunder ",{"type":58,"tag":80,"props":626,"children":628},{"className":627},[],[629],{"type":63,"value":630},"severityLevels: [\"error\", \"fatal\"]",{"type":63,"value":165},{"type":58,"tag":392,"props":633,"children":635},{"id":634},"what-is-this-stream-saying-unfamiliar-service",[636],{"type":63,"value":637},"\"What is this stream saying?\" — unfamiliar service",{"type":58,"tag":66,"props":639,"children":640},{},[641,646,648,654,656,662,664,670],{"type":58,"tag":80,"props":642,"children":644},{"className":643},[],[645],{"type":63,"value":85},{"type":63,"value":647}," over the last hour, scoped to the service. Scan templates by ",{"type":58,"tag":80,"props":649,"children":651},{"className":650},[],[652],{"type":63,"value":653},"estimated_count",{"type":63,"value":655}," and\nnon-zero error share in ",{"type":58,"tag":80,"props":657,"children":659},{"className":658},[],[660],{"type":63,"value":661},"severity_counts",{"type":63,"value":663},". Widen the window or add ",{"type":58,"tag":80,"props":665,"children":667},{"className":666},[],[668],{"type":63,"value":669},"searchTerm",{"type":63,"value":671}," only if the answer isn't there.",{"type":58,"tag":392,"props":673,"children":675},{"id":674},"known-needle-a-specific-message-attribute-or-person",[676],{"type":63,"value":677},"Known needle — a specific message, attribute, or person",{"type":58,"tag":66,"props":679,"children":680},{},[681,683,688,689,694,696,701,703,708],{"type":63,"value":682},"When the target is already precise (an error string, a request id, a distinct_id), skip pattern mining:\ndiscover the right keys with ",{"type":58,"tag":80,"props":684,"children":686},{"className":685},[],[687],{"type":63,"value":351},{"type":63,"value":294},{"type":58,"tag":80,"props":690,"children":692},{"className":691},[],[693],{"type":63,"value":358},{"type":63,"value":695},",\nsize the result with ",{"type":58,"tag":80,"props":697,"children":699},{"className":698},[],[700],{"type":63,"value":292},{"type":63,"value":702},", then pull rows with ",{"type":58,"tag":80,"props":704,"children":706},{"className":705},[],[707],{"type":63,"value":101},{"type":63,"value":165},{"type":58,"tag":105,"props":710,"children":712},{"id":711},"rules-that-keep-investigations-honest-and-cheap",[713],{"type":63,"value":714},"Rules that keep investigations honest and cheap",{"type":58,"tag":112,"props":716,"children":717},{},[718,730,747,760,780,806],{"type":58,"tag":116,"props":719,"children":720},{},[721,723,728],{"type":63,"value":722},"Scope ",{"type":58,"tag":80,"props":724,"children":726},{"className":725},[],[727],{"type":63,"value":455},{"type":63,"value":729}," (or a resource-attribute filter) on every call once the target service is known.\nUnscoped calls scan the whole team's stream and starve the pattern sample budget.",{"type":58,"tag":116,"props":731,"children":732},{},[733,738,740,745],{"type":58,"tag":80,"props":734,"children":736},{"className":735},[],[737],{"type":63,"value":101},{"type":63,"value":739}," requires an explicit ",{"type":58,"tag":80,"props":741,"children":743},{"className":742},[],[744],{"type":63,"value":439},{"type":63,"value":746}," — omitting it is a 400, not a default window.",{"type":58,"tag":116,"props":748,"children":749},{},[750,752,758],{"type":63,"value":751},"Pattern counts are sampled estimates (",{"type":58,"tag":80,"props":753,"children":755},{"className":754},[],[756],{"type":63,"value":757},"sampled: true",{"type":63,"value":759},"); templates rarer than ~1 in 10,000 rows can be invisible.\nAbsence of a rare template is not evidence it stopped.",{"type":58,"tag":116,"props":761,"children":762},{},[763,765,770,772,778],{"type":63,"value":764},"Before trusting a wall of ",{"type":58,"tag":80,"props":766,"children":768},{"className":767},[],[769],{"type":63,"value":569},{"type":63,"value":771}," entries in a diff, check ",{"type":58,"tag":80,"props":773,"children":775},{"className":774},[],[776],{"type":63,"value":777},"baseline.total_count",{"type":63,"value":779}," —\na tiny or empty baseline (logging only just started) makes everything look new.",{"type":58,"tag":116,"props":781,"children":782},{},[783,789,791,797,799,805],{"type":58,"tag":80,"props":784,"children":786},{"className":785},[],[787],{"type":63,"value":788},"severityLevels",{"type":63,"value":790}," matches the six canonical lowercase buckets against ",{"type":58,"tag":80,"props":792,"children":794},{"className":793},[],[795],{"type":63,"value":796},"severity_text",{"type":63,"value":798}," exactly.\nZero rows on a severity filter → check the stored values with ",{"type":58,"tag":80,"props":800,"children":802},{"className":801},[],[803],{"type":63,"value":804},"posthog:logs-attribute-values-list { key: \"severity_text\" }",{"type":63,"value":165},{"type":58,"tag":116,"props":807,"children":808},{},[809,811,817,819,825],{"type":63,"value":810},"Budget: one services call, at most one patterns-diff per window pair, 3–4 count-ranges levels,\nand ",{"type":58,"tag":80,"props":812,"children":814},{"className":813},[],[815],{"type":63,"value":816},"query-logs",{"type":63,"value":818}," only for confirmed suspects with ",{"type":58,"tag":80,"props":820,"children":822},{"className":821},[],[823],{"type":63,"value":824},"limit",{"type":63,"value":826}," ≤ 100.",{"type":58,"tag":105,"props":828,"children":830},{"id":829},"output",[831],{"type":63,"value":832},"Output",{"type":58,"tag":66,"props":834,"children":835},{},[836],{"type":63,"value":837},"Lead with the verdict, then the evidence:",{"type":58,"tag":112,"props":839,"children":840},{},[841,851,881],{"type":58,"tag":116,"props":842,"children":843},{},[844,849],{"type":58,"tag":72,"props":845,"children":846},{},[847],{"type":63,"value":848},"Verdict",{"type":63,"value":850},": healthy \u002F regressed \u002F inconclusive, with the windows compared.",{"type":58,"tag":116,"props":852,"children":853},{},[854,859,861,866,867,872,874,879],{"type":58,"tag":72,"props":855,"children":856},{},[857],{"type":63,"value":858},"Suspects",{"type":63,"value":860}," (if any): template, classification (",{"type":58,"tag":80,"props":862,"children":864},{"className":863},[],[865],{"type":63,"value":569},{"type":63,"value":294},{"type":58,"tag":80,"props":868,"children":870},{"className":869},[],[871],{"type":63,"value":577},{"type":63,"value":873},"), estimated counts or ",{"type":58,"tag":80,"props":875,"children":877},{"className":876},[],[878],{"type":63,"value":463},{"type":63,"value":880},", services, and 1–2 sample raw lines.",{"type":58,"tag":116,"props":882,"children":883},{},[884,889],{"type":58,"tag":72,"props":885,"children":886},{},[887],{"type":63,"value":888},"What was checked and what wasn't",{"type":63,"value":890},": services covered, windows, and any sampling or baseline caveats that limit confidence.",{"type":58,"tag":66,"props":892,"children":893},{},[894],{"type":63,"value":895},"The user should be able to act on the verdict without re-running the investigation.",{"items":897,"total":992},[898,912,924,936,949,962,975],{"slug":899,"name":899,"fn":900,"description":901,"org":902,"tags":903,"stars":26,"repoUrl":27,"updatedAt":911},"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},[904,906,909,910],{"name":905,"slug":34,"type":15},"Analytics",{"name":907,"slug":908,"type":15},"Cost Optimization","cost-optimization",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-07-28T05:34:11.117757",{"slug":913,"name":913,"fn":914,"description":915,"org":916,"tags":917,"stars":26,"repoUrl":27,"updatedAt":923},"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},[918,919,922],{"name":905,"slug":34,"type":15},{"name":920,"slug":921,"type":15},"Audit","audit",{"name":9,"slug":8,"type":15},"2026-06-08T08:08:33.693989",{"slug":925,"name":925,"fn":926,"description":927,"org":928,"tags":929,"stars":26,"repoUrl":27,"updatedAt":935},"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},[930,931,933,934],{"name":920,"slug":921,"type":15},{"name":932,"slug":36,"type":15},"Data Warehouse",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-06-18T08:22:57.67984",{"slug":937,"name":937,"fn":938,"description":939,"org":940,"tags":941,"stars":26,"repoUrl":27,"updatedAt":948},"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},[942,943,944,947],{"name":920,"slug":921,"type":15},{"name":932,"slug":36,"type":15},{"name":945,"slug":946,"type":15},"Performance","performance",{"name":9,"slug":8,"type":15},"2026-06-18T08:25:10.936787",{"slug":950,"name":950,"fn":951,"description":952,"org":953,"tags":954,"stars":26,"repoUrl":27,"updatedAt":961},"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},[955,958,959,960],{"name":956,"slug":957,"type":15},"Alerting","alerting",{"name":24,"slug":25,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-06-18T08:24:40.318583",{"slug":163,"name":163,"fn":963,"description":964,"org":965,"tags":966,"stars":26,"repoUrl":27,"updatedAt":974},"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},[967,968,969,970,973],{"name":905,"slug":34,"type":15},{"name":21,"slug":22,"type":15},{"name":13,"slug":14,"type":15},{"name":971,"slug":972,"type":15},"Operations","operations",{"name":9,"slug":8,"type":15},"2026-07-18T05:10:54.430898",{"slug":976,"name":976,"fn":977,"description":978,"org":979,"tags":980,"stars":26,"repoUrl":27,"updatedAt":991},"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},[981,984,987,988],{"name":982,"slug":983,"type":15},"Automation","automation",{"name":985,"slug":986,"type":15},"MCP","mcp",{"name":9,"slug":8,"type":15},{"name":989,"slug":990,"type":15},"Workflow Automation","workflow-automation","2026-07-28T05:34:12.167015",61,{"items":994,"total":1111},[995,1002,1008,1015,1022,1029,1037,1044,1058,1073,1083,1101],{"slug":899,"name":899,"fn":900,"description":901,"org":996,"tags":997,"stars":26,"repoUrl":27,"updatedAt":911},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[998,999,1000,1001],{"name":905,"slug":34,"type":15},{"name":907,"slug":908,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"slug":913,"name":913,"fn":914,"description":915,"org":1003,"tags":1004,"stars":26,"repoUrl":27,"updatedAt":923},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1005,1006,1007],{"name":905,"slug":34,"type":15},{"name":920,"slug":921,"type":15},{"name":9,"slug":8,"type":15},{"slug":925,"name":925,"fn":926,"description":927,"org":1009,"tags":1010,"stars":26,"repoUrl":27,"updatedAt":935},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1011,1012,1013,1014],{"name":920,"slug":921,"type":15},{"name":932,"slug":36,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"slug":937,"name":937,"fn":938,"description":939,"org":1016,"tags":1017,"stars":26,"repoUrl":27,"updatedAt":948},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1018,1019,1020,1021],{"name":920,"slug":921,"type":15},{"name":932,"slug":36,"type":15},{"name":945,"slug":946,"type":15},{"name":9,"slug":8,"type":15},{"slug":950,"name":950,"fn":951,"description":952,"org":1023,"tags":1024,"stars":26,"repoUrl":27,"updatedAt":961},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1025,1026,1027,1028],{"name":956,"slug":957,"type":15},{"name":24,"slug":25,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"slug":163,"name":163,"fn":963,"description":964,"org":1030,"tags":1031,"stars":26,"repoUrl":27,"updatedAt":974},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1032,1033,1034,1035,1036],{"name":905,"slug":34,"type":15},{"name":21,"slug":22,"type":15},{"name":13,"slug":14,"type":15},{"name":971,"slug":972,"type":15},{"name":9,"slug":8,"type":15},{"slug":976,"name":976,"fn":977,"description":978,"org":1038,"tags":1039,"stars":26,"repoUrl":27,"updatedAt":991},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1040,1041,1042,1043],{"name":982,"slug":983,"type":15},{"name":985,"slug":986,"type":15},{"name":9,"slug":8,"type":15},{"name":989,"slug":990,"type":15},{"slug":1045,"name":1045,"fn":1046,"description":1047,"org":1048,"tags":1049,"stars":26,"repoUrl":27,"updatedAt":1057},"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},[1050,1051,1052,1055,1056],{"name":905,"slug":34,"type":15},{"name":24,"slug":25,"type":15},{"name":1053,"slug":1054,"type":15},"Frontend","frontend",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-05-07T05:56:19.828048",{"slug":1059,"name":1059,"fn":1060,"description":1061,"org":1062,"tags":1063,"stars":26,"repoUrl":27,"updatedAt":1072},"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},[1064,1067,1068,1069],{"name":1065,"slug":1066,"type":15},"API Development","api-development",{"name":1053,"slug":1054,"type":15},{"name":9,"slug":8,"type":15},{"name":1070,"slug":1071,"type":15},"SDK","sdk","2026-06-08T08:08:34.929454",{"slug":1074,"name":1074,"fn":1075,"description":1076,"org":1077,"tags":1078,"stars":26,"repoUrl":27,"updatedAt":1082},"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},[1079,1080,1081],{"name":1065,"slug":1066,"type":15},{"name":971,"slug":972,"type":15},{"name":9,"slug":8,"type":15},"2026-07-15T05:29:58.442727",{"slug":1084,"name":1084,"fn":1085,"description":1086,"org":1087,"tags":1088,"stars":26,"repoUrl":27,"updatedAt":1100},"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},[1089,1090,1093,1094,1097],{"name":982,"slug":983,"type":15},{"name":1091,"slug":1092,"type":15},"Email","email",{"name":9,"slug":8,"type":15},{"name":1095,"slug":1096,"type":15},"Reporting","reporting",{"name":1098,"slug":1099,"type":15},"Slack","slack","2026-06-09T07:32:27.935712",{"slug":1102,"name":1102,"fn":1103,"description":1104,"org":1105,"tags":1106,"stars":26,"repoUrl":27,"updatedAt":1110},"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},[1107,1108,1109],{"name":905,"slug":34,"type":15},{"name":1065,"slug":1066,"type":15},{"name":9,"slug":8,"type":15},"2026-06-08T08:08:29.624498",231]