A IA escolhe a história. Quem escreve sou eu.
Eu não deixo a IA escrever meus posts. Deixo ela fazer a parte em que sou lento: ler uma semana bagunçada de commits e apontar a única coisa que vale a pena dizer. Depois eu escrevo, e eu publico.
Um agente agendado me avisou que esta página valia a pena. Ele leu os últimos quatro dias do meu histórico de git, achou a única ideia que valia a pena explicar e me entregou um primeiro rascunho cru. O que você está lendo fui eu que escrevi e editei, e então apertei publicar. O agente nunca chega a apertar esse botão. Essa separação é o sentido de todo o sistema, e é a parte que quase todo mundo pula.
Toco vários projetos que querem se comunicar: um diretório, uma plataforma de arte, este site, trabalho de clientes. Cada um produz material real toda semana, e eu não consigo sentar e garimpar tudo atrás do que vale a pena dizer. Então passei a metade chata para um agente: leia tudo, me diga o melhor ângulo, esboce. A escrita continua minha. A publicação continua minha. O trabalho do agente termina na minha fila de revisão.
É assim que as peças se encaixam.
O formato
Três partes:
- Um agente agendado que varre o trabalho real e levanta o melhor ângulo como rascunho cru.
- Um único endpoint de ingestão que aceita esses rascunhos de qualquer projeto.
- Um hub de revisão onde eu leio, reescrevo e publico num lugar só.
O agente nunca toca numa API social nem no meu site. Ele só sabe fazer POST para o meu próprio hub. Tudo o que ele envia chega como status = 'pending': material cru me esperando, nunca um post no ar.
Passo 1: o agente cura a partir dos commits reais
O agente roda git log --since="4 days ago" nos meus repos, agrupa os commits e escolhe a coisa mais ensinável. Essa é a parte em que sou ruim: perceber, numa semana espalhada, qual coisa realmente rende um post. Ele me entrega isso como um rascunho ao qual posso reagir, não como um artigo pronto. Um ponto de partida.
// scripts/ingest-draft.mjs — one POST per channel, same group
const channels = ["article", "facebook", "instagram"];
for (const ch of channels) {
const part = bundle[ch];
if (!part) continue;
const payload = { ...part, project, channel: ch, group };
const { ok, json } = await ingestOne(payload);
// ...
}
O id de group mantém uma peça de trabalho unida. O artigo e seus posts sociais carregam a mesma string, então o hub os mostra como um cartão só com uma ação só, em vez de rascunhos soltos que eu teria que remontar no olho.
Passo 2: o endpoint de ingestão confia num token, não em mim
Essa é a linha que importa. A rota de ingestão é autenticada por um token bearer compartilhado, e é de propósito isenta do login do navegador:
// app/api/ingest/route.js
const auth = (request.headers.get("authorization") || "")
.replace(/^Bearer\s+/i, "").trim();
if (auth !== process.env.INGEST_TOKEN)
return Response.json({ error: "Unauthorized" }, { status: 401 });
Uma máquina com o token pode adicionar à minha fila. É só isso que ela pode fazer. O endpoint faz upsert em (project, slug), então rodar de novo atualiza um rascunho pendente no lugar em vez de acumular duplicatas. Rascunhos já publicados nunca são tocados.
Passo 3: publicar confia no meu cookie, não no token
A rota de publicação é a outra metade. Ela fica atrás do cookie de sessão que só o meu login define:
// app/api/publish/route.js
// Publish/send a pending draft to its channel. Gated by the session
// cookie (middleware). Per channel: instagram, facebook, threads,
// x, email, article...
Então o limite não é uma convenção nem uma flag que eu prometo respeitar. São duas fronteiras de autenticação diferentes. O token pode encher a minha fila e nada mais. O meu login é a única coisa que pode pôr palavras na frente das pessoas, e só depois que eu as escrevi e revisei. Um agente confuso, ou um token vazado, no pior caso bagunça a minha fila. Nenhum dos dois publica uma frase.
O que publicar faz de verdade
Para os canais sociais, publicar chama a API da plataforma. Para o canal de artigos, “publicar” é algo de que eu gosto mais: faz commit de um arquivo markdown no repo deste site pela GitHub Contents API, e o pipeline de deploy que eu já tinha faz o resto.
// lib/github.js
// "Publish" = the .md file lands on main -> Vercel rebuilds
// edragrey.com -> the article is live. Path matches the Astro
// collection: src/content/articles/<lang>/<slug>.md
Sem CMS à parte, sem uma segunda fonte de verdade. Um rascunho que terminei vira um commit, o commit vira um deploy, o deploy vira uma página no ar.
O caminho que não segui
Meu primeiro instinto foi rotear tudo pelo Buffer e deixar o agente agendar os posts direto. Larguei. Isso é um agente que escreve e publica sozinho, exatamente o que eu não queria. Colocar a fila num hub que eu controlo fez o alcance do agente terminar no meu banco de dados, e as palavras continuam minhas.
O que usei
- Uma tarefa agendada do Claude Code que lê o
git loge levanta o ângulo. - Um hub em Next.js sobre Neon Postgres com duas rotas:
/api/ingest(token bearer) e/api/publish(cookie de sessão). - A GitHub Contents API para o canal de artigos, então publicar é só um commit.
Para levar
A ideia tentadora é que a IA pode escrever seus posts. Pode, o resultado é ok, e é aí que mora a armadilha. A divisão melhor é deixar a IA fazer o perceber (ler tudo e levantar o ângulo) e ficar com a escrita e a publicação para você. As palavras que as pessoas leem deveriam ser suas. Esta página começou com um agente apontando para quatro dias de commits e dizendo “essa”. O resto sou eu.
Deixe seu e-mail e eu te aviso quando o próximo sair, com as ferramentas e fluxos que eu de fato uso. Sem spam.
Mais tutoriais ↗