From posthog
Explores PostHog Inbox reports and acts on them: lists, filters, drills into, dismisses, snoozes, or converts reports into PRs. Use when users ask about their inbox or flagged issues.
How this skill is triggered — by the user, by Claude, or both
Slash command
/posthog:inbox-explorationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The **Inbox** is where PostHog surfaces signal reports — clusters of related observations
The Inbox is where PostHog surfaces signal reports — clusters of related observations (signals) that have been aggregated into a single issue or trend (e.g. "Error rate spiked 3× on /checkout"). Reports come from multiple source products: error tracking, session replay, web analytics, experiments, and integrations like Linear, GitHub, and Zendesk.
Inbox is part of PostHog Code, PostHog's agentic surface for engineering teams.
Don't assume the user's project has reports, or that any signal sources are configured — plenty of projects don't have Inbox set up. Always run the setup-check workflow below before answering the user's actual question.
For deeper investigation, hand off to other skills and tools:
signals skill — query document_embeddings via HogQL for raw signal text, semantic
search across signals, or to inspect every signal that contributed to a report.query-error-tracking-issues-list, query-error-tracking-issue,
query-error-tracking-issue-events for error-tracking-sourced reportsquery-logs, logs-count-ranges to find log activity around the issuequery-session-recordings-list, session-recording-get to find
recordings of affected userspersons-retrieve, activity-log-list to inspect a specific user's
behaviorquery-trends, execute-sql for ad-hoc verification queriesA signal report tells you what PostHog clustered. The product-specific tools tell you the underlying detail — pair them when the user wants to dig in.
| Tool | Purpose |
|---|---|
inbox-reports-list | Paginated list of reports with filters (status, search, etc.) |
inbox-reports-retrieve | Full detail for a single report |
inbox-reports-set-state | Dismiss (suppressed) or snooze (potential) a report — the one write |
inbox-source-configs-list | Configured signal sources (which products feed the inbox) |
inbox-source-configs-retrieve | Full record for a single source config |
posthog:execute-sql (signals skill) | HogQL access to underlying signals (read the signals skill first) |
The inbox-reports-*-list / -retrieve and inbox-source-configs-* tools are read-only. The
only exposed write is inbox-reports-set-state (dismiss / snooze — see Workflow: dismiss or
snooze a report). Other writes (pause processing, change source configs, mark a report resolved,
set implementation_pr_url) are not exposed via MCP today — those happen on the product surface
when a PR is opened against a report.
What each report status means (in roughly the order a triage agent should care about):
ready — judgment finished, actionable assessment availablepending_input — waiting on user input to proceedin_progress — actively being summarized / judgedcandidate / potential — accumulated signals but not yet promoted to a real reportfailed — processing erroredsuppressed — manually hidden; not surfaced by defaultBy default inbox-reports-list excludes suppressed reports and orders results by
-is_suggested_reviewer,status,-updated_at — the user's own suggested reports first, then by
status, then most recently updated. Refer to the tool's input schema for filter mechanics.
is_suggested_reviewer: true on a report means the current PostHog user is one of up to
three people the report-research flow flagged as best-placed to act on this report. It is
the strongest signal you have that a report matters to the user personally, and you should
lean on it when triaging.
How the flag is produced (see report_generation/resolve_reviewers.py):
SUGGESTED_REVIEWERS artefact on the report.is_suggested_reviewer flips to true for that
report.Practical implications for triage:
true value means "you wrote (or recently touched) the code this report is about" — not
"you were assigned this." It's heuristic, not authoritative.false value doesn't mean the report is irrelevant — it can mean (a) someone else owns
the code, (b) no one in the org has a linked GitHub account matching the suggested logins,
or (c) the source material wasn't tied to a specific repo / commits.is_suggested_reviewer: true
reports — these are the ones where the user's name is on the relevant code. Mention the
rest as a secondary group rather than mixing them in.Run this check whenever a user asks about the inbox for the first time in a session, or any
time inbox-reports-list returns count: 0. The diagnosis decides what to say next.
inbox-source-configs-list
{ "limit": 50 }
Three meaningful cases:
Case A — no source configs at all (count: 0)
The user hasn't onboarded to Inbox / signals. Don't pretend the inbox has data. Tell the user plainly that Inbox needs signal sources to be set up first, and that the recommended way to do this is to install PostHog Code at https://posthog.com/code. Example response:
Your project doesn't have any signal sources configured yet, so the Inbox is empty. Inbox surfaces issues and trends that PostHog automatically clusters from sources like error tracking, session replay, GitHub, Linear, and Zendesk. The fastest way to set this up is to install PostHog Code — once it's connected, signals will start flowing in and reports will appear in your inbox over the next day or so.
Stop here unless the user wants to discuss setup. Don't run further inbox tools — they'll all be empty.
Case B — source configs exist but all are enabled: false
Sources have been set up at some point but are currently turned off. Tell the user no signals are flowing right now and point them at the project's signals settings to re-enable. Don't go fishing for reports — anything still there is stale.
Case C — at least one source config is enabled: true
Setup looks healthy. If inbox-reports-list still returns nothing, it's most likely "give it time"
— signals are flowing but nothing has clustered into a report yet. Tell the user that, briefly
list which sources are active (e.g. "you have GitHub and error tracking enabled"), and offer to
check back later or to drop into the signals skill to look at raw signal volume.
If any source config has status: "failed", surface that as part of your reply — that source
isn't producing signals right now, which may explain a thin inbox.
If Step 1 found a healthy setup and at least one report exists, continue with the triage / drill / filter workflows below.
When the user asks "what should I look at?" or "what's actionable?":
inbox-reports-list
{
"status": "ready,in_progress,pending_input",
"limit": 20
}
If count: 0 comes back, jump to the empty/unconfigured workflow above before saying "your
inbox is empty" — the right reply depends on whether sources are configured.
For each report, the response includes:
id, title, summarystatus, priority, actionability (note: null for reports still in pending_input /
candidate — judgment hasn't run yet)signal_count, total_weight — how much underlying evidence drove the reportsource_products — which product(s) the underlying signals came fromis_suggested_reviewer — whether the current user is a suggested reviewer for this
report (see "What 'suggested reviewer' means" above — it's based on GitHub commit
authorship of the relevant code, mapped to PostHog users via linked GitHub identity)implementation_pr_url — if a PR has been opened against this report_posthogUrl — clickable deep-link to the report; always include this in your responseGroup the results so the user can scan quickly. Lead with reports where
is_suggested_reviewer: true — those are the ones tied to code the current user has
authored — and only then fall back to priority groupings for the rest:
## Inbox — 8 actionable reports
⭐ Suggested for you (1)
- Checkout error rate spiked 3× — error_tracking, 47 signals (you're a suggested reviewer)
<_posthogUrl>
🔴 High priority (2 more)
- Session replays on /pricing show repeated rage clicks — session_replay, 12 signals
<_posthogUrl>
…
🟠 Medium priority (4)
…
If no reports come back with is_suggested_reviewer: true, say so explicitly before listing
the rest — don't silently drop the section.
End with a clear hand-off: "Want me to dig into the checkout errors?" → call
inbox-reports-retrieve for the full report, then optionally hop to the signals skill to look
at the underlying signal text.
When the user pastes an Inbox URL or report ID:
inbox-reports-retrieve
{ "id": "<report_uuid>" }
Returns the full record including signals_at_run and artefact_count. Combine this with the
signals skill if the user wants to see the actual signal contents:
inbox-reports-retrieve to get the report metadata + idsignals skill's Example 2 (fetch all signals for a specific report) — pass the
report ID as metadata.report_id in the HogQL queryThe two layers complement each other: the inbox-* tools give you the curated/judged view, and
the signals skill lets you inspect the raw observations that produced it.
When the user wants to do something about a report — "fix this inbox item", "turn this into a
PR", "implement this" — not just read it. A ready report with
actionability: immediately_actionable is the usual candidate. The discipline that matters here:
a report is a diagnosis, not ground truth — verify it against the actual code before you
implement. Reports from signals_scout (and any LLM-research source) are especially worth
double-checking; their summary often reads as a confident root-cause with file and function
names, but it can be stale or wrong.
inbox-reports-retrieve
{ "id": "<report_uuid>" }
Before doing any work, look at:
already_addressed — if true, the fix may already be in flight or merged; confirm with the
user before duplicating it.implementation_pr_url — if a PR is already linked, surface it instead of opening a second one.status — only ready reports carry a finished judgment. A candidate / pending_input
report hasn't been researched yet; don't implement off a half-formed summary.The report's summary will name files, functions, and sometimes line numbers. Open them and
confirm the claim holds — that the cited code exists, still looks the way the report describes,
and actually produces the described failure. Pull the underlying signals via the signals skill
(metadata.report_id) if you need the raw evidence behind the summary. If the diagnosis doesn't
hold up, say so and stop — a wrong report is itself a useful finding (and a candidate for
dismiss below), not a license to write a speculative fix.
source_products includes signals_scout and the root cause is in a scout's own
behavior (the prompt it runs, a threshold it uses), the better fix is often the scout's
SKILL.md, not the harness. Note that per-team custom scouts live in the user's Skills Store,
not this repo, so the fix site may be out of reach of a repo PR — flag that to the user.CLAUDE.md,
area-specific skills), make the change minimal, and add a regression test that would have caught
the reported failure.Open the PR following the repo's PR conventions. There is no MCP tool to mark a report resolved
or set implementation_pr_url — that link is populated on the product surface when a PR is
opened against the report. So reference the report in the PR description (its _posthogUrl) and
tell the user which report the PR addresses, so the loop is traceable. Don't claim the report is
"resolved" in the inbox — it isn't until the product surface records the merged PR.
When the user has reviewed a report and wants it gone, or wants to defer it. This is the one inbox write exposed via MCP:
inbox-reports-set-state
{
"id": "<report_uuid>",
"state": "suppressed",
"dismissal_reason": "not_a_bug",
"dismissal_note": "Verified against products/foo/bar.py — the cited code path can't reach this state."
}
state: "suppressed" dismisses the report from the inbox; state: "potential" snoozes it back
into the pipeline. When snoozing, snooze_for: <N> holds it until it accumulates N more signals.dismissal_reason is a short caller-owned code (not_a_bug, wont_fix, duplicate, …);
dismissal_note is free-form (≤ 4000 chars). Both persist as a DISMISSAL artefact, so the
rationale survives even if the report transitions again later — always include them so a
future reader knows why.409 if it isn't allowed from the
report's current status. Confirm with the user before suppressing, and capture why in the note
— a dismissal with no rationale is worse than none. A report you dismissed because the diagnosis
was wrong (Step 2 above) is the textbook case: suppress it with the evidence in the note."Are there any reports about ?" — start with search:
inbox-reports-list
{
"search": "checkout",
"status": "ready,in_progress,pending_input",
"limit": 20
}
search matches title and summary. If the user is asking about a product area rather than a
keyword, use source_product:
inbox-reports-list
{
"source_product": "session_replay,error_tracking",
"limit": 20
}
If the keyword search returns nothing meaningful, hand off to the signals skill — semantic
search over signal text via embedText() will catch reports the keyword filter missed.
When the user asks "which signal sources are set up?" or "is hooked up?":
inbox-source-configs-list
{ "limit": 50 }
Each entry returns id, source_product, source_type, enabled, status, plus timestamps.
For full details (including the per-source config JSON — recording filters, evaluation IDs,
etc.):
inbox-source-configs-retrieve
{ "id": "<source_config_uuid>" }
Integration credentials live in a separate Integration model — they are not in the
config blob, so it's safe to summarize the contents back to the user.
The status field reflects the underlying data import or workflow:
running / completed — feeding signals normallyfailed — the source isn't currently producing signals; flag this to the userinbox-reports-list returns count: 0,
call inbox-source-configs-list first — no sources means the user needs to install
PostHog Code to start receiving signals; sources-but-no-reports
means signals are flowing but nothing has clustered yet_posthogUrl so the user can click through to the reportpriority and actionability are null for reports still in pending_input or candidate
status; this is expected, not a bug — judgment hasn't run yetsuppressed reports are excluded by default; pass status: "suppressed" explicitly if the
user wants to see hidden itemsinbox-reports-set-state (dismiss / snooze). To
act on a report (implement a fix), verify the diagnosis against the code first, then open a
PR — see Workflow: act on an actionable report. Marking a report resolved / setting
implementation_pr_url happens on the product surface, not via MCP; always also surface the
_posthogUrl deep-linksummary. Reports — especially
signals_scout ones — are LLM diagnoses; confirm the cited files / functions / behavior in the
actual code before writing a fix. A report that doesn't hold up is a dismissal candidate, not a
fixsignals skill — the report layer hides individual observations; you need
HogQL on document_embeddings to see theminbox-source-configs-retrieve returns no _posthogUrl. Don't confuse them with reportsnpx claudepluginhub anthropics/claude-plugins-official --plugin posthogQuery the document_embeddings table for raw signal data using HogQL. Use for semantic search over signals, fetching signals for a report, or listing signal types.
Delivers a daily briefing of recent changes across an Amplitude instance, surfacing anomalies, trends, and experiments from the last 1-2 days.
Discovers product opportunities by analyzing Amplitude analytics, experiments, session replays, and customer feedback. Synthesizes evidence into RICE-scored, actionable priorities.