grain
grain.
A meeting recording — list, fetch, rename, tag, or share one.
setup & usage
crée une clé API dans Grain (app → Settings → Integrations → API — voir la doc d'intégration), puis colle-la dans oto.
grain donne accès aux enregistrements de réunion, transcripts et données d'organisation, en 5 tools :
grain_recording(op="list", filter={"attendance": "hosted"}) — voir l'avertissement de portée ci-dessous, attendance est ce qui restreint à « les miennes »grain_recording(op="get", recording_id="...", include={"ai_summary": true, "highlights": true})grain_transcript(recording_id="...", format="txt"|"vtt"|"srt")grain_recording(op="update"|"tag"|"share_user"|"share_team", recording_id="...", ...)grain_recording_file(op="download", recording_id="...")grain_hook(op="create", hook_url="https://...", hook_type="recording_added")grain_hook(op="create", hook_url="https://...", hook_type="highlight_added", include={"transcript": true})grain_org(op="users"|"teams"|"meeting_types")grain_recording(op="list", filter={"team": "...", "meeting_type": "...", "title_search": "onboarding"}) — les trois filtres se combinent, confirmé en live (ids via grain_org)## ⚠️ note — un Personal Access Token voit AUSSI les réunions des autres
Vérifié en live le 2026-08-20 sur un vrai workspace : grain_recording(op="list") sans filtre attendance rend les enregistrements share_state="public" de toute l'organisation, pas seulement ceux du porteur du token — constaté concrètement : des réunions enregistrées par des collègues, où le porteur du PAT n'était même pas participant, sont remontées en premier (tri chronologique). C'est le comportement documenté par Grain (« Personal notes » + « Public notes : workspace-visible notes »), pas un bug — mais ça surprend si on s'attend à un scope « mes réunions seulement ».
Pour scoper à « mes réunions » : passer filter={"attendance": "hosted"} (réunions animées par le porteur du token) ou "attended" (réunions auxquelles il a participé) — confirmé en live, ces deux valeurs filtrent correctement. Sans ce filtre, un agent qui liste sans précaution peut faire remonter l'appel client d'un collègue dans une réponse.
list_users rend aussi l'annuaire complet du workspace (tous les membres, pas seulement le porteur) — normal, c'est un annuaire, pas du contenu de réunion.
share_with_team attendait team_id dans le corps JSON (comme share_with_user), pas dans le chemin de l'URL comme la doc le suggérait au départ — la forme documentée 404 réellement. Corrigé et reverrouillé par un testgrain_recording(op="get") utilise un POST côté Grain (pas GET) — confirmé à la fois par la doc et par le test livetag/untag, update, share_*/unshare_*, suppression de webhook) rendent {"success": true}, pas l'objet mis à jour — confirmé en livegrain_recording via include={"highlights": true}grain_hook couvre toute la surface webhooks de Grain — list/create/delete est tout ce qui existe côté Grain (pas de PATCH/update, confirmé sur la page de doc, ce n'est pas une couverture partielle)grain_hook(op="create") : Grain teste la joignabilité de hook_url à la création — l'URL doit répondre 2xx immédiatement ou l'appel échoue (confirmé en live avec une URL de test réelle) ; pour hook_type="highlight_added"|"highlight_updated", include accepte {"transcript": bool, "speakers": bool} (confirmé sur la doc) ; les événements story_* sont le SEUL moyen d'observer les Stories Grain — aucun endpoint REST ne les liste/récupère directement, la charge utile du webhook EST la donnéeinclude={"hubspot": true} sur grain_recording rend {"hubspot_company_ids": [...], "hubspot_deal_ids": [...]} ; include={"participants": true} porte aussi hs_contact_id par participant (null si non lié) — confirmé en livegrain_recording_file(op="create_upload_url") donne l'URL, l'envoi des octets se fait hors agent (le client oto-core porte upload_recording_file pour un usage scripté ; vérifié : c'est une URL S3 pré-signée sur un AUTRE host qu'api.grain.com, jamais le Bearer Grain envoyé dessus)outils
utilisation
claude plugin marketplace add otomata-tech/oto-plugin — mcp + skill configurés.pipx install oto-cli puis oto grain …