Produits SMS natifs

Construis un produit dont l'interface est constituée de SMS plutôt que d'une application ou d'un site web — « pas d'appli, pas de site », « ils envoient juste un texto à un numéro », « discute avec notre agent via SMS natifs », « peut-on faire ça par texto », « un bot SMS », « un bot Telegram », « transforme-le en groupe de discussion », « friction minimale ». S'applique également quand tout a mal tourné — « ma campagne a été rejetée », « notre numéro est bloqué », « les textos n'arrivent pas », « pourquoi dois-je m'enregistrer ». Couvre la barrière qui décide si un tel produit peut envoyer des messages (enregistrement US A2P 10DLC, règles de contenu SHAFT, codes de rejet permanent), les MMS de groupe depuis du code, ce que chaque canal ne peut pas faire, une architecture qui survit à la perte du canal, et la protection du contenu utilisateur réécrit par un modèle.

Qu'est-ce que Produits SMS natifs ?

Ce skill aide les ingénieurs et agents IA à concevoir des produits dont l'interface utilisateur est exclusivement basée sur les SMS (ou Telegram, WhatsApp), sans application ni site web. Il met l'accent sur la barrière réglementaire US A2P 10DLC (étape 0), qui peut bloquer définitivement l'envoi de messages si le contenu est classé SHAFT (Sexe, Haine, Alcool, Armes à feu, Tabac) ou si l'enregistrement est trompeur. Le skill détaille les capacités et limitations des canaux : groupe MMS via Twilio Conversations (limité à 10 participants, +1 longs codes uniquement), absence de création de groupes Telegram par bot, pas de messagerie de groupe WhatsApp Cloud API, et coûts élevés des API iMessage. L'architecture préconisée sépare strictement le moteur de décision (machine) des effets (envoi de messages), avec un simulateur qui exécute le même code que la production pour tester les scénarios temporels. Enfin, il traite de la réécriture de contenu utilisateur par un modèle (LLM) en imposant des garde-fous contre l'invention de faits, et de la gestion robuste des commandes STOP/HELP avant toute logique applicative.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/2016judea/brick-mortar-skills/tree/HEAD/skills/sms-native-product

Installed? Explore more Productivité et collaboration skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Produits dont l'interface est constituée de SMS

L'attrait est réel : les gens n'aiment pas installer d'applications ni visiter des sites web, mais tout le monde peut envoyer un texto. Le problème est que vous ne possédez pas le canal. Les opérateurs américains, oui, et ils ont une politique de contenu et un processus d'approbation qui peuvent vous refuser définitivement. Cette barrière décide ce que le produit est autorisé à être, donc elle passe en premier.


Étape 0 — la barrière. Fais ceci avant la conception, pas après.

Depuis février 2025, les opérateurs américains bloquent le trafic A2P non enregistré, donc une marque et une campagne doivent être approuvées avant l'envoi du premier message. Relis la documentation d'erreur en direct à chaque fois ; la politique des opérateurs évolue.

CodeDéclencheurNouvelle soumission ?
30953langage explicite/suggestif, ou un site lié hébergeant du « contenu pornographique, d'escorte, de rencontres ou de divertissement pour adultes »Non
30885« risque élevé » — marketing trompeur, ou un enregistrement qui dénature le traficNon
30898trop de marques sur un seul EIN, ou un enregistrement à l'apparence duplicativeOui, avec motif

Règle : nomme la catégorie de contenu du produit à voix haute dans la première réponse, et dis si elle est sur cette liste. Si la catégorie (par exemple, rencontres) est littéralement un mot-clé dans une règle de rejet, le trouver à la minute cinq change l'architecture, le texte de la page d'atterrissage et le plan de repli. SHAFT est l'abréviation : Sexe, Haine, Alcool, Armes à feu, Tabac — plus le Cannabis, et les rencontres sont associées.

Règle : enregistre un projet secondaire en tant que marque de Sole Proprietor, pas sous l'EIN d'une entreprise existante. Les modèles de risque suivent le numéro d'identification fiscale (30898), donc un refus sur un projet secondaire ne doit pas affecter la capacité d'envoi de votre activité principale. Sole Proprietor est limité aux particuliers sans numéro d'identification fiscale ; le débit est faible, et faible est suffisant pour une bêta.

Règle : ne construis jamais une page d'atterrissage factice pour faire approuver une campagne. Une page qui cache ce qu'est réellement le trafic est le motif 30885, et elle transforme un risque à un seul numéro en un risque pour chaque numéro que vous enregistrerez jamais. Énonce les probabilités clairement et laisse le propriétaire décider.

Décris le service par ce qu'il fait mécaniquement, et seulement si c'est vrai (par exemple, journaling et responsabilité en petit groupe, quand c'est ce que sont les messages). Si aucune description vraie ne franchit la barrière, la réponse est un canal différent, pas un meilleur euphémisme.

La vérification récompense les faits que vous pouvez montrer : opt-in entrant uniquement, volume conversationnel, pas de liens dans les messages récurrents, STOP traité avant tout, contenu explicite refusé à la porte.

Étape 0.5 — lis le brief pour les NOMBRES et les OBJETS, pas pour l'intention

Conserve le brief du fondateur textuellement comme README.md et dis dans CLAUDE.md qu'il prime sur tout document d'ingénierie.

Règle : avant d'écrire une machine à états, liste chaque durée dans le brief et chaque nom sur lequel elle agit. S'il existe deux durées, ce sont deux fonctionnalités. Un brief avec un délai d'une semaine sur les réponses des amis parvenant à l'auteur et un verrouillage de deux semaines sur la propre mise à jour de l'auteur est facile à réduire en un seul blocage de sept jours sur l'entrée — le seul objet dont aucun des deux délais ne parlait — et chaque erreur en aval découle de cette fusion.

**Règle : nomme l'objet de chaque délai — « retenu DE qui ». ** Retenu des amis et retenu de l'auteur sont des produits opposés.

Règle : lorsque la conception littérale du brief ne peut pas être appliquée sur le canal, dis-le et donne les alternatives — ne choisis pas silencieusement celle qui est applicable. (Le créateur d'un groupe de discussion en est membre, donc aucun code ne peut lui refuser les réponses du groupe.) C'est une décision de principe, et les décisions de principe appartiennent au propriétaire.

Une mauvaise lecture cohérente n'en a pas l'air. Conserve un paragraphe de conception remplacé barré en place plutôt que de le supprimer ; cela montre à une session ultérieure comment le brief a été mal lu.

Étape 1 — ce que le canal peut et ne peut pas faire

  • L'envoi de textos de groupe depuis du code fonctionne. Twilio Conversations gère les MMS de groupe sur les +1 longs codes uniquement — pas les numéros gratuits, pas les codes courts — limité à 10 participants, y compris votre propre numéro. Ne prétends pas le contraire de mémoire.
  • Les participants SMS aux MMS de groupe portent une Address et pas de ProxyAddress, donc un numéro sert chaque salon — mais la règle d'unicité participant/proxy (50425) n'a aucun comportement documenté pour les participants sans proxy. Ne conçois jamais plusieurs salons simultanés qui partagent un numéro et un ensemble de participants. Un salon durable par personne a un ensemble de participants stable.
  • Une page web ne peut pas lire le carnet d'adresses d'un iPhone. L'API Contact Picker est Chrome-sur-Android uniquement. « Synchronise tes contacts » est mort à l'arrivée ; remplace-le par une ligne que l'utilisateur transmet — le texto entrant du destinataire est l'enregistrement de consentement que les opérateurs veulent de toute façon.
  • Un bot Telegram ne peut pas créer de groupe ni ajouter personne à un groupe, et avec le mode confidentialité activé, il n'entend que les commandes qui lui sont adressées. Les deux aident : le créateur ajoute le bot à la discussion qu'il a déjà, et les bavardages généraux ne peuvent pas être confondus avec une entrée. Créer un bot nécessite un humain dans @BotFather (pas d'API) ; demande le token.
  • WhatsApp Cloud API n'a pas de messagerie de groupe.
  • Les API iMessage (Sendblue, LoopMessage) gèrent les bulles bleues et les vrais groupes de discussion, mais coûtent environ 100 $/ligne/mois plus les frais d'installation.

Étape 2 — architecture qui survit à la perte du canal

Parce que le canal peut être refusé, le transport doit être un seul fichier :

machine.js   pur : (contexte, événement) -> {réponses, effets}    pas d'E/S, pas d'horloge
engine.js    assemblage du contexte -> machine -> effets          le chemin complet
effects.js   createEffects({db, canal})                          exécute les décisions
twilio.js  / telegram.js                                         interchangeables
api/*.js     shims fins sur engine.js                            ~10 lignes chacun
sim/         db en mémoire + canal console
  • Le cœur de décision prend now comme argument et ne touche à aucun réseau. Chaque bogue dans cette classe de produit est un bogue de séquencement (un rappel qui se déclenche deux fois, un message dans un salon vide, un élément retenu qui n'arrive jamais), et aucun n'est testable contre un réseau en direct et une minuterie de sept jours.
  • Les adaptateurs sont des arguments, jamais des imports, dans la couche d'effets — le même refactor dont le simulateur et le canal de repli ont besoin.
  • Aucune logique dans un gestionnaire HTTP. L'intégration spécifique au canal écrite dans api/telegram.js est non testable ; extrayez-la.

Étape 3 — pilote-le, ne te contente pas de le tester

node sim/drive.js          scénarisé : la boucle complète, une semaine sautée, les gardes
node sim/drive.js --repl   tape comme n'importe quel numéro ; /as <n>  /jump <jours>  /state
  • Le simulateur doit exécuter le chemin de production, pas une copie parallèle.
  • Attends-toi à ce qu'un premier pilotage révèle plusieurs défauts réels que les tests unitaires ne peuvent pas atteindre : un salon qui se salue avant que quiconque y soit, un jour de la semaine nu pour une date à une semaine, un rappel qui ne dit pas à quel élément il fait référence, un salon dont tous les membres sont partis.
  • Lorsqu'un test échoue, vérifie d'abord le test (une regex de date qui n'accepte pas la virgule dans dim., 30 août ; un doesNotMatch qui se déclenche sur un autre message légitime).
  • Ne décide ni n'imprime jamais à partir d'un horodatage estampillé par le magasin. Le magasin écrit created_at à partir de l'horloge réelle, pas du now injecté par le moteur, donc sous une horloge sautée, il ment (et imprime des dates dans le passé). Décide uniquement à partir des colonnes que la machine a écrites, et attache les dates connexes à un ancrage stocké.

Étape 4 — texte pour un écran verrouillé

Un seul fichier contient chaque chaîne sortante.

  • Pas d'emoji, pas de points d'exclamation, pas de marketing.
  • Jamais de jour de la semaine nu pour une date à plus d'un jour ou deux. dim. 30 août.
  • Ignore la ponctuation et la casse pour chaque mot-clé — « Attends. » et « Oui ! » doivent fonctionner.
  • Une prose contenant un mot-clé reste de la prose : « nous devrions attendre et voir » n'est pas ATTENDS. Fais correspondre l'intégralité du message canonique, jamais une sous-chaîne.
  • STOP / HELP / START sont analysés avant tout état applicatif et avant tout appel de modèle, donc le désabonnement ne peut pas être cassé par un bogue ailleurs ou une panne d'API.
  • Si un modèle vérifie le contenu, échoue en mode fermé : si la vérification ne peut pas s'exécuter, n'envoie rien et dis-le.

Étape 5 — si un modèle réécrit le contenu utilisateur, exécute-le avant de lui faire confiance

Un garde qui supprime les noms de tiers des entrées utilisateur peut lire parfaitement et néanmoins :

  1. Inventer un fait — invité à remplacer « Jeanne Dupont » par « un identifiant naturel », il a écrit « la fille de l'appli » alors que rien ne mentionnait d'application ; les destinataires ont pris une fabrication pour un fait.
  2. Sur-corriger et supprimer des détails réels — « Jeanne du club de course » est devenu « elle ».

Règle : l'instruction doit dire ce que le modèle NE PEUT PAS inventer et ce qu'il NE PEUT PAS supprimer. La forme qui fonctionne : fonder la substitution sur la source, remplacer le jeton pas la phrase qui l'entoure, et préférer un repli neutre plutôt que de réutiliser un détail que la phrase énonce déjà.

Règle : épingle chaque défaut du modèle en direct comme un test optionnel, ignoré sans clé API, afin que les modifications du prompt ne puissent pas régresser silencieusement sans faire grimper les coûts à chaque exécution de test. Prévoyez 2 à 5 secondes par appel de garde.

Coûts (ordre de grandeur ; confirmer en direct)

Un +1 long code coûte un dollar ou deux par mois ; les SMS moins d'un cent par segment dans chaque sens ; les MMS quelques centimes. L'enregistrement Sole Proprietor coûte quelques dollars en une fois plus une petite redevance mensuelle de campagne. Telegram est gratuit.

Demander vs. décider

  • Demander : s'il faut soumettre un enregistrement honnête en sachant qu'il peut être refusé définitivement, ou commencer sur Telegram (argent et résultat irréversible) ; tout ce qui change ce qu'est le produit en substance.
  • Décider : architecture, ton du texte, machine à états, couverture de test, quel adaptateur en premier, formats de date, comportement des gardes.

Avant de signaler quoi que ce soit comme bloqué, énumère chaque identifiant candidat (une clé API épuisée sur le disque ne signifie pas qu'il n'y en a pas une autre qui fonctionne).

Voir aussi : build-remote-mcp-server (un autre modèle de « surface native »).

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

2016judea/ascii-charts

Build charts as plain Unicode-block text — bar, range, bullet, gap-bracket, star-histogram, heatmap, line, Venn, pie, donut and scatter — with a dependency-free Python script, for anywhere only monospace text survives (newsletter code blocks, Markdown, terminals, plain-text email, chat). Use when a chart has to embed as literal text instead of an image or a third-party chart service, or when you want a hand-made terminal look with no branding footer.

2016judea/buffett-checklist

Apply Warren Buffett's investment framework as a discipline lens when weighing a buy, hold, or sell decision — circle of competence, economic moat, owner earnings & intrinsic value, margin of safety, management/capital-allocation quality, and market psychology (Mr. Market, fear vs greed, temperament). Use when asked to "run this through Buffett", "what would Buffett say", "does this pass the moat test", "is this cheap enough", or for a second, more skeptical read on a name being evaluated or already held. This is a discipline overlay, not a replacement for a strategy — it applies the Buffett lens to how someone actually invests, rather than issuing generic advice.

2016judea/image-riff

Turn one or more reference images into original art in that reference's own visual language, then cut it to whatever surface it's for. Use when you paste or point at art and say "use this as the base image", "generate art from this", "riff on this", "some creative ideation with these images", "make me a channel banner / avatar / cover / plate", "wilder version of this", or want a spread of options off one piece of reference. This is the TASK skill; the engine is the `make-art` tool skill.

2016judea/leonardo

Draw the way Leonardo da Vinci drew — a study sheet, a notebook folio, a red-chalk or silverpoint study, a machine cutaway, a storm of vortices — in his real materials and page-logic, generated with the make-art engine and anchored on fifteen of his actual (public-domain) sheets. Use when you say "Leonardo", "da Vinci", "like his notebooks", "a codex page of X", "draw this as one of his study sheets", "sanguine", "silverpoint", or wants a design, diagram, or illustration in that hand. Also a reading guide to his notebooks (Richter's 1883 public-domain translation) for "what did Leonardo say about shadow / trees / water". This is a TASK skill; the engine is `make-art`.

2016judea/mcp-stack

Which free MCP server or framework to reach for, and its traps — finance/gov data (SEC EDGAR, Yahoo, SAM.gov, USAspending), web research (Exa, Firecrawl, Crawl4AI, Jina reader), design/art/brand (Canva, Inkscape, Penpot, Figma, Orshot, Hugging Face image gen, vectorizing, charts), data/spatial (DuckDB spatial, live ArcGIS layers, OpenStreetMap/Overpass, Census, MapLibre), and ops (PostHog, iMessage, context7 docs). Use when making a social post, OG card, poster, logo/vector, chart, map, or brand asset; when querying parquet/geojson/duckdb or a city's open-data layer; when an MCP "needs authentication" or fails; or when asked "what tools do we have", "is there an MCP for X", "should we add X".

2016judea/records-request

Get a specific record out of a US government office by public-records request — "request the assessor's model", "file a data practices request", "FOIA this", "open records request", "can we just ask the county for it", "who do I write to at <county>", "chase that request", "did they ever answer". Covers checking the website first, finding the right office and statute, the carve-out paragraph that makes a request answerable instead of refused, web-form traps (hidden character caps, WAFs that reject apostrophes), chasing (there is usually no deadline), whether what comes back may be republished, and parsing multi-year tables without silent errors.

2016judea/vertical-market-agent

Build a chat agent that knows one industry in one metro better than any general model because it carries a precomputed digest of real public records (or a mined review corpus) and can pull live records mid-conversation — finding the moat, building a byte-stable substrate, enumerating what the records can't, the data traps that produce plausible wrong numbers, deterministic math in tools, measured prompt cost and cache TTL, shipping as an ad destination, an off-sector ending, and a precomputed spatial "what is this next to" layer. Use when building a vertical AI agent grounded in records rather than general knowledge.

Skills associés