2016judea/sms-native-product

Construa um produto cuja interface são mensagens de texto em vez de um aplicativo ou site — "sem app, sem site", "eles só enviam uma mensagem para um número", "converse com nosso agente nativamente por Mensagens de Texto", "podemos fazer isso por texto", "um bot SMS", "um bot Telegram", "torne isso um chat em grupo", "mínima fricção viável". Também atua quando já deu errado — "minha campanha foi rejeitada", "nosso número está bloqueado", "as mensagens não estão chegando", "por que preciso me registrar". Abrange o portão que decide se tal produto pode enviar mensagens (registro US A2P 10DLC, regras de conteúdo SHAFT, códigos de rejeição permanente), MMS em grupo a partir de código, o que cada canal não pode fazer, uma arquitetura que sobrevive à perda do canal e a proteção de conteúdo do usuário reescrito por modelo.

O que é sms-native-product?

Esta skill fornece um guia estruturado para construir produtos centrados em mensagens de texto (SMS, Telegram, WhatsApp, iMessage), priorizando a viabilidade regulatória e arquitetura robusta. O principal obstáculo identificado é que o canal de mensagens não é controlado pelo desenvolvedor; operadoras dos EUA possuem um processo rigoroso de aprovação (registro A2P 10DLC) que pode rejeitar permanentemente campanhas com base em conteúdo (SHAFT). A skill aborda detalhadamente como navegar por esses portões, interpretar códigos de erro (30953, 30885, 30898) e estruturar o produto desde o conceito. A arquitetura proposta separa rigidamente a lógica de negócio (machine.js) dos adaptadores de canal (Twilio, Telegram), permitindo simulação completa e troca de canais sem reescrita. Também aborda desafios práticos: limitações de cada plataforma (grupos MMS, agenda de contatos, bots Telegram), tratamento de atrasos e objetos de estado, e proteção contra alucinações de modelos de IA ao reescrever conteúdo do usuário. A skill enfatiza a descrição factual do serviço, registro separado para projetos paralelos, e decisões sobre arquitetura versus perguntas sobre o que o produto é.

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

Installed? Explore more Produtividade e Colaboração skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Produtos cuja interface são mensagens de texto

O apelo é real: as pessoas não gostam de instalar aplicativos ou visitar sites, mas todos podem enviar mensagens de texto. A pegadinha é que você não é dono do canal. As operadoras dos EUA são, e elas têm uma política de conteúdo e um processo de aprovação que pode te recusar permanentemente. Esse portão decide o que o produto pode ser, então ele vem primeiro.


Etapa 0 — o portão. Faça isso antes do design, não depois.

A partir de fevereiro de 2025, operadoras dos EUA bloqueiam tráfego A2P não registrado por completo, então uma marca e uma campanha devem ser aprovadas antes que uma única mensagem seja enviada. Releia a documentação de erros ativa a cada vez; a política da operadora muda.

CódigoGatilhoReenviar?
30953linguagem explícita/sugestiva, ou um site vinculado hospedando "conteúdo pornográfico, de acompanhantes, namoro ou entretenimento adulto"Não
30885"alto risco" — marketing enganoso, ou um registro que deturpa o tráfegoNão
30898muitas marcas em um único EIN, ou um registro com aparência duplicativaSim, com justificativa

Regra: nomeie a categoria de conteúdo do produto em voz alta na primeira resposta e diga se ela está nessa lista. Se a categoria (ex.: namoro) for literalmente uma palavra-chave em uma regra de rejeição, descobrir isso no minuto cinco muda a arquitetura, o texto da página de destino e o plano de fallback. SHAFT é a abreviação: Sexo, Ódio, Álcool, Armas de fogo, Tabaco — além de Cannabis, e namoro anda junto.

Regra: registre um projeto paralelo como uma marca de Empresário Individual (Sole Proprietor), não sob o EIN de uma empresa existente. Padrões de risco seguem o TIN (30898), então uma recusa em um projeto paralelo não deve afetar a capacidade de envio do seu negócio principal. Empresário Individual é voltado para pessoas físicas sem TIN; a taxa de transferência é baixa, e baixa é suficiente para um beta.

Regra: nunca crie uma página de destino falsa para obter aprovação de campanha. Uma página que esconde o que o tráfego realmente é é o padrão 30885, e converte um risco de um número em um risco de todos os números que você já registrou. Indique as probabilidades claramente e deixe o proprietário decidir.

Descreva o serviço pelo que ele faz mecanicamente, e somente se isso for verdade (ex.: journaling e responsabilidade em pequenos grupos, quando é isso que as mensagens são). Se nenhuma descrição verdadeira ultrapassar o portão, a resposta é um canal diferente, não um eufemismo melhor.

A revisão recompensa fatos que você pode apontar: aceitação apenas inbound, volume conversacional, sem links em mensagens recorrentes, STOP tratado antes de tudo, conteúdo explícito recusado na porta.

Etapa 0.5 — leia o briefing por NÚMEROS e OBJETOS, não por intenção

Mantenha o briefing do fundador literalmente como README.md e diga em CLAUDE.md que ele tem precedência sobre todo documento de engenharia.

Regra: antes de escrever uma máquina de estados, liste cada duração no briefing e cada substantivo sobre o qual ela atua. Se existirem duas durações, elas são duas funcionalidades. Um briefing com um atraso de uma semana nas respostas dos amigos chegando ao autor e um bloqueio de duas semanas na atualização do próprio autor é fácil de colapsar em uma retenção de sete dias em a entrada — o único objeto sobre o qual nenhum atraso era — e todo erro downstream segue dessa fusão.

Regra: nomeie o objeto de cada atraso — "retido DE quem". Retido dos amigos e retido do autor são produtos opostos.

Regra: quando o design literal do briefing não puder ser aplicado no canal, diga isso e dê as alternativas — não escolha silenciosamente o que é aplicável. (O criador de um chat em grupo é um membro dele, então nenhum código pode reter as respostas do grupo dele.) Isso é uma decisão de premissa, e decisões de premissa são do proprietário.

Uma leitura incorreta coerente não parece ser uma. Mantenha um parágrafo de design substituído riscado no lugar em vez de deletá-lo; ele mostra a uma sessão posterior como o briefing foi mal interpretado.

Etapa 1 — o que o canal pode e não pode fazer

  • Mensagens em grupo a partir de código funcionam. Twilio Conversations faz MMS em grupo apenas em códigos longos +1 — não gratuitos, não códigos curtos — com limite de 10 participantes incluindo seu próprio número. Não afirme o contrário de memória.
  • Participantes de SMS de MMS em grupo carregam um Address e nenhum ProxyAddress, então um número atende a todas as salas — mas a regra de unicidade de participante/proxy (50425) não tem comportamento documentado para participantes sem proxy. Nunca projete várias salas concorrentes que compartilham um número e um conjunto de participantes. Uma sala durável por pessoa tem um conjunto de participantes estável.
  • Uma página web não pode ler a agenda de contatos de um iPhone. A Contact Picker API é apenas Chrome-no-Android. "Sincronizar seus contatos" está morto na chegada; substitua por uma linha que o usuário encaminha — o texto de entrada do destinatário é o registro de consentimento que as operadoras querem de qualquer forma.
  • Um bot do Telegram não pode criar um grupo nem adicionar ninguém a um, e com o modo de privacidade ativo, ele só ouve comandos endereçados a ele. Ambos ajudam: o criador adiciona o bot ao chat que já possui, e conversas gerais não podem ser confundidas com entrada. Criar um bot precisa de um humano no @BotFather (sem API); peça o token.
  • A WhatsApp Cloud API não tem mensagens em grupo.
  • APIs do iMessage (Sendblue, LoopMessage) fazem bolhas azuis e chats em grupo reais, mas custam cerca de US$ 100/linha/mês mais taxas de configuração.

Etapa 2 — arquitetura que sobrevive à perda do canal

Porque o canal pode ser recusado, o transporte deve ser um arquivo:

machine.js   puro: (contexto, evento) -> {respostas, efeitos}    sem E/S, sem relógio
engine.js    montagem de contexto -> máquina -> efeitos           o caminho inteiro
effects.js   createEffects({db, canal})                           executa decisões
twilio.js  / telegram.js                                          intercambiável
api/*.js     adaptadores finos sobre engine.js                    ~10 linhas cada
sim/         banco em memória + canal de console
  • O núcleo de decisão recebe now como argumento e não toca na rede. Todo bug nessa classe de produto é um bug de sequenciamento (um lembrete que dispara duas vezes, uma mensagem para uma sala vazia, um item retido que nunca chega), e nenhum é testável contra uma rede ativa e um timer de sete dias.
  • Adaptadores são argumentos, nunca imports, na camada de efeitos — a mesma refatoração que o simulador e o canal de fallback precisam.
  • Sem lógica dentro de um manipulador HTTP. Integração específica de canal escrita dentro de api/telegram.js é intestável; extraia-a.

Etapa 3 — dirija-o, não apenas teste-o

node sim/drive.js          roteirizado: o loop completo, uma semana pulada, as proteções
node sim/drive.js --repl   digite como qualquer número; /as <n>  /jump <dias>  /state
  • O simulador deve executar o caminho de produção, não uma cópia paralela.
  • Espere que uma primeira direção revele vários defeitos reais que testes unitários não conseguem alcançar: uma sala que se cumprimenta antes de alguém estar nela, um dia da semana simples para uma data a uma semana, um lembrete que não diz qual item significa, uma sala cujos membros todos saíram.
  • Quando um teste falha, verifique o teste primeiro (uma regex de data que não permite a vírgula em Sun, Aug 30; um doesNotMatch que dispara em uma mensagem diferente e legítima).
  • Nunca decida ou imprima a partir de um timestamp carimbado pelo armazenamento. O armazenamento escreve created_at do relógio real, não do now injetado do mecanismo, então sob um relógio pulado ele mente (e imprime datas no passado). Decida apenas a partir de colunas que a máquina escreveu, e pendure datas relacionadas a uma âncora armazenada.

Etapa 4 — texto para uma tela de bloqueio

Um arquivo contém toda string de saída.

  • Sem emoji, sem pontos de exclamação, sem marketing.
  • Nunca um dia da semana simples para uma data com mais de um ou dois dias de distância. Sun Aug 30.
  • Perdoe pontuação e maiúsculas/minúsculas em toda palavra-chave — Wait. e Yes! devem funcionar.
  • Prosa contendo uma palavra-chave ainda é prosa: "we should wait and see" não é WAIT. Corresponda a mensagem inteira canonizada, nunca uma substring.
  • STOP / HELP / START são analisados antes de todo estado da aplicação e antes de qualquer chamada de modelo, então a desistência não pode ser quebrada por um bug em outro lugar ou uma falha de API.
  • Se um modelo protege conteúdo, falhe fechado: se a verificação não puder executar, não envie nada e diga isso.

Etapa 5 — se um modelo reescrever conteúdo do usuário, execute-o antes de confiar nele

Uma proteção que remove nomes de terceiros de entradas de usuário pode ler perfeitamente e ainda:

  1. Inventar um fato — ao pedir para substituir "Jane Doe" por "um identificador natural", escreveu "a garota do app" quando nada mencionou um app; os destinatários leram uma fabricação como fato.
  2. Corrigir demais e deletar detalhe real — "Jane do clube de corrida" se tornou "ela".

Regra: a instrução deve dizer o que o modelo NÃO PODE inventar e o que ele NÃO PODE deletar. A forma funcional: baseie a substituição na fonte, substitua o token não a frase ao redor dele, e prefira um fallback neutro a reutilizar um detalhe que a frase já afirma.

Regra: fixe cada defeito do modelo ativo como um teste opt-in, ignorado sem uma chave de API, para que edições de prompt não possam regredir silenciosamente sem aumentar os custos a cada execução de teste. Reserve 2 a 5 segundos por chamada de proteção.

Custos (ordem de grandeza; confirme ativo)

Um código longo +1 custa um ou dois dólares por mês; SMS, menos de um centavo por segmento em cada direção; MMS, alguns centavos. O registro de Empresário Individual custa alguns dólares uma vez mais uma pequena taxa mensal de campanha. O Telegram é gratuito.

Perguntar vs. Decidir

  • Perguntar: se deve submeter um registro honesto sabendo que pode ser recusado permanentemente, ou começar no Telegram (dinheiro e um resultado irreversível); qualquer coisa que mude o que o produto é.
  • Decidir: arquitetura, voz do texto, a máquina de estados, cobertura de teste, qual adaptador primeiro, formatos de data, comportamento da proteção.

Antes de relatar algo como bloqueado, enumere cada credencial candidata (uma chave de API esgotada no disco não significa que não há outra que funcione).

Veja também: build-remote-mcp-server (outro padrão de "superfície 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.

Habilidades Relacionadas