2016judea/sms-native-product

Crea un producto cuya interfaz sean mensajes de texto en lugar de una aplicación o sitio web, incluyendo la aprobación del canal, los límites técnicos y una arquitectura tolerante a fallos.

¿Qué es sms-native-product?

Este skill guía a un agente de IA en la construcción de un producto nativo de SMS (o Telegram) donde toda la interacción del usuario ocurre a través de mensajes de texto. Su principal utilidad es prevenir errores costosos al comenzar por la puerta de entrada regulatoria (registro A2P 10DLC en EE. UU., reglas SHAFT) y aprender los límites reales de cada canal (grupos MMS, Telegram bots, WhatsApp Cloud API). El agente aprende a diseñar una arquitectura limpia y testeable que separa las decisiones centrales del I/O, permitiendo que el mismo código funcione en simulación y producción. Además, enseña a manejar contenido reescrito por un modelo de lenguaje, a forzar la prueba de código antes de implementar, y a tomar decisiones de diseño basadas en hechos del canal, no en suposiciones. Compatible con Claude Code, Cursor y otros asistentes que lean SKILL.md.

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

Installed? Explore more Productividad y colaboración skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

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ódigoDisparador¿Reenviar?
30953lenguaje 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áficoNo
30898demasiadas marcas en un solo EIN, o un registro con apariencia duplicadaSí, 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 ahora como 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.js no 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 doesNotMatch que se dispara en un mensaje diferente y legítimo).
  • Nunca decidas ni imprimas desde una marca de tiempo almacenada. El almacén escribe created_at desde el reloj real, no el ahora inyectado 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. y Yes! 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í:

  1. 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.
  2. 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").

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 relacionados