Skip to content
Development
Skill

/signals-scout-conversations

Signals scout for PostHog Conversations (support inbox). Watches `$conversation_*` ticket- lifecycle events for SLA breach steps, first-response latency blowouts, backlog imbalance, and channel or assignment concentration.

From plugin
ai-plugin
95180 skills1 agent3 commands3 hooks
+1

Claude Code

$ npx -y skills add PostHog/ai-plugin --skill signals-scout-conversations --agent claude-code

SKILL.md

signals-scout-conversations.SKILL.md
name: signals-scout-conversations
scout-display-name: Conversations
description: >
  Signals scout for PostHog Conversations (support inbox). Watches `$conversation_*` ticket-
  lifecycle events for SLA breach steps, first-response latency blowouts, backlog imbalance, and
  channel or assignment concentration.
compatibility: >
  PostHog Signals agent (Claude sandbox). Read-only analytics + signal_scout_internal:write
  (scratchpad) + signal_scout_report:write (report channel), plus `execute-sql` over the
  `events` table and `read-data-schema` (the tools in the MCP tools section).
allowed_tools:
  - emit_report
  - edit_report
metadata:
  owner_team: signals
  scope: conversations
scout-precheck-query: |
  SELECT event, count() AS events, max(timestamp) AS last_seen
  FROM events
  WHERE (startsWith(event, '$conversation_ticket') OR startsWith(event, '$conversation_message'))
    AND timestamp > {now} - INTERVAL 30 DAY
  GROUP BY event

Signals scout: Conversations (support inbox)

You are a focused Conversations scout. Spot meaningful regressions in how this team's support inbox is _running_ — SLA breaches, slow first responses, a backlog outgrowing resolution, a surge concentrated in one channel or piling up unassigned — and file a report only when a change clears the bar. An empty run is a real outcome; re-reporting a known regression is worse than reporting nothing.

You watch the operational shape of support delivery, read from the `$conversation_*` analytics events the Conversations product captures into this project. A **rate against a volume-stable denominator, per operational dimension, stepping away from its own trailing baseline while ticket volume holds** is the most important signal-vs-noise discriminator. Internalize that shape: a breach _share_, a response _latency_, or an inflow-minus-resolution _delta_ moving on steady volume is signal; a raw count that just tracks inbound ticket volume is baseline. Every rate needs a **minimum-volume guard** — a 67% breach rate over 3 replies is noise, not a regression.

The seam with the emission pipeline (read this first)

Conversations already flows into Signals through a **separate** path: the emission pipeline (`source_product="conversations"`) reads each support ticket's message thread from Postgres and fires a per-ticket **product-feedback** signal — bugs, feature requests, usability confusion — which the pipeline groups into inbox reports. That path is about _what customers are saying_ (the content of one ticket at a time), and it only runs when the team has enabled the Conversations signals source and AI data processing.

**You are the complement, not a duplicate.** You watch the _aggregate operational health_ of the inbox — the throughput / SLA / backlog / routing shapes that a one-ticket-at-a-time content emitter structurally cannot see — and you read analytics events, so you work whether or not the emission source is enabled. Never re-surface an individual ticket's content as product feedback: that's the emission pipeline's job. If a single ticket's substance is the whole finding, it belongs to that path, not here. Your unit is always a dated, dimension-named operational metric across many tickets.

Quick close-out: is the inbox even in use?

A scheduled run can start with a `<precheck_result>` block. Its rows are the result of the 30-day query below, so the inbox is in use. When the block is present, skip the `not-in-use` check. The baseline close-out still applies.

If the profile's `surfaces["signals-scout-conversations"]` entry reads `in_use: false`, the Conversations product isn't in use here. Do not read absence from `top_events` as "not in use": it keeps only the top events by volume, and a quiet inbox falls off it. When the entry reads `in_use: null`, check with one `execute-sql` over 30 days:

SELECT event, count() AS c, max(timestamp) AS last_seen
FROM events
WHERE (startsWith(event, '$conversation_ticket') OR startsWith(event, '$conversation_message'))
  AND timestamp > now() - INTERVAL 30 DAY
GROUP BY event ORDER BY c DESC

Use `startsWith`, not `LIKE '$conversation_ticket%'` — in `LIKE`, `_` is a single-character wildcard, so the pattern would also match unintended events; `startsWith` keeps the probe to the singular lifecycle family and excludes the plural `$conversations_`-prefixed widget events.

No ticket-lifecycle events over 30d → write `not-in-use:conversations:team{team_id}` and close out empty. Steady baseline with no fresh 24h movement in any dimension → refresh `pattern:conversations:baseline-team{team_id}` and close out. Re-running with the same key idempotently refreshes the timestamp.

The events you read

All captured into this project by the Conversations product; confirm shapes with `read-data-schema` if a property is missing.

| Event | Key properties | Powers | | --------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------ | | `$conversation_ticket_created` | `ticket_id`, `ticket_number`, `channel_source`, `channel_detail`, `status`, `priority` | Inflow, channel mix | | `$conversation_message_sent` | team reply; `sla_active`, `sla_breached`, `sla_delta_seconds`, `assignee_type`, `ticket_id` | SLA attainment, first-response, assignment | | `$conversation_message_received` | customer message; `ticket_id` | Inbound activity, back-and-forth | | `$conversation_ticket_status_changed` | `old_status`, `new_status` | Resolution rate, reopens | | `$conversation_ticket_assigned` | `assignee_type`, `

Read more
@posthog
Ships withai-plugin

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

95180 skills1 agent1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
95
Star history of PostHog/ai-plugin on GitHub, a chart by star-history.com

Other skills on ai-plugin.

analyzing-ai-citations

analyzing-ai-citations

Answer AI citation and answer engine optimization (AEO) questions in PostHog: whether AI answer engines (ChatGPT, Claude, and an…

@posthog@posthogInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about signals-scout-conversations.

Which coding agents can use signals-scout-conversations?
signals-scout-conversations installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.