Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion context/agents/integration-v2/integrate-posthog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ Plan a PostHog integration and seed the task queue with this graph:
its tests.
- `dashboard`, after `build` — only once the integration is confirmed building,
linting, and testing cleanly.
- `report`, after `dashboard` — it writes the setup report last.
- `subscribe`, after `dashboard` — with the user's consent, it subscribes them to
the new dashboard by email and alerts on its highest-signal insights.
- `report`, after `dashboard` and `subscribe` — it writes the setup report last.

## How you know you succeeded

Expand Down
2 changes: 1 addition & 1 deletion context/agents/integration-v2/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ effort_sdk: high
skills: [integration-v2-report, integration-v2-notebook, integration-v2-mcp]
allowedTools: [Read, Write, Glob, Grep]
disallowedTools: [enqueue_task]
dependsOn: [dashboard]
dependsOn: [dashboard, subscribe]
---

## Goal
Expand Down
39 changes: 39 additions & 0 deletions context/agents/integration-v2/subscribe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
type: subscribe
flow: integration-v2
label: Subscribe the user to the dashboard
model_pi: openai/gpt-5.6-luna
effort_pi: medium
model_sdk: claude-sonnet-4-6
effort_sdk: high
skills: [dashboard-subscriptions, wizard-ask, integration-v2-mcp]
allowedTools: [Read, Glob, Grep]
disallowedTools: [Write, Edit, Bash, enqueue_task]
dependsOn: [dashboard]
---

## Goal

A dashboard nobody revisits is dead weight. Set up a weekly email subscription for
the dashboard the previous step created, plus up to two alerts on its
highest-signal insights, so the wizard's output reaches an inbox and the metrics
that actually matter get flagged.

This step schedules a real recurring email and enrols the user in alert
notifications, standing side effects beyond the code integration they asked for.
Get consent before creating anything.

## The question

Ask exactly this, then follow the answer:

- "Want a weekly email digest of your new dashboard, plus alerts on up to two of
its most important insights that email you when they move the wrong way?"
- Yes: create the subscription and the alerts.
- No: skip this whole step and create nothing.

## How you know you succeeded

Either the user declined and nothing was created, or what they agreed to exists in
PostHog with a link to each created record in your handoff, plus which insight(s)
got an alert and why. The report step relays this to the user.
9 changes: 9 additions & 0 deletions context/skills/dashboard-subscriptions/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type: skill
template: description.md
description: Set up a dashboard email subscription and alerts on its highest-signal insights
tags: [dashboard, subscriptions, alerts]
variants:
- id: all
display_name: Dashboard subscriptions and alerts
tags: [dashboard, subscriptions, alerts]
docs_urls: []
44 changes: 44 additions & 0 deletions context/skills/dashboard-subscriptions/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Set up a subscription and alerts so a dashboard reaches an inbox

This sets up a real recurring email and enrols the user in alert notifications for
a target dashboard.

Call `user-get` with uuid `@me` for the current user's id and email. If no email
comes back (service account, unusual SSO), skip the subscription — don't invent a
recipient, note the skip — and still create the alerts, which key off the id, not
the email.

1. **One dashboard subscription (`subscriptions-create`).** Weekly email digest of
the target dashboard: `target_type: "email"`, `target_value` set to the user's
email from `user-get`, `dashboard` set to the dashboard id,
`dashboard_export_insights` set to up to 6 of its insight ids (or fewer if the
dashboard has fewer), `frequency: "weekly"`, `interval: 1` (every 1 week),
`start_date` set to now. Leave `summary_enabled` off — enabling AI summaries
needs its own separate human OK.
2. **One or two insight alerts (`alert-create`)**, only on the insight(s) that
would actually cost the business something if they moved the wrong way — a
conversion funnel dropping, a churn/drop-off event spiking, signups stalling.
Skip "nice to watch" insights (e.g. a raw pageview count), and if nothing on
the dashboard clearly qualifies, create zero rather than padding to the
ceiling. For a funnel step, use `condition: { type: "relative_decrease" }` with
a `FunnelsAlertConfig`; for a trend that should stay above/below a bound, use a
`TrendsAlertConfig` with `threshold.configuration.bounds`. Set
`subscribed_users` to `[<the numeric id from user-get>]` (the integer id, not
the uuid) and `calculation_interval: "daily"` unless the insight's own interval
argues for something coarser.

The create calls return the new records but not a link, so build each URL with
`generate-app-url` from the ids you just got back — never hand-construct these
paths. For the subscription, call `generate-app-url` with `url` set to
`/dashboard/{id}/subscriptions/{subscriptionId}` and `params`
`{ "id": <dashboard id>, "subscriptionId": <id from subscriptions-create> }`. For
each alert, call `generate-app-url` with `url` set to
`/insights/{insightShortId}/alerts` and `params`
`{ "insightShortId": <short id of the alert's insight> }`.

When writing up what was created, briefly explain what a subscription is (a
recurring email snapshot of the dashboard) and what an alert is (a one-off email
the moment a specific metric crosses a threshold), and name which insight(s) got
an alert and why they were judged the highest-signal ones. Remind the user to
check the subscription and alert(s) went to the right inbox and cadence — the
defaults are their account email and a weekly/daily schedule.
22 changes: 0 additions & 22 deletions context/skills/integration/references/4-conclude.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,6 @@ Valid `trendsFilter.display` values are `ActionsLineGraph`, `ActionsBar`, `Actio

Once the dashboard exists, emit its URL on its own line in your assistant message using this exact marker: `[DASHBOARD_URL] <full https url>`. The wizard parses this marker from your visible message and surfaces the link in the success summary. Mentioning the URL only in thinking or in prose without the marker means the link is dropped.

### Set up a subscription and alerts so the dashboard reaches an inbox

This step schedules a real recurring email and enrols the user in alert notifications — standing side effects beyond the code integration they asked for, so get consent first.

**Ask before creating anything.** Tell the user you'd like to set up a weekly email digest of the new dashboard plus up to two alerts on its highest-signal insights, say in one line what each is, and get a yes/no. If they decline, skip this whole section.

On a yes, call `user-get` with uuid `@me` for the current user's id and email. If no email comes back (service account, unusual SSO), skip the subscription — don't invent a recipient, note the skip in the report — and still create the alerts, which key off the id, not the email.

1. **One dashboard subscription (`subscriptions-create`).** Weekly email digest of the dashboard just created: `target_type: "email"`, `target_value` set to the user's email from `user-get`, `dashboard` set to the new dashboard id, `dashboard_export_insights` set to up to 6 of its insight ids (or fewer if the dashboard has fewer), `frequency: "weekly"`, `interval: 1` (every 1 week), `start_date` set to now. Leave `summary_enabled` off — enabling AI summaries needs its own separate human OK that this consent didn't cover.
2. **One or two insight alerts (`alert-create`)**, only on the insight(s) that would actually cost the business something if they moved the wrong way — a conversion funnel dropping, a churn/drop-off event spiking, signups stalling. Skip "nice to watch" insights (e.g. a raw pageview count), and if nothing on the dashboard clearly qualifies, create zero rather than padding to the ceiling. For a funnel step, use `condition: { type: "relative_decrease" }` with a `FunnelsAlertConfig`; for a trend that should stay above/below a bound, use a `TrendsAlertConfig` with `threshold.configuration.bounds`. Set `subscribed_users` to `[<the numeric `id` from `user-get`>]` (the integer id, not the uuid) and `calculation_interval: "daily"` unless the insight's own interval argues for something coarser.

The create calls return the new records but not a link, so build each URL with `generate-app-url` from the ids you just got back — never hand-construct these paths. For the subscription, `call generate-app-url` with `url` set to `/dashboard/{id}/subscriptions/{subscriptionId}` and `params` `{ "id": <dashboard id>, "subscriptionId": <id from subscriptions-create> }`. For each alert, `call generate-app-url` with `url` set to `/insights/{insightShortId}/alerts` and `params` `{ "insightShortId": <short id of the alert's insight> }`.

When writing the setup report, briefly explain what a subscription is (a recurring email snapshot of the dashboard) and what an alert is (a one-off email the moment a specific metric crosses a threshold), and name which insight(s) got an alert and why they were judged the highest-signal ones.

Search for a file called `.posthog-events.json` and read it for available events.

Do not spawn subagents.
Expand All @@ -104,10 +89,6 @@ We've built some insights and a dashboard for you to keep an eye on user behavio

[links]

[one line explaining the dashboard subscription: what it is, cadence, and which email it goes to, with a link to it in PostHog]

[one line per alert: which insight it watches, the condition, that it emails on breach, why that metric moving is worth caring about, and a link to it in PostHog]

## Verify before merging

[checklist]
Expand All @@ -126,7 +107,6 @@ For the "Verify before merging" checklist, write GitHub-style checkboxes (`- [ ]
- If this integration ships a minified production browser bundle (most SPA/SSR web frameworks — e.g. Next.js, Nuxt, SvelteKit, Astro, Vite-based apps): "Wire source-map upload (`posthog-cli sourcemap` or your bundler's upload step) into CI so production stack traces de-minify."
- If LLM analytics was set up in this run: "Trigger the LLM call path(s) you instrumented and confirm `$ai_generation` events appear in PostHog AI Observability."
- If the app has user auth and an `identify` call was added: "Confirm the returning-visitor path also calls `identify` — a handler that only identifies on fresh login can leave returning sessions on anonymous distinct IDs."
- Always (if a subscription or alert was created): "Check the dashboard subscription and alert(s) went to the right inbox and cadence — the wizard defaulted to your account email and a weekly/daily schedule."

Do not invent items beyond what applies. If only the two "Always" items apply, the checklist is just those two.

Expand All @@ -139,7 +119,5 @@ Upon completion, update `.posthog-events.json` so it matches the events you actu
Status to report in this phase:

- Configured dashboard: [insert PostHog dashboard URL]
- Configured dashboard subscription: [recipient email, frequency]
- Configured alert(s): [insight name(s), condition]
- Created setup report: [insert full local file path]
- Created notebook: [insert PostHog notebook URL]
9 changes: 9 additions & 0 deletions context/skills/wizard-ask/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type: skill
template: description.md
description: Ask the user structured questions through the wizard and act on their answers
tags: [wizard, ask]
variants:
- id: all
display_name: Asking the user through the wizard
tags: [wizard, ask]
docs_urls: []
43 changes: 43 additions & 0 deletions context/skills/wizard-ask/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Asking the user through the wizard

`wizard_ask` puts structured questions in front of the user in the wizard's own UI
and waits for their answers. Use it whenever you would otherwise inline a question
in your text output.

One call carries 1–8 questions:

```json
{
"questions": [
{
"id": "<your-question-id>",
"prompt": "<the question, one line>",
"kind": "single",
"options": [
{ "label": "<what the user sees>", "value": "<what you get back>" },
{ "label": "<another choice>", "value": "<its value>" }
]
},
{ "id": "<another-id>", "prompt": "<a free-text question>", "kind": "text" }
]
}
```

- `id` — unique per question; answers come back keyed by it.
- `kind` — `single` (pick one), `multi` (pick several), `text` (free entry).
`single` and `multi` require at least one `{ label, value }` option.
- `required` — defaults to true. Mark a question `required: false` when a blank
answer is acceptable and you have a sensible default to fall back on.
- `sensitive` — `text` only. The answer goes into the wizard's secret vault and
you receive `{ secretRef: "secret:..." }` instead of the raw string. Only
wizard tools that accept refs (e.g. `set_env_values`) can resolve it — other
MCP tools reject it, so write a secret to the env first if another tool needs it.

Batch related questions into a single call rather than asking one at a time —
sequential calls are for questions that genuinely depend on earlier answers, and
the wizard nudges then caps agents that dribble questions out.

A cancelled or timed-out overlay means the user declined: fall back gracefully —
your defaults, a deep link, or skipping the optional work with a note — and don't
re-ask. In a non-interactive run the tool returns an error saying so; do what it
instructs (proceed on defaults, or abort if the answer was truly required).
Loading