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.
| Code | Déclencheur | Nouvelle soumission ? |
|---|---|---|
| 30953 | langage 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 trafic | Non |
| 30898 | trop de marques sur un seul EIN, ou un enregistrement à l'apparence duplicative | Oui, 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
nowcomme 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.jsest 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; undoesNotMatchqui 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 dunowinjecté 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 :
- 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.
- 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 »).