adding-warehouse-perso…
Sync columns from a synced data warehouse table onto PostHog person or group properties, so warehouse data becomes usable anywhere person and group properties…
Build, edit, test, enable, and monitor PostHog workflows over MCP. Author the action/edge 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,
$ npx -y skills add PostHog/ai-plugin --skill building-workflows --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/building-workflowsContext preview
The summary Claude sees to decide when to auto-load this skill.
Build, edit, test, enable, and monitor PostHog workflows over MCP. Author the action/edge 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,
name: building-workflows description: 'Build, edit, test, enable, and monitor PostHog workflows over MCP. Author the action/edge 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.'
A PostHog **workflow** is a directed graph: a list of **action nodes** (`actions`) wired by **edges** (`edges`), with exactly one `trigger` node that starts every run. You author that graph as JSON and ship it over MCP. Always call it a "workflow" to the user. "Hog flow" is the internal code name (`HogFlow`), not a user-facing term.
The single biggest failure mode is **getting the graph JSON structurally wrong**. The backend stores `actions`/`config` as loose JSON, but the visual editor parses every node against a strict schema, so a malformed node saves but then **breaks the editor view** for the whole workflow. Before composing or editing any graph, read [references/graph-schema.md](references/graph-schema.md). It is the contract; do not improvise node shapes from these examples alone.
Work the workflow through these stages. Don't jump straight to enabling it.
1. **Compose the graph.** Build `actions` + `edges` per [references/graph-schema.md](references/graph-schema.md). For any `function` node, don't guess the template: list the live catalog with `cdp-function-templates-list` and read its required inputs with `cdp-function-templates-retrieve`. 2. **Create as a draft.** `workflows-create`. Every workflow is created `draft`; it does not execute yet. 3. **Test-run it.** `workflows-test-run` runs **one step at a time**. Start at the first step (omit `current_action_id`, or point it at the trigger) with sample `globals` (`{event, person, groups}`), shaped like the trigger's real payload: an `event` trigger needs an event matching its filters, and an `internal-event` trigger needs an event named in its `filters.events` (for the Slack trigger, a `$slack_message_received` event with the Slack property bag) and no person (see [references/graph-schema.md](references/graph-schema.md)). A `status=skipped` result means this payload would not fire the trigger: if you fabricated the payload, fix it to match the trigger; if it came from a real past run (`workflows-get-invocation`), the trigger's filter is wrong, not the payload. The result includes the next step's id (`nextActionId`). Feed that back as `current_action_id` and run again, walking step by step to the end. Skip `delay` nodes by jumping to the action after them (delays aren't simulated). Async side effects (HTTP/email/SMS/push) are mocked unless you set `mock_async_functions=false`. Read each step's trace to confirm the path taken. 4. **Read logs while iterating.** `workflows-logs` shows the per-step execution trace (levels DEBUG to ERROR). This is how you see _why_ a step skipped, branched, or errored. 5. **Edit, then re-test.** Patch the graph with `workflows-patch-graph` (see [Editing a draft](#editing-a-draft)). **Every edit invalidates your earlier test** — re-run the affected path before moving on. On a draft workflow, edits apply directly; on an active one they stage a draft (see [Changing a live workflow](#changing-a-live-workflow)). 6. **Enable (needs the user's explicit sign-off).** `workflows-enable` flips it to `active` and an **event/webhook/manual** trigger starts firing on matching activity. From then on it runs on real people, and every change goes through the draft → test → publish cycle before taking effect — so finish testing, then get the user's explicit go before enabling. Don't enable on your own initiative. 7. **Dispatch (batch/schedule only).** A `batch` or `schedule` workflow does **not** fire on enable alone. Send a one-off broadcast with `workflows-run-batch`, or attach a recurring schedule with `workflows-schedule-create`. A `batch` trigger fans out to a person audience, so scheduling it needs the `workflows-blast-radius` preview and its confirm token; a `schedule` trigger runs once per occurrence with no audience, so schedule it directly. Confirm with `workflows-get` that `status=='active'` _and_ its read-only `schedules` field has an active entry. 8. **Monitor.** Drill down: `workflows-global-stats` (which workflows are failing) to `workflows-stats` (one workflow's trend) to `workflows-list-invocations` (who it failed for) to `workflows-get-invocation` (the triggering payload) to `workflows-logs` (the failing step).
Full tool catalog, grouped by job: [references/lifecycle-and-debugging.md](references/lifecycle-and-debugging.md).
**Patch, don't replace.** Edit a draft with `workflows-patch-graph`: a small, ordered list of id-addressed operations (`update_action`, `add_action`, `remove_action`, `add_edge`, `remove_edge`, `replace_action_edges`). `update_action` deep-merges its patch, so changing one email subject is a few lines, not the whole graph. The ops apply atomically server-side (read, apply in order, validate, save only if valid), and the response echoes the **full updated graph**, so you never re-fetch before the next edit. This keeps each round-trip tiny instead of re-transmitting every action and edge.
`workflows-update` covers only what a graph patch can't express: top-level fields like name, description, exit_condition, conversion, trigger_masking, and variables. It rejects `actions`/`edges` outright - a partial list would silently drop every step it omits - so every graph change goes through `workflows-patch-graph`.
After **any** patch, re-test the path you changed (step 3). A patch that validates structurally can still route the wrong way.
Email content follows the same rule. The email inside a `function_email` step is edited with **`workflows-patch-action-email`**: the same id-addressed design ops as the template patc
Official PostHog plugin for AI clients. Access PostHog products directly from your AI coding tool.
Repo: PostHog/ai-plugin
Sync columns from a synced data warehouse table onto PostHog person or group properties, so warehouse data becomes usable anywhere person and group properties…
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…
Analyze session replay patterns across experiment variants to understand user behavior differences. Use when the user wants to see how users interact with…
Split a completed PostHog task run into activity records — what the agent tried, whether it worked, what blocked it — and record each one through the…
Assesses what a page's heatmap is telling you and recommends concrete changes. Pulls click / rageclick / scroll-depth data for a URL, names the hot elements by…
Audit every endpoint in a PostHog project for staleness, failed materialisations, and unused materialised versions. Use when the user asks "what endpoints can…