Productos cuya interfaz son mensajes de texto
El atractivo es real: a la gente no le gusta instalar aplicaciones ni visitar sitios web, pero todo el mundo puede enviar mensajes de texto. El problema es que no eres dueño del canal. Lo son las operadoras estadounidenses, y tienen una política de contenido y un proceso de aprobación que puede rechazarte permanentemente. Esa puerta decide lo que el producto puede ser, así que va primero.
Paso 0 — la puerta. Haz esto antes del diseño, no después.
Desde febrero de 2025, las operadoras de EE. UU. bloquean directamente el tráfico A2P no registrado, por lo que una marca y una campaña deben ser aprobadas antes de que se envíe un solo mensaje. Relee la documentación de errores en vivo cada vez; las políticas de las operadoras cambian.
| Código | Disparador | ¿Reenviar? |
|---|---|---|
| 30953 | lenguaje explícito/sugerente, o un sitio enlazado que albergue "contenido pornográfico, de escort, citas o entretenimiento para adultos" | No |
| 30885 | "alto riesgo" — marketing engañoso, o un registro que tergiversa el tráfico | No |
| 30898 | demasiadas marcas en un solo EIN, o un registro con apariencia duplicada | Sí, con causa |
Regla: nombra la categoría de contenido del producto en voz alta en la primera respuesta, y di si está en esa lista. Si la categoría (p. ej., citas) es literalmente una palabra clave en una regla de rechazo, encontrarlo en el minuto cinco cambia la arquitectura, el texto de la página de destino y el plan de respaldo. SHAFT es el acrónimo: Sexo, Odio, Alcohol, Armas de fuego, Tabaco — más Cannabis, y las citas van al lado.
Regla: registra un proyecto secundario como marca de Propietario Único, no bajo el EIN de una empresa existente. Los patrones de riesgo siguen al ID fiscal (30898), por lo que un rechazo en un proyecto secundario no debe afectar la capacidad de envío de tu negocio principal. Propietario Único está limitado a personas sin ID fiscal; el rendimiento es bajo, y bajo es suficiente para una beta.
Regla: nunca construyas una página de destino falsa para obtener la aprobación de una campaña. Una página que oculta lo que realmente es el tráfico es el patrón 30885, y convierte un riesgo de un número en un riesgo de todos los números que registres. Expone las probabilidades claramente y deja que el dueño decida.
Describe el servicio por lo que hace mecánicamente, y solo si eso es cierto (p. ej., llevar un diario y responsabilidad en grupos pequeños, cuando eso es lo que son los mensajes). Si ninguna descripción verdadera supera la puerta, la respuesta es un canal diferente, no un eufemismo mejor.
La revisión recompensa los hechos que se pueden señalar: solo entrada por aceptación, volumen conversacional, sin enlaces en mensajes recurrentes, STOP manejado antes que todo, contenido explícito rechazado en la puerta.
Paso 0.5 — lee el resumen en busca de NÚMEROS y OBJETOS, no de intención
Mantén el resumen del fundador palabra por palabra como README.md y di en CLAUDE.md que tiene prioridad sobre cualquier documento de ingeniería.
Regla: antes de escribir una máquina de estados, enumera cada duración en el resumen y cada sustantivo sobre el que actúa. Si existen dos duraciones, son dos funcionalidades. Un resumen con un retraso de una semana en las respuestas de los amigos que llegan al autor y un bloqueo de dos semanas en la actualización del propio autor es fácil de colapsar en una sola retención de siete días en la entrada — el único objeto del que no trataba ninguno de los retrasos — y cada error posterior se deriva de esa fusión.
Regla: nombra el objeto de cada retraso — "retenido DE quién". Retenido de los amigos y retenido del autor son productos opuestos.
Regla: cuando el diseño literal del resumen no pueda aplicarse en el canal, dilo y da las alternativas — no elijas silenciosamente el que se puede aplicar. (El creador de un chat grupal es miembro de él, por lo que ningún código puede retener las respuestas del grupo de él.) Esa es una decisión de premisa, y las decisiones de premisa son del dueño.
Una lectura errónea coherente no se siente como tal. Mantén un párrafo de diseño reemplazado tachado en su lugar en lugar de eliminarlo; le muestra a una sesión posterior cómo se malinterpretó el resumen.
Paso 1 — lo que el canal puede y no puede hacer
- El envío de mensajes de texto grupales desde código funciona. Twilio Conversations admite MMS grupales solo en códigos largos +1 — no gratuitos, no códigos cortos — con un límite de 10 participantes, incluido tu propio número. No afirmes lo contrario de memoria.
- Los participantes de SMS en grupo-MMS llevan una Dirección y sin ProxyAddress, por lo que un número sirve para todas las salas — pero la regla de unicidad de participante/proxy (50425) no tiene un comportamiento documentado para participantes sin proxy. Nunca diseñes muchas salas concurrentes que compartan un número y un conjunto de participantes. Una sala duradera por persona tiene un conjunto de participantes estable.
- Una página web no puede leer la libreta de direcciones de un iPhone. La API Contact Picker es solo de Chrome en Android. "Sincroniza tus contactos" está muerto a la llegada; reemplázalo con una línea que el usuario reenvíe — el mensaje de texto entrante del destinatario es el registro de consentimiento que las operadoras quieren de todas formas.
- Un bot de Telegram no puede crear un grupo ni agregar a nadie a uno, y con el modo de privacidad activado solo escucha comandos dirigidos a él. Ambos ayudan: el creador agrega el bot al chat que ya tiene, y la charla general no puede confundirse con entrada. Crear un bot necesita un humano en @BotFather (sin API); pide el token.
- WhatsApp Cloud API no tiene mensajería grupal.
- Las API de iMessage (Sendblue, LoopMessage) hacen burbujas azules y chats grupales reales, pero cuestan alrededor de $100/línea/mes más tarifas de configuración.
Paso 2 — arquitectura que sobrevive a la pérdida del canal
Debido a que el canal puede ser rechazado, el transporte debe ser un archivo:
machine.js puro: (contexto, evento) -> {respuestas, efectos} sin E/S, sin reloj
engine.js ensamblaje de contexto -> máquina -> efectos todo el camino
effects.js createEffects({db, canal}) ejecuta decisiones
twilio.js / telegram.js intercambiables
api/*.js adaptadores delgados sobre engine.js ~10 líneas cada uno
sim/ db en memoria + canal de consola
- El núcleo de decisiones toma
ahoracomo argumento y no toca la red. Cada error en esta clase de producto es un error de secuenciación (un recordatorio que se dispara dos veces, un mensaje a una sala vacía, un elemento retenido que nunca llega), y ninguno es comprobable contra una red en vivo y un temporizador de siete días. - Los adaptadores son argumentos, nunca importaciones, en la capa de efectos — la misma refactorización que necesitan el simulador y el canal de respaldo.
- Sin lógica dentro de un controlador HTTP. La incorporación específica del canal escrita dentro de
api/telegram.jsno es comprobable; extráela.
Paso 3 — condúcelo, no solo lo pruebes
node sim/drive.js con script: el ciclo completo, una semana saltada, las compuertas
node sim/drive.js --repl escribe como cualquier número; /as <n> /jump <días> /state
- El simulador debe ejecutar la ruta de producción, no una copia paralela.
- Espera que el primer recorrido saque a la luz varios defectos reales a los que las pruebas unitarias no pueden llegar: una sala que se saluda a sí misma antes de que haya alguien, un día de la semana desnudo para una fecha dentro de una semana, un recordatorio que no dice a qué elemento se refiere, una sala cuyos miembros se fueron todos.
- Cuando una prueba se ponga roja, revisa la prueba primero (una expresión regular de fecha que no permite la coma en "Sun, Aug 30"; un
doesNotMatchque se dispara en un mensaje diferente y legítimo). - Nunca decidas ni imprimas desde una marca de tiempo almacenada. El almacén escribe
created_atdesde el reloj real, no elahorainyectado del motor, por lo que bajo un reloj saltado miente (e imprime fechas en el pasado). Decide solo a partir de columnas que la máquina escribió, y cuelga las fechas relacionadas de un ancla almacenada.
Paso 4 — texto para una pantalla de bloqueo
Un archivo contiene cada cadena de salida.
- Sin emojis, sin signos de exclamación, sin marketing.
- Nunca un día de la semana desnudo para una fecha con más de un día o dos de distancia. "Sun Aug 30".
- Perdona la puntuación y las mayúsculas/minúsculas en cada palabra clave —
Wait.yYes!deben funcionar. - La prosa que contiene una palabra clave sigue siendo prosa: "we should wait and see" no es WAIT. Iguala el mensaje completo canonizado, nunca una subcadena.
- STOP / HELP / START se analizan antes de todo el estado de la aplicación y antes de cualquier llamada al modelo, para que la exclusión voluntaria no pueda ser interrumpida por un error en otro lugar o una interrupción de la API.
- Si un modelo protege el contenido, falla cerrado: si la verificación no puede ejecutarse, no envíes nada y dilo.
Paso 5 — si un modelo reescribe el contenido del usuario, ejecútalo antes de confiar en él
Un guardián que elimina nombres de terceros de las entradas del usuario puede leer perfectamente y aún así:
- Inventar un hecho — al pedirle que reemplace "Jane Doe" con "un identificador natural", escribió "la chica de la aplicación" cuando nada mencionaba una aplicación; los destinatarios interpretaron una invención como un hecho.
- Sobre-corregir y eliminar detalles reales — "Jane del club de running" se convirtió en "ella".
Regla: la instrucción debe decir qué NO puede inventar el modelo y qué NO puede eliminar. La forma funcional: fundamenta la sustitución en la fuente, reemplaza el token no la frase que lo rodea, y prefiere un respaldo neutral sobre reutilizar un detalle que la oración ya establece.
Regla: fija cada defecto del modelo en vivo como una prueba opcional, que se omite sin una clave de API, para que las ediciones de prompt no puedan regresionarlos silenciosamente sin aumentar los costos en cada ejecución de prueba. Presupuesta de 2 a 5 segundos por llamada del guardián.
Costos (orden de magnitud; confirma en vivo)
Un código largo +1 cuesta uno o dos dólares al mes; SMS menos de un centavo por segmento en cada dirección; MMS unos pocos centavos. El registro de Propietario Único cuesta unos pocos dólares una sola vez más una pequeña tarifa mensual de campaña. Telegram es gratuito.
Preguntar vs. decidir
- Preguntar: si presentar un registro honesto sabiendo que puede ser rechazado permanentemente, o comenzar en Telegram (dinero y un resultado irreversible); cualquier cosa que cambie lo que el producto es.
- Decidir: arquitectura, voz del texto, la máquina de estados, cobertura de pruebas, qué adaptador primero, formatos de fecha, comportamiento del guardián.
Antes de informar algo como bloqueado, enumera cada credencial candidata (una clave de API agotada en disco no significa que no haya otra que funcione).
Ver también: build-remote-mcp-server (otro patrón de "superficie nativa").