You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .claude-plugin/plugin.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
{
2
2
"name": "posthog",
3
3
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from your AI coding tool. Optionally capture Claude Code sessions to PostHog LLM Analytics.",
Copy file name to clipboardExpand all lines: skills/authoring-scouts/SKILL.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -112,6 +112,10 @@ For an **existing scout**, tune with `posthog:scout-config-update` (find the `id
112
112
The standard flow is to make a scout and let it write — seeing what actually lands is the fastest way to calibrate it.
113
113
Set **`emit=false` (dry-run)** only when you want to be extra careful: the scout still runs and logs its reasoning but writes nothing to the inbox.
114
114
Reach for dry-run on a scout you expect to be chatty, expensive, or high-stakes; for most scouts, just writing and watching the inbox is the better loop.
115
+
-`auto_pause_exempt` — defaults to `false`.
116
+
A scout whose reports nobody acts on is warned and then paused automatically (`pause_reason=ignored`) — every run costs a sandbox agent, so a scout producing output no human consumes shouldn't keep running forever. A scout that is merely quiet is only flagged (`pause_reason=no_output`, a warning that never advances to a pause), since a watch scout's silence can be its job.
117
+
`-config-list` shows the warning as `status=pending_pause` and the pause as `status=paused_by_system`; setting `enabled=true` again resumes the scout, and marks it exempt so the sweep never overrules a person twice.
118
+
Set `auto_pause_exempt=true` up front for a watchdog scout whose whole job is to stay quiet, so it never even picks up the quiet flag.
Copy file name to clipboardExpand all lines: skills/authoring-scouts/references/lifecycle-and-testing.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,8 @@ How scouts get discovered, scheduled, and dispatched; the two distribution paths
21
21
The body is the system prompt; the agent orients, explores, files reports or remembers, and writes a one-paragraph summary to the run row.
22
22
23
23
Pausing a scout = `enabled=false`.
24
+
That records `status=paused_by_user`, which automatic lifecycle sweeps never resume or re-pause; `enabled=true` resumes from any pause, including a system-applied one (`status=paused_by_system`, cause in the read-only `pause_reason`).
25
+
Config responses expose `status` and `pause_reason` read-only; writes flow through `enabled`.
24
26
Slowing it = a larger `run_interval_minutes`.
25
27
Dry-running it = `emit=false`.
26
28
All three via `posthog:scout-config-update` (get the `id` from `-config-list`), or set at creation time in the nested `config` object passed to `posthog:scout-create-prepare`.
Copy file name to clipboardExpand all lines: skills/authoring-scouts/references/report-contract.md
+79-1Lines changed: 79 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,6 +36,7 @@ Judges the report for safety, then persists it at the judged status.
36
36
|`actionability_explanation`| string | One sentence justifying the actionability call below. |
37
37
|`actionability`| enum |`immediately_actionable` / `requires_human_input` / `not_actionable`. You make this call — the channel does not re-research it. |
38
38
|`already_addressed`| bool, default `false`| Set when the underlying issue is already handled and you're filing for the record. |
39
+
|`charts`| list, ≤20, optional | Queries the inbox draws on the report — the report's full set, replacing any it already had. Each `{chart_id, title, query, caption?, size?}`. See _Attaching charts_ below. |
39
40
40
41
**Status is decided for you, from safety × actionability:**
41
42
@@ -48,6 +49,83 @@ Judges the report for safety, then persists it at the judged status.
48
49
49
50
The result tells you what happened: `report_id` (always set when a report was persisted — **even when suppressed**, so you can edit or dedup against it), `report_status` (the birth status — `ready` / `pending_input` / `suppressed` — the field is named `report_status` in the response, not `status`), `emitted` (true only when it actually surfaced — `READY` / `PENDING_INPUT`), `safety_explanation`, and `skipped_reason` (set only when a preflight gate stopped the call before any report was created — the AI-data-processing / source-enabled gates that govern every scout write).
50
51
52
+
### Attaching charts
53
+
54
+
`charts` puts the data next to the claim, so a reader sees the move instead of taking the number on trust.
55
+
Worth it when the _shape_ is the point — a trend that broke, a distribution that shifted, a funnel step that collapsed.
56
+
A chart restating one number the summary already gives is noise; just write the number.
|`chart_id`| string, required | Your own slug (lowercase letters, numbers, `_`, `-`). How the summary points at the chart, and the key a later edit refreshes it under. Unique within the report. |
61
+
|`title`| string, required | Heading above the chart. |
62
+
|`query`| object, required | An `InsightVizNode`, `DataVisualizationNode` (a `HogQLQuery` source, plus `display` and `chartSettings` for a graph), or `SavedInsightNode` (by `shortId`). Any other `kind` is refused at write time. |
63
+
|`caption`| string, optional | One line on what to look at. |
64
+
|`size`| enum, optional |`small` / `medium` / `large`. Leave it out unless the default looks wrong — the inbox sizes a chart from its query (a big single number gets a short box, a retention grid a tall scrolling one). |
65
+
66
+
A trends chart and a graph built from SQL, as they arrive in `charts`:
**A graph from SQL needs its axes named.** Setting `display` without `chartSettings` draws an empty box; `chartSettings.xAxis.column` and `chartSettings.yAxis[].column` say which columns of the result are which.
102
+
Omit `display` altogether and the node renders the result table, which reads better than a chart for a handful of rows.
103
+
104
+
**Only the node's `kind` and its serialized size are checked on write.** A well-formed node of an allowed kind carrying a broken query is stored without complaint, then fails to draw when a reader opens the report, and nothing reports that back to the scout.
105
+
So a scout should attach a query it has already run in the same session, or point at an insight that already exists via `SavedInsightNode`, rather than composing a node from memory.
106
+
This is the single most useful thing to reinforce in a scout body that leans on charts.
107
+
108
+
**A chart query must not carry anything executable.** HogVM `bytecode` (what conditional formatting compiles to), a nested `HogQuery`, and `sendRawQuery` are each refused with a 400 wherever they sit in the node, because a chart renders data rather than running code in the reader's session.
109
+
A nested `SuggestedQuestionsQuery` is refused the same way, for cost rather than execution: its runner calls an LLM, so a chart carrying one buys a completion every time a reader opens the report.
110
+
A query over a warehouse connection is fine as long as it goes through HogQL: keep `connectionId`, drop `sendRawQuery`.
111
+
So a direct-warehouse query you ran with the raw-SQL bypass has to be rewritten before it can be attached.
112
+
113
+
**Placement comes from the summary.** A markdown link with a `chart:` target — `[Daily signups](chart:signups-drop)` — draws the chart at that point in the body; a chart you never reference still renders, after the prose.
114
+
Reference each chart once: a repeated reference reads as pointing back at the chart, not as asking for a second copy of it.
115
+
Two references in one paragraph sit side by side, so put a pair you want compared in a paragraph of their own.
116
+
A reference inside a code span, a table cell, or a heading has no room to draw — its chart falls to the end of the report instead.
117
+
118
+
**The summary has to read without the charts.** A report can also be delivered to Slack, where nothing draws and each reference degrades to the plain label it was given.
119
+
"Signups fell 60% over the week" survives that; "the chart below shows the drop" leaves a Slack reader with nothing.
120
+
121
+
**Pin the window** to absolute dates wherever the node supports it, so a reader opening the report days later sees the data you wrote about rather than whatever a relative range resolves to then.
122
+
123
+
**`charts` on an edit is the report's whole set, not an addition.**
124
+
It replaces what the report had, the way `summary` replaces the summary — so send every chart you want kept, and re-send an id under a newer window to refresh that chart.
125
+
Leave `charts` out entirely and the report keeps the ones it has; read the report first (`inbox-reports-retrieve` returns its `charts`) when you mean to add to them.
126
+
Send `charts: []` to take every chart down, for when the finding has moved on and the old chart would now mislead.
127
+
Cap is **20 charts per report** (and a combined query-size budget), which is far more than most reports should use. Each chart runs its query when the report is opened, so attach the ones that carry the argument rather than everything you looked at: three charts a reader studies beat a dozen they scroll past.
128
+
51
129
### Opening a draft PR (autostart)
52
130
53
131
A surfaced, immediately-actionable report can open a draft PR automatically — the same autostart path the pipeline uses.
@@ -105,7 +183,7 @@ The fleet's reviewer map should compound over time.
105
183
## `edit_report` — update an existing report
106
184
107
185
Rewrite `title`/`summary`, append a note, and/or set `suggested_reviewers` on a report that already exists.
108
-
Pass `run_id` (the current run) and `report_id`, plus at least one of `title`, `summary`, `append_note`, `suggested_reviewers`.
186
+
Pass `run_id` (the current run) and `report_id`, plus at least one of `title`, `summary`, `append_note`, `suggested_reviewers`, `charts`.
109
187
110
188
`edit_report` can target **any** of the team's inbox reports — not just ones a scout authored.
111
189
That makes it the right tool when a later run learns something about a report the pipeline (or another scout) created.
0 commit comments