creating-replay-vision-scanners

Par posthog · skills

Guide les agents dans la création et le dimensionnement sécurisé d'un scanner Replay Vision : choix du type de scanner (monitor/classifier/scorer/summarizer), construction de la RecordingsQuery qui sélectionne les sessions, et — point crucial — estimation du volume d'observations et vérification du quota mensuel de l'organisation avant la création, afin qu'un scanner trop large n'épuise pas le budget dès son premier passage planifié.\nDÉCLENCHER lorsque : l'utilisateur demande à créer, configurer ou paramétrer un scanner Replay Vision, OU lorsque vous êtes sur le point d'appeler vision-scanners-create, OU lors de l'élargissement de la query ou du sampling_rate d'un scanner existant via vision-scanners-update.\nNE PAS DÉCLENCHER lorsque : seule la lecture des scanners ou des observations est en jeu, lors de la suppression d'un scanner, ou lors de l'exécution d'un scanner existant sur une session unique à la demande (vision-scanners-scan-session).

npx skills add https://github.com/posthog/skills --skill creating-replay-vision-scanners

Créer des scanners Replay Vision

Un scanner est une sonde LLM permanente sur des enregistrements de session. Une fois créé et activé, il s'exécute selon un calendrier temporel qui balaie toutes les 5 minutes, en appliquant son prompt à chaque nouvel enregistrement correspondant et en enregistrant le résultat comme une observation (un événement $recording_observed interrogeable). Chaque observation compte dans un quota mensuel de l'organisation (un nombre fixe d'observations par mois calendaire).

C'est précisément ce calendrier qui rend nécessaire une vérification : un scanner avec une requête permissive et un échantillonnage complet commence immédiatement à consommer le quota et peut épuiser tout le budget du mois dans ses premiers balayages. La création elle-même ne vérifie pas le quota — cette protection ne s'active qu'au moment de l'observation, à quel point le budget peut déjà être épuisé.

Principe fondamental : dimensionner avant de déployer

Ne créez jamais un scanner activé à l'aveugle. Estimez son volume, vérifiez le quota restant, et — quand le volume projeté représente une part significative de ce qui reste — affichez les chiffres à l'utilisateur et obtenez une confirmation avant de créer. C'est le cœur du skill ; le reste est du détail de support.

Le flux

Étape 1 : Que doit faire le scanner ?

Choisissez un scanner_type et écrivez sa scanner_config. Chaque type nécessite un prompt ; le reste est spécifique au type :

Type Ce qu'il produit Forme de scanner_config
monitor Observation open-ended contre un prompt (ex: "signaler les clics ragés") {"prompt": "..."}
classifier Assigne des tags d'un ensemble d'étiquettes fixe {"prompt": "...", "tags": ["tag-a", "tag-b"]}tags nécessite ≥1 entrée ; "multi_label": true, "allow_freeform_tags": false optionnels
scorer Score numérique sur une rubrique {"prompt": "...", "scale": {"min": 1, "max": 5, "label": "frustration"}}min < max ; label optionnel
summarizer Résumé en texte libre ; embeddings de facettes optionnels pour la recherche {"prompt": "..."}; optionnels "length": "short" \| "medium" \| "long" (défaut "medium"), "emits_embeddings": false

scanner_type est verrouillé après création — pour le changer vous devez supprimer et recréer, donc confirmez que le type est correct d'emblée, et que la forme scanner_config est correcte (une mauvaise forme est une erreur de création, pas une valeur par défaut silencieuse).

Si l'intention de l'utilisateur rend le type et le prompt évidents, procédez simplement — ne l'interrogez pas.

Étape 2 : Quelles sessions ?

query est une forme RecordingsQuery qui sélectionne quels enregistrements le scanner surveille. date_from et date_to sont ignorés (le calendrier contrôle le temps), ne vous embêtez donc pas à les définir. Rétrécissez la requête aux sessions qui comptent réellement — par événement, URL, propriété de personne, durée, etc. Une requête étroite est le levier unique le plus important sur le coût.

sampling_rate (0..1, défaut 1.0) est un sous-échantillonnage aléatoire appliqué après que la requête trouve des correspondances. Réduisez-le pour échanger la couverture contre le budget.

Étape 3 : Le dimensionner — la vérification (ne pas sauter)

Avant de créer, exécutez les deux vérifications et raisonnez à leur sujet ensemble :

  1. Estimez le volume — appelez vision-scanners-estimate-create avec la query + sampling_rate proposées. Elle retourne matched_sessions_in_window, la window_days mesurée, et estimated_observations_per_month.
  2. Vérifiez le budget — appelez vision-quota-retrieve pour remaining et exhausted par rapport au monthly_quota mensuel de l'organisation.

Décidez ensuite :

  • Si estimated_observations_per_month s'adapte confortablement dans remaining, procédez.
  • Si c'est une large fraction de (ou dépasse) remaining, arrêtez-vous et dites à l'utilisateur les chiffres concrets — ex: "Ce scanner est projeté de produire ~X observations/mois ; vous en avez Y de Z restant ce mois." — et confirmez avant de créer, ou suggérez de resserrer la query ou de réduire d'abord sampling_rate.
  • Si l'organisation est déjà exhausted, dites-le — un nouveau scanner activé ne produira rien jusqu'à ce que le quota soit réinitialisé, et ses observations seront silencieusement ignorées.

La confirmation ici est une étape de conversation, pas une capacité API — mettez en évidence le compromis et laissez l'utilisateur choisir. Quand le volume projeté est clairement petit par rapport au budget, vous n'avez pas besoin de demander.

Étape 4 : Créer

Appelez vision-scanners-create. Exemple minimal :

{
  "name": "Rage click monitor",
  "scanner_type": "monitor",
  "scanner_config": { "prompt": "Flag sessions where the user repeatedly clicks the same element in frustration." },
  "query": { "kind": "RecordingsQuery", "events": [{ "id": "$rageclick", "type": "events" }] },
  "sampling_rate": 1.0,
  "model": "gemini-3-flash-preview",
  "enabled": true
}

name doit être unique dans l'équipe. Définissez enabled: false si l'utilisateur veut le créer en pause (pas de calendrier, pas de consommation de quota) et l'activer plus tard.

Après la création

  • Affichez l'URL PostHog du scanner depuis la réponse pour que l'utilisateur puisse l'examiner dans l'interface.
  • Les résultats prennent quelques minutes à apparaître (rastérisation de l'enregistrement en vidéo + l'appel LLM sont lents). Inspectez-les avec vision-scanners-observations-list pour un scanner dans le temps, ou vision-observations-list (nécessite session_id) pour les résultats de chaque scanner sur une seule session. Pour approfondir un enregistrement, passez le au skill investigating-replay.

Mettre à jour un scanner existant

vision-scanners-update est une mise à jour partielle — envoyez uniquement les champs modifiés. Relancez la vérification de l'étape 3 chaque fois que vous élargissez la portée : une query plus large ou un sampling_rate plus élevé augmentent le volume de balayage comme le ferait un nouveau scanner large. Basculer enabled, ajuster le prompt, ou rétrécir la requête ne nécessitent pas une ré-estimation. Éditer la config augmente scanner_version ; les observations passées conservent un instantané de l'ancienne config.

Pièges

  • Une observation par (scanner, session). Relancer un scanner sur une session qu'il a déjà observée — même une échouée ou inéligible — est un no-op et ne produira pas un nouveau scan.
  • Inéligible ≠ échoué. Les observations peuvent arriver ineligible (ex: too_short, no_recording) — une issue terminale non-erreur. Vérifiez error_reason quand vous triez pourquoi un scanner n'a rien produit.
  • Provider/model sont Google/Gemini uniquement dans la version actuelle.

Skills similaires