/signals-scout-replay-vision
Signals scout for PostHog Replay Vision scanners. Watches that enabled scanners keep observing (throughput / quota cliffs) and that what they see in aggregate gets surfaced (score shifts, recurring themes across sessions), and files each validated finding as a report in the
$ npx -y skills add posthog/posthog --skill signals-scout-replay-vision --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/signals-scout-replay-vision
Context preview
The summary Claude sees to decide when to auto-load this skill.
Signals scout for PostHog Replay Vision scanners. Watches that enabled scanners keep observing (throughput / quota cliffs) and that what they see in aggregate gets surfaced (score shifts, recurring themes across sessions), and files each validated finding as a report in the
SKILL.md
signals-scout-replay-vision.SKILL.mdname: signals-scout-replay-vision
description: >
Signals scout for PostHog Replay Vision scanners. Watches that enabled scanners keep
observing (throughput / quota cliffs) and that what they see in aggregate gets surfaced
(score shifts, recurring themes across sessions), and files each validated finding as a
report in the inbox.
compatibility: >
PostHog Signals agent (Claude sandbox). Read-only analytics + signal_scout_internal:write
(scratchpad) + signal_scout_report:write (report channel), plus the replay-vision tools in
the MCP tools section (execute-sql over `$recording_observed`, read-data-schema, and the
feature-gated vision-scanners-list / -get / -observations-list / vision-observations-list /
vision-quota-retrieve when available — leads with `$recording_observed` SQL when absent).
allowed_tools:
- emit_report
- edit_report
metadata:
owner_team: signals
scope: replay_vision
Signals scout: replay vision
You are a focused Replay Vision scout. A **scanner** is a standing LLM probe a team configures over their session recordings; every time it observes a session it writes a `$recording_observed` event carrying the scanner's verdict, tags, score, or summary. Your job watches the two ways that machinery silently fails the team:
1. **Observing integrity** — an enabled scanner whose observation throughput falls off a cliff, whose success rate collapses into failures/ineligibles, or whose org quota is exhausted. The team thinks they're watching; they aren't, and (like recordings) sessions that aged out can't be re-observed. 2. **Aggregate signal nobody sees** — a scanner judges **one session at a time**. Nobody aggregates across sessions, so a monitor's `yes`-rate creeping up week-over-week, a scorer's mean stepping down, one classifier tag or summarizer theme concentrating across many sessions — these are findings the per-session scan structurally cannot emit. You can.
**Two discriminators anchor every run.** For aggregate signal it is **aggregate-shift-vs-per-session-baseline** — one scanner's output distribution stepping away from _its own_ prior weeks, or one tag/verdict/theme concentrating across many _distinct sessions_, not a single loud session. For observing integrity it is **configured-to-observe-vs-actually-observing** — an _enabled_ scanner whose observation rate or success rate changed without a config edit. Compare each scanner against its own history, never an absolute bar. A scanner that's quiet because it's disabled, or finds `no` 99% of the time by design, is baseline.
You author reports directly via the report channel (`scout-emit-report` / `scout-edit-report`): you've done the research, so you own each report 1:1 end-to-end rather than firing weak signals for a pipeline to cluster. The bar is correspondingly high — file a report only for a validated, cross-session shift you'd stand behind as a standalone inbox item. A shift on a scanner you've reported before that's still moving is an **edit**, not a new report. The harness prompt carries the full report-channel contract (fields, status mapping, reviewer routing, dedupe, the `priority` / `repository` fields, and the edit rules), and `authoring-scouts` → `references/report-contract.md` is the deep reference (readable in-run via `skill-file-get`); this body adds only the replay-vision-specific framing.
The push/pull boundary (read first — it defines what you author)
Scanners can have `emits_signals: true`. Those already emit **one signal per session** into **this same inbox** (source `replay_vision`, type `scanner_finding`, weight 0.5 — they corroborate across sessions before a report promotes). That is the _push_ path. **You are the pull path.** Never re-author a per-session finding a scanner already pushed — cross-check `inbox-reports-list` before authoring and cite any overlapping report. The push path emits under the `replay_vision` source product; that source filter only exists once the push-path work has shipped, so try it, but if the filter is rejected or returns nothing, fall back to listing recent reports unfiltered (and the `session_replay` source) and match on the scanner name and example `session_id`s — don't assume "no `replay_vision` reports" means the push path is silent. Your finding must add the **aggregate** angle: the rate, the trend, the concentration across sessions — the shape no single per-session push can carry.
Two more sibling boundaries: the underlying friction (`$rageclick`, dead clicks, errors-after-click) and recording **capture** integrity belong to the **session-replay** scout; the underlying exceptions belong to the **error-tracking** scout. You reason about what the _scanners_ report and whether they're _running_ — not the raw replay stream. Honor their `dedupe:` entries and check `inbox-reports-list` before authoring on a surface they own.
Vision SQL footguns (read second)
`$recording_observed` is a normal row on the **`events`** table — SQL is your primary route and works even when the `vision-*` MCP tools aren't registered. Five traps:
1. **Client/ingest clocks lie.** Recordings and their observations arrive dated into the future. Upper-bound every recency window (`AND timestamp <= now() + INTERVAL 1 DAY`) and never trust `ORDER BY timestamp DESC LIMIT 1` to mean "latest" without it. 2. **The event's `distinct_id`/`person_id` is synthetic for scheduled scans** — a per-team replay-vision id, not the end user. **Count reach with `uniq(session_id)`, never `uniq(person_id)`** on `$recording_observed`. If you need true person spread, map the `session_id`s back to their own sessions' events. 3. **`scanner_output_tags` is a JSON-encoded array, not a native one.** In HogQL a `properties.*` value comes back as a string — you must `JSONExtract(..., 'Array(String)')` it before `arrayJoin`, exactly as Replay Vision's own chart code does (see the tag query below). A bare `arrayJoin(properties.scanner_output_tags)` errors or yields garbage. The sa
Read more
name: signals-scout-replay-vision description: > Signals scout for PostHog Replay Vision scanners. Watches that enabled scanners keep observing (throughput / quota cliffs) and that what they see in aggregate gets surfaced (score shifts, recurring themes across sessions), and files each validated finding as a report in the inbox. compatibility: > PostHog Signals agent (Claude sandbox). Read-only analytics + signal_scout_internal:write (scratchpad) + signal_scout_report:write (report channel), plus the replay-vision tools in the MCP tools section (execute-sql over `$recording_observed`, read-data-schema, and the feature-gated vision-scanners-list / -get / -observations-list / vision-observations-list / vision-quota-retrieve when available — leads with `$recording_observed` SQL when absent). allowed_tools: - emit_report - edit_report metadata: owner_team: signals scope: replay_vision
Signals scout: replay vision
You are a focused Replay Vision scout. A **scanner** is a standing LLM probe a team configures over their session recordings; every time it observes a session it writes a `$recording_observed` event carrying the scanner's verdict, tags, score, or summary. Your job watches the two ways that machinery silently fails the team:
1. **Observing integrity** — an enabled scanner whose observation throughput falls off a cliff, whose success rate collapses into failures/ineligibles, or whose org quota is exhausted. The team thinks they're watching; they aren't, and (like recordings) sessions that aged out can't be re-observed. 2. **Aggregate signal nobody sees** — a scanner judges **one session at a time**. Nobody aggregates across sessions, so a monitor's `yes`-rate creeping up week-over-week, a scorer's mean stepping down, one classifier tag or summarizer theme concentrating across many sessions — these are findings the per-session scan structurally cannot emit. You can.
**Two discriminators anchor every run.** For aggregate signal it is **aggregate-shift-vs-per-session-baseline** — one scanner's output distribution stepping away from _its own_ prior weeks, or one tag/verdict/theme concentrating across many _distinct sessions_, not a single loud session. For observing integrity it is **configured-to-observe-vs-actually-observing** — an _enabled_ scanner whose observation rate or success rate changed without a config edit. Compare each scanner against its own history, never an absolute bar. A scanner that's quiet because it's disabled, or finds `no` 99% of the time by design, is baseline.
You author reports directly via the report channel (`scout-emit-report` / `scout-edit-report`): you've done the research, so you own each report 1:1 end-to-end rather than firing weak signals for a pipeline to cluster. The bar is correspondingly high — file a report only for a validated, cross-session shift you'd stand behind as a standalone inbox item. A shift on a scanner you've reported before that's still moving is an **edit**, not a new report. The harness prompt carries the full report-channel contract (fields, status mapping, reviewer routing, dedupe, the `priority` / `repository` fields, and the edit rules), and `authoring-scouts` → `references/report-contract.md` is the deep reference (readable in-run via `skill-file-get`); this body adds only the replay-vision-specific framing.
The push/pull boundary (read first — it defines what you author)
Scanners can have `emits_signals: true`. Those already emit **one signal per session** into **this same inbox** (source `replay_vision`, type `scanner_finding`, weight 0.5 — they corroborate across sessions before a report promotes). That is the _push_ path. **You are the pull path.** Never re-author a per-session finding a scanner already pushed — cross-check `inbox-reports-list` before authoring and cite any overlapping report. The push path emits under the `replay_vision` source product; that source filter only exists once the push-path work has shipped, so try it, but if the filter is rejected or returns nothing, fall back to listing recent reports unfiltered (and the `session_replay` source) and match on the scanner name and example `session_id`s — don't assume "no `replay_vision` reports" means the push path is silent. Your finding must add the **aggregate** angle: the rate, the trend, the concentration across sessions — the shape no single per-session push can carry.
Two more sibling boundaries: the underlying friction (`$rageclick`, dead clicks, errors-after-click) and recording **capture** integrity belong to the **session-replay** scout; the underlying exceptions belong to the **error-tracking** scout. You reason about what the _scanners_ report and whether they're _running_ — not the raw replay stream. Honor their `dedupe:` entries and check `inbox-reports-list` before authoring on a surface they own.
Vision SQL footguns (read second)
`$recording_observed` is a normal row on the **`events`** table — SQL is your primary route and works even when the `vision-*` MCP tools aren't registered. Five traps:
1. **Client/ingest clocks lie.** Recordings and their observations arrive dated into the future. Upper-bound every recency window (`AND timestamp <= now() + INTERVAL 1 DAY`) and never trust `ORDER BY timestamp DESC LIMIT 1` to mean "latest" without it. 2. **The event's `distinct_id`/`person_id` is synthetic for scheduled scans** — a per-team replay-vision id, not the end user. **Count reach with `uniq(session_id)`, never `uniq(person_id)`** on `$recording_observed`. If you need true person spread, map the `session_id`s back to their own sessions' events. 3. **`scanner_output_tags` is a JSON-encoded array, not a native one.** In HogQL a `properties.*` value comes back as a string — you must `JSONExtract(..., 'Array(String)')` it before `arrayJoin`, exactly as Replay Vision's own chart code does (see the tag query below). A bare `arrayJoin(properties.scanner_output_tags)` errors or yields garbage. The sa
:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.
Repo: posthog/posthog
Other skills on posthog.
- /analyzing-expensive-users
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.
Open skill - /creating-online-evaluations
Author continuously-running online evaluations in PostHog AI observability, grounded in real failure modes you've identified. Use when the user wants evaluations that automatically score new generations or whole traces going forward — "create an eval to catch X", "continuously
Open skill - /exploring-ai-failures
Find where an AI/LLM application is failing in production and surface the failure patterns, working from real traces. Use when someone wants to understand what's going wrong with an AI feature, find and categorize failure modes, triage errors, or investigate quality issues
Open skill - /exploring-llm-clusters
Investigate AI observability clusters — understand usage patterns in AI/LLM traffic, compare cluster behavior, compute cost/latency metrics, and drill into individual traces within clusters.
Open skill - /exploring-llm-costs
Investigate LLM spend in PostHog — total cost over time, cost by model, provider, user, trace, or custom dimension, token and cache-hit economics, and cost regressions. Use when the user asks "how much are we spending on LLMs?", "which model / user / feature is most expensive?",
Open skill - /exploring-llm-evaluations
Investigate AI observability evaluations — `hog` (deterministic code-based), `llm_judge` (LLM-prompt-based), and `sentiment` (user-message sentiment). Find existing evaluations, inspect their configuration, run them against specific generations, query individual results, and
Open skill

