← Tutoriales
BUILD · PIPELINE

La IA elige la historia. La escribo yo.

No dejo que la IA escriba mis posts. Dejo que haga la parte en la que soy lento: leer una semana desordenada de commits y sacar la única cosa que vale la pena contar. Luego la escribo yo, y la publico yo.

Para
Builders que usan IA para contenido y quieren seguir siendo el autor, no entregarle el teclado
Necesitas
Una cola que controlas, un token bearer y un sitio donde publicar
Tiempo
Una tarde

Un agente programado me avisó de que esta página valía la pena. Leyó los últimos cuatro días de mi historial de git, encontró la única idea que valía la pena explicar y me pasó un primer borrador en bruto. Lo que estás leyendo lo escribí y lo edité yo, y luego pulsé publicar. El agente nunca llega a pulsar ese botón. Esa separación es el sentido de todo el sistema, y es la parte que casi todos se saltan.

Llevo varios proyectos que quieren comunicar: un directorio, una plataforma de arte, este sitio, trabajo de clientes. Cada uno produce material real cada semana, y no puedo sentarme a revisarlo todo buscando qué merece decirse. Así que le pasé la mitad aburrida a un agente: lee todo, dime el mejor ángulo, esbózalo. La escritura sigue siendo mía. La publicación sigue siendo mía. El trabajo del agente termina en mi cola de revisión.

Así encajan las piezas.

La forma

Tres partes:

  1. Un agente programado que revisa el trabajo real y saca el mejor ángulo como borrador en bruto.
  2. Un único endpoint de ingesta que acepta esos borradores desde cualquier proyecto.
  3. Un hub de revisión donde leo, reescribo y publico en un solo lugar.

El agente nunca toca una API social ni mi sitio. Solo sabe hacer POST a mi propio hub. Todo lo que envía llega como status = 'pending': material en bruto que me espera, nunca un post en vivo.

Paso 1: el agente cura desde los commits reales

El agente ejecuta git log --since="4 days ago" en mis repos, agrupa los commits y elige lo más enseñable. Esta es la parte en la que soy malo: notar, en una semana dispersa, qué cosa vale de verdad un post. Me lo entrega como un borrador al que puedo reaccionar, no como un artículo terminado. Un punto 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);
  // ...
}

El id de group mantiene unida una sola pieza de trabajo. El artículo y sus posts sociales llevan la misma cadena, así que el hub los muestra como una sola tarjeta con una sola acción, en vez de borradores sueltos que tendría que recomponer a ojo.

Paso 2: el endpoint de ingesta confía en un token, no en mí

Esta es la línea que importa. La ruta de ingesta se autentica con un token bearer compartido, y está deliberadamente exenta del login del 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 });

Una máquina con el token puede añadir a mi cola. Eso es todo lo que puede hacer. El endpoint hace upsert sobre (project, slug), así que volver a ejecutarlo actualiza un borrador pendiente en su sitio en vez de acumular duplicados. Los borradores ya publicados no se tocan.

La ruta de publicación es la otra mitad. Vive detrás de la cookie de sesión que solo pone mi login:

// 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...

Así que el límite no es una convención ni una bandera que prometo respetar. Son dos fronteras de autenticación distintas. El token puede llenar mi cola y nada más. Mi login es lo único que puede poner palabras delante de la gente, y solo después de que yo las haya escrito y revisado. Un agente confundido, o un token filtrado, como mucho me ensucia la cola. Ninguno puede publicar una frase.

Qué hace publicar en realidad

Para los canales sociales, publicar llama a la API de la plataforma. Para el canal de artículos, “publicar” es algo que me gusta más: hace commit de un archivo markdown al repo de este sitio a través de la GitHub Contents API, y el pipeline de despliegue que ya tenía hace el 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

Sin CMS aparte, sin una segunda fuente de verdad. Un borrador que terminé se vuelve un commit, el commit se vuelve un deploy, el deploy se vuelve una página en vivo.

El camino que no tomé

Mi primer instinto fue enrutar todo a través de Buffer y dejar que el agente programara los posts directamente. Lo descarté. Eso es un agente que escribe y publica por su cuenta, justo lo que no quería. Meter la cola en un hub que controlo significó que el alcance del agente termina en mi base de datos, y las palabras siguen siendo mías.

Qué usé

Para llevar

La idea tentadora es que la IA puede escribir tus posts. Puede, el resultado es decente, y ahí está la trampa. La mejor división es dejar que la IA haga el notar (leer todo y sacar el ángulo) y quedarte la escritura y la publicación. Las palabras que la gente lee deberían ser tuyas. Esta página empezó con un agente señalando cuatro días de commits y diciendo “esa”. El resto soy yo.

¿TE SIRVIÓ? RECIBE EL PRÓXIMO

Déjame tu correo y te aviso cuando publique el próximo, con las herramientas y flujos que de verdad uso. Sin spam.

Más tutoriales ↗