Skip to content
Development
Skill

/signals-scout-replay-vision

Signals scout for PostHog Replay Vision scanners. Watches that enabled scanners keep observing (throughput and quota cliffs) and that aggregate score shifts and recurring themes get surfaced.

From plugin
posthog
84164 skills1 agent3 commands2 hooks
+1
Install
$ npx -y skills add PostHog/ai-plugin --skill signals-scout-replay-vision --agent claude-code

How 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 and quota cliffs) and that aggregate score shifts and recurring themes get surfaced.

SKILL.md

signals-scout-replay-vision.SKILL.md
name: signals-scout-replay-vision
description: >
  Signals scout for PostHog Replay Vision scanners. Watches that enabled scanners keep observing
  (throughput and quota cliffs) and that aggregate score shifts and recurring themes get
  surfaced.
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, so filter on it; when it returns nothing, also scan recent reports unfiltered (and the `session_replay` source) and match on the scanner name and example `session_id`s, since a per-session finding can reach the inbox clustered under a neighboring surface. 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 same applies to `scanner_output_tags_freeform` — union both, or you miss the freeform tags that are often the ones concentrating. 4. **Group and filter scanners by `scanner_id`, n

Read more
Ships withposthog

Official PostHog plugin for AI clients. Access PostHog products directly from your AI coding tool.

Get the whole plugin

Other skills on posthog.