Tag: AI

  • Claude diseñó proteínas solo: manual de agentes de IA autónomos

    Claude diseñó proteínas solo: manual de agentes de IA autónomos

    Casi todo lo que leo sobre IA cabe en tres cajones: autocompletar código, sacar un gráfico de un Excel y vídeos de gente que no existe bailando en una playa.

    Ese es el techo mental de la conversación. El mío también, muchos días.

    Y mientras discutimos si Cursor gestiona el contexto mejor que Claude Code, los mismos agentes de IA autónomos que tú y yo soltamos dentro de un repo llevaban 48 horas seguidas diseñando proteínas que no existían. Proteínas que después alguien sintetizó de verdad, en un laboratorio de verdad, y midió con un aparato de verdad.

    Ahí el error no se arregla con git revert.

    El 18 de agosto de 2026 Anthropic publicó How Claude is accelerating protein design and analytical chemistry y, debajo, un informe técnico con el detalle fino: 1.320 diseños generados, 354 binders confirmados en laboratorio, 14 de 15 dianas con al menos un acierto.

    Ese titular corrió por todas partes. Y es el trozo menos interesante de la historia.

    Porque lo que a ti y a mí nos sirve el lunes por la mañana no son los 354 binders. Es cómo estaba escrito el documento que le dieron al agente antes de arrancar.


    Primero, qué hizo exactamente

    Un binder es una proteína pequeña que se pega a una diana concreta. Es el paso cero de medio catálogo de fármacos. No es un fármaco: por delante queda todo el recorrido preclínico y regulatorio, que se mide en años.

    Claude no inventó ninguna herramienta. Usó las que ya existen y son públicas: diez generadores de estructura distintos, con PXDesign (358 diseños), RFdiffusion3 (267) y Genie 3 (185) a la cabeza; SolubleMPNN para el diseño de secuencia (1.133 de los diseños testeados) y un ensemble de ESMFold2, ESMFold2-Fast y Protenix v2 para rankear. Ninguna venía preinstalada: el protocolo le obliga a compilar cada una desde su repositorio público y validarla en la primera hora. Todo dentro de Claude Science, el entorno de investigación de Anthropic.

    Lee esa lista otra vez. Ninguna herramienta es suya.

    El modelo no aportó capacidad generativa nueva al campo. Aportó criterio: qué herramienta usar, en qué orden y qué candidatos tirar a la basura. Es la diferencia entre IA generativa e IA agéntica llevada a un dominio donde el resultado se mide con un sensor.

    Y se nota en el ranking: su diseño número uno acertó el 49 % de las veces, el top cinco un 44 %, el top diez un 39 %, frente al 28 % del conjunto de treinta. El criterio estaba en el orden.

    Y se midió fuera de casa. Adaptyv Bio convirtió las secuencias en ADN, sintetizó las proteínas con síntesis libre de células y robots, y midió afinidad por resonancia de plasmón superficial. Twist Bioscience también participó. Esto no es una simulación puntuándose a sí misma.

    Los números por brazo del experimento, que mucha gente ha contado mal mezclándolos:

    Configuración Binders / diseños Tasa de acierto
    Baseline de la industria hoy 10–15 %
    Opus 4.8 · 14 dianas a la vez, una sola sesión · 48 h 88 / 390 22,6 %
    Mythos Preview · 14 dianas a la vez, una sola sesión · 48 h 104 / 390 26,7 %
    Mythos Preview · una sesión de 24 h por diana 158 / 450 35,1 %

    Del formato multi-diana se analizan 13 de las 14 dianas; la campaña de diana única cubrió las 15.

    El 26,8 % global sale de dividir 354 entre 1.320. El 95 % de los diseños se expresó correctamente. Y hubo dos casos que se salen de la media:

    • RBX1: 28 binders de 90 diseños sumando las tres campañas, un 31 %. Y un 40 % en la campaña de diana única, la mejor configuración. En la competición abierta previa sobre esta misma diana solo pegaron 9 de 245 diseños: un 3,7 %. El mejor diseño del agente se midió en 3,9 nM, por delante del que ganó aquella competición.
    • TREM2: 72 binders de 90 diseños. Un 80 %, frente al 38,3 % de la competición previa de Adaptyv.

    Con un asterisco que pone el propio informe: cuatro de las seis competiciones con las que se compara ya estaban publicadas y accesibles para el agente mientras diseñaba.

    Impresionante igual. Ahora la parte que de verdad importa.


    Dos tercios del prompt no eran de biología

    Antes de arrancar, un grupo de expertos escribió un protocolo. Unos 30.000 tokens. Y después —cita textual del informe— "no dimos ninguna guía científica, técnica ni operativa adicional después de iniciar las campañas".

    Ni una corrección. Ni un "prueba mejor por aquí". Los únicos mensajes humanos que entraron fueron instrucciones cortas y no técnicas para reanudar cuando una sesión se caía por infraestructura. El resto de incidencias las detectó y las sorteó el agente solo.

    Lo interesante es cómo se repartía ese documento:

    PROTOCOLO ENTREGADO AL AGENTE - ~16.000 palabras (~30.000 tokens)
    
      Ciencia y herramientas      ################   34,2 %
      Orquestacion y validacion   ################   34,7 %
      Operaciones                 ##############     31,1 %
                                                     -------
      Todo lo que NO es dominio                      65,8 %
    

    Un 34,2 % de ciencia. Y un 65,8 % de cosas que no tienen nada que ver con proteínas: cómo trabajar, cómo decidir, cómo validar, cuándo parar, qué hacer cuando algo se rompe.

    Piensa ahora en tu último system prompt.

    Si el 90 % es "eres un ingeniero senior experto en X con 20 años de experiencia", ya sabes qué te falta. No te falta dominio. Te falta procedimiento.

    Y un detalle remata la idea: probaron el protocolo en campañas piloto y, antes de las corridas finales, revisaron justo las secciones de orquestación y operaciones. No cambiaron el modelo. No añadieron más ciencia. Iteraron sobre el harness.

    Eso es Spec-Driven Development sin llamarlo por su nombre: escribir la especificación antes de dejar que nada se ejecute, y corregir la especificación en lugar de corregir la ejecución. La misma disciplina que desarrollo en el libro de SDD, solo que aquí el precio de improvisar no era un sprint perdido, eran 50.000 dólares de GPU.


    "¿No habíamos quedado en que los mega-prompts son mala idea?"

    Sí. Y este experimento no me desmiente. Me da la razón, aunque de lejos parezca lo contrario.

    Escribí Arquitectura de subagentes vs. mega-prompt defendiendo que un contexto único cargado de responsabilidades se degrada. Aquí hay un documento de 30.000 tokens que funcionó. Toca mirar el detalle.

    Primero: eso no es un prompt, es un protocolo compartido. Y el informe lo dice sin ambigüedad: cada agente de la campaña lo recibe como system prompt. En plural. Uno de los bloques de orquestación explica cómo delegar el trabajo en un equipo de subagentes de dos capas y cómo supervisarlo.

    Especificación larga, ejecución repartida. Que es justo lo que defendía aquel post.

    Segundo, el dato que lo remata. La campaña que atacó las 14 dianas a la vez dentro de una sola sesión se quedó en el 26,7 %. Darle a cada diana su propia sesión de 24 horas subió al 35,1 %: 143 binders frente a 104 sobre las mismas 13 dianas, con una p de 0,003.

    Anthropic avisa de que esa sesión dedicada también tuvo 2,8 veces más cómputo por diana, así que foco y presupuesto no se pueden separar del todo. Pero la dirección es la de siempre: cuantas menos cosas metes en un contexto, mejor sale.

    Un mega-prompt de los malos es sedimento. Instrucciones de dominio acumuladas, ejemplos pegados a mano y reglas contradictorias que alguien fue añadiendo cada vez que algo petó en producción. Esto es un manual de operaciones escrito una vez y repartido entre varios agentes.

    La lección no es "escríbelo todo más largo". Es qué metes dentro de cada contexto y cómo lo estructuras.


    Qué es un agente de IA autónomo (y qué no lo es)

    Un agente de IA autónomo es un sistema que recibe un objetivo y un protocolo escritos por una persona y, a partir de ahí, decide solo qué herramientas usar, en qué orden y qué resultados descartar, sin intervención humana durante la ejecución. No es un modelo más listo: es un modelo con un carril bien escrito.

    En esta campaña la autonomía duró 48 horas. Lo que la hizo posible no fue el modelo, fue el documento que alguien escribió antes de pulsar enter.


    La frontera real de los agentes de IA autónomos

    La palabra "autónomo" ha vendido muchos titulares estos días. Merece un asterisco grande.

    Lo decidió el agente Lo fijó el humano
    Qué investigar de cada diana Qué dianas
    Qué epítopo atacar El protocolo
    Qué herramientas usar y en qué orden Los antígenos del ensayo
    Qué candidatos descartar Los pedidos de síntesis
    Cómo rankear las secuencias finales La lectura de los datos

    Nadie tocó al agente durante la corrida. Cierto. Pero un humano eligió el problema, escribió las reglas, definió el ensayo y leyó los resultados.

    Ese es el patrón que veo funcionar una y otra vez en producción: autonomía total dentro de un carril que alguien dibujó antes, con mucho cuidado.

    El trabajo del ingeniero se ha movido del bucle al carril. Es justo lo que trabajo en el curso Construye con IA: el resultado depende mucho más de lo que escribes antes de lanzar el agente que del modelo que elijas.


    Por qué la química tardó minutos y esto semanas

    En la misma publicación hay un segundo experimento que casi nadie ha citado. Claude Opus 5 procesó ficheros de NMR y LC-MS en 23 y 19 minutos, y calculó una pureza del 96,4 % frente al 96,33 % que había medido el laboratorio.

    Minutos.

    Los binders necesitaron semanas de laboratorio húmedo para saber si el agente había acertado.

    Misma tecnología, misma calidad de razonamiento, velocidades incomparables. ¿La variable? Lo que cuesta comprobar la respuesta.

    Donde verificar es barato y rápido, el agente itera, se corrige y avanza. Donde verificar cuesta semanas y dinero, el agente dispara a ciegas y espera.

    Tu código está en el primer grupo. O debería estarlo. Un test que corre en 200 milisegundos es tu resonancia de plasmón superficial: la señal barata que le dice al agente si va bien o va mal. Por eso insisto tanto con el test harness. Sin él, tu agente vive en el mundo de las proteínas: dispara y reza.

    Y un detalle que deberías tatuarte: las puntuaciones de confianza del propio agente no avisaron de ninguno de los fallos. Los diseños contra MBP puntuaban casi igual que los que sí funcionaron. La confianza del modelo no es una señal de verificación.


    Los fallos, que Anthropic no escondió

    Contra MBP (maltose binding protein), una superficie grande, convexa y polar, sin un bolsillo donde agarrarse: 0 binders de 90 diseños. Cero.

    Contra TNFα, Opus 4.8 sacó 12 binders de 150 diseños y Mythos Preview ninguno de 60. El modelo mejor en la media, a cero en esa diana concreta. Y el informe no lo vende como victoria de un modelo: dice que cada campaña corrió una sola vez y usó generadores distintos, así que no pueden atribuir la diferencia a los modelos.

    Y hubo una diana 16 (GDF-8 mature) excluida del análisis porque el ensayo dio mediciones de mala calidad: la proteína se agregaba consigo misma. Ahí no falló el agente, falló el ensayo.

    Estos tres datos me dan más confianza que los 354 binders. Un informe que solo cuenta aciertos es marketing.

    Tampoco esconden el coste: 50.000 dólares de GPU en la corrida de 48 horas contra todas las dianas a la vez (hasta 12.500 horas de NVIDIA H100) y 10.000 por cada sesión de 24 horas contra una sola. La configuración más precisa fue también la más cara por diana.


    Lo que esto no es

    No es peer review. Es un estudio autopublicado por Anthropic sobre sus propios modelos. El trabajo de laboratorio lo hicieron terceros, que es lo que lo salva de ser una nota de prensa, pero nadie externo ha revisado la metodología.

    Y hay una línea que Anthropic no ha cruzado: el diseño de proteínas y otras capacidades de biología de uso dual siguen sin acceso general en Claude Fable 5, su modelo más capaz, por riesgo de armas biológicas. Los modelos clase Opus mantienen acceso limitado.

    La empresa que publica el estudio ha decidido no ofrecer esa capacidad en su mejor modelo. Ese freno también es un resultado del experimento.


    Qué haces el lunes con tus agentes de IA autónomos

    Abre el system prompt del agente que tengas en producción ahora mismo. Son quince minutos:

    1. Etiqueta cada bloque con una de estas tres palabras: dominio, orquestación, operaciones.
    2. Saca porcentajes. Divide las líneas de cada etiqueta entre el total.
    3. Compara con el 34/35/31 de Anthropic. Si te sale algo parecido a 90/5/5, ya sabes qué te falta: no te falta dominio, te falta procedimiento.
    4. Escribe lo que falta: el procedimiento paso a paso, los criterios para descartar, las señales de que va por buen camino, cuándo debe pararse y a quién avisa cuando no sabe seguir.

    Ese fue el 65,8 % del documento que le dieron a Claude. Y es la parte que casi nadie escribe, porque es aburrida y no luce en un tuit.

    Si te llevas una sola frase de todo esto, que sea esta: si tu agente no tiene una forma barata de saber si acertó, no tienes un agente. Tienes un generador de texto con acceso a tu terminal.

    En Dominicode Labs desmontamos este tipo de arquitecturas con proyectos reales. Pero el ejercicio de los quince minutos hazlo hoy.


    Preguntas frecuentes

    ¿Claude ha creado un fármaco?

    No. Diseñó binders: proteínas pequeñas que se pegan a una diana. Es el paso cero de muchos programas farmacológicos, y por delante queda todo el recorrido preclínico y regulatorio, que se mide en años.

    ¿El estudio está revisado por pares?

    No. Es un estudio autopublicado por Anthropic sobre sus propios modelos, sin peer review. Lo que sí es externo es la validación: Adaptyv Bio y Twist Bioscience sintetizaron las proteínas y midieron afinidad por resonancia de plasmón superficial. Nadie de fuera ha revisado la metodología, pero los resultados no salen de una simulación.

    ¿Qué significa una tasa de acierto del 26,8 %?

    Que de 1.320 diseños generados, 354 se confirmaron como binders en el laboratorio. El baseline actual de la industria está entre el 10 % y el 15 %. Conviene no mezclar brazos del experimento: el 26,8 % es el dato global y, por configuración, va del 22,6 % al 35,1 %.

    ¿Por qué acierta más si trabaja contra una sola diana?

    Porque la sesión dedicada de 24 horas concentra todo el presupuesto de razonamiento y cómputo en un único problema: sube del 26,7 % al 35,1 %. También sale más cara por diana, y Anthropic avisa de que no puede separar el efecto del foco del de un presupuesto 2,8 veces mayor por diana. Es tu mismo dilema entre lanzar un agente contra quince tickets a la vez o dedicarle una sesión completa al que importa.

    ¿Puedo usar Claude para diseñar proteínas?

    No con acceso general. El diseño de proteínas y otras capacidades de biología de uso dual siguen restringidas en Claude Fable 5, el modelo más capaz, por riesgo de armas biológicas. Los modelos clase Opus mantienen acceso limitado.

    ¿Qué me llevo de esto para mis agentes de IA autónomos si no toco biología?

    El reparto del protocolo: 34,2 % dominio, 34,7 % orquestación y validación, 31,1 % operaciones. Es la plantilla que yo usaría para escribir el contexto de un agente. Y la consecuencia práctica: iteraron sobre el harness, no sobre el modelo.


    Fuentes


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • El impuesto oculto de los frameworks de IA no existe: medí lo que mandan

    El impuesto oculto de los frameworks de IA no existe: medí lo que mandan

    Hay una frase que se repite en cada hilo sobre frameworks de IA: "te inyectan miles de tokens de prompts ocultos que tú no has escrito".

    La he leído decenas de veces. Nunca con un número al lado.

    Así que la medí. Levanté un endpoint falso que se hace pasar por la API de Anthropic, apunté a él el SDK oficial, el Vercel AI SDK y LangChain, y guardé el cuerpo exacto de la petición HTTP que cada uno manda por el cable.

    El resultado no es el que esperaba, y probablemente tampoco es el que esperas tú.


    Cómo lo medí

    La idea es simple: si quieres saber qué manda una librería, no leas su código. Ponte en medio.

    import http from "node:http";
    
    const capturas = [];
    const server = http.createServer((req, res) => {
      let body = "";
      req.on("data", c => (body += c));
      req.on("end", () => {
        capturas.push(body);                  // esto es lo que se manda de verdad
        res.writeHead(200, { "content-type": "application/json" });
        res.end(JSON.stringify({
          id: "msg_x", type: "message", role: "assistant", model: "claude-opus-5",
          content: [{ type: "text", text: "ok" }],
          stop_reason: "end_turn", stop_sequence: null,
          usage: { input_tokens: 1, output_tokens: 1 },
        }));
      });
    });
    await new Promise(r => server.listen(0, r));
    const BASE = `http://127.0.0.1:${server.address().port}`;
    

    Después, cada librería apuntando a BASE con la misma tarea: un mensaje de sistema idéntico, la misma pregunta y —en la segunda tanda— la misma herramienta.

    Versiones medidas: @anthropic-ai/sdk 0.120.0, ai 7.0.77 con @ai-sdk/anthropic 4.0.41, y langchain 1.5.10 con @langchain/anthropic 1.5.8. Los números son de estas versiones; si lees esto dentro de seis meses, vuelve a correrlo.


    Resultado 1: nadie inyecta un prompt oculto

    Primera tanda, sin herramientas. Mensaje de sistema de 47 caracteres, escrito por mí.

    Librería Cuerpo total Campo system
    SDK oficial de Anthropic 194 B 47 B
    LangChain (modelo directo) 210 B 47 B
    Vercel AI SDK 246 B 74 B

    LangChain manda exactamente mis 47 caracteres. Ni uno más. El SDK oficial, lo mismo.

    Vercel AI SDK manda 74 en vez de 47, y esos 27 caracteres de diferencia no son prosa: es que envuelve el string en la forma de bloques de contenido, [{"type":"text","text":"…"}]. Estructura, no instrucciones.

    Y ahora el dato que cierra el asunto. Repetí la prueba con el agente prefabricado de LangChain —el createAgent que viene de fábrica, justo la abstracción que se supone que te llena el contexto de basura— y el campo system de la petición venía así:

    system = 0 bytes
    

    Vacío. El agente prefabricado de LangChain no manda ningún prompt de sistema que tú no hayas puesto.

    Sea cual sea el origen de la leyenda de los "1.500 tokens ocultos", no describe estas librerías en 2026.


    Resultado 2: donde sí se paga es en los esquemas

    Segunda tanda, misma tarea pero declarando una herramienta: get_weather, con un solo parámetro string y su descripción.

    Librería Cuerpo total system tools
    SDK oficial de Anthropic 393 B 47 B 213 B
    LangChain (agente prefabricado) 436 B 0 B 299 B
    Vercel AI SDK 556 B 74 B 294 B

    Aquí sí hay diferencia, y no está donde la buscaba todo el mundo: está en cómo cada librería serializa el esquema de la herramienta.

    El SDK oficial manda el JSON Schema que tú escribiste, tal cual: 213 bytes. Vercel AI SDK y LangChain lo generan a partir de tu esquema de Zod, y el resultado es más verboso: 294 y 299 bytes. Un 38% y un 40% más para describir exactamente la misma función.

    En el total de la petición: 393 bytes contra 556 del Vercel AI SDK. Un 41% más.


    Qué significan de verdad 163 bytes

    Aquí es donde hay que ser honesto en las dos direcciones.

    En una llamada, no significa nada. 163 bytes son unos 40 tokens. Si tu agente hace diez peticiones al día, esta discusión es irrelevante y deberías dedicar el rato a otra cosa.

    Pero no escala como una constante, escala con tus herramientas. El 40% no es de la petición: es del bloque de esquemas. Un agente serio no tiene una tool, tiene quince o veinte. Ese bloque va en cada turno del bucle, no una vez por conversación. Y si el prefijo de tu prompt cambia entre peticiones, además pierdes los aciertos de caché.

    Así que el número que importa no es el mío: es el tuyo. Coge tu agente real, con tus tools reales, y mide el bloque tools de una petición. Si te sale un bloque de 6 KB repitiéndose en veinte turnos, ahí tienes una conversación que merece la pena. Cómo desglosar en qué se te va la factura lo conté en medir el consumo de tokens de un agente, y el efecto de cambiar de modelo con ese mismo contexto, en el coste de los subagentes.

    Y la palanca real, una vez lo has medido, no es quitar el framework: es tener menos herramientas y mejor descritas. Ese criterio lo desarrollé al montar un servidor de herramientas para tu agente sin MCP.


    Entonces, ¿framework o código directo?

    Si has llegado hasta aquí esperando que te diga que quites el framework, malas noticias: el argumento de los tokens no sostiene esa decisión. La diferencia existe, es medible y es pequeña comparada con lo que de verdad decide.

    Lo que sí decide:

    Depurabilidad. Cuando un agente falla en producción necesitas ver el mensaje exacto que salió. Con el SDK directo pones un console.log en la llamada. Con capas por encima, tienes que aprender dónde mirar. No es imposible —el arnés de esta prueba son cuarenta líneas— pero es trabajo.

    Retraso frente a la API. Los proveedores sacan capacidades nuevas constantemente. Con el SDK directo las usas el mismo día. Con una capa intermedia, esperas a que la abstraiga. Este es, en mi experiencia, el coste real de un framework, y no aparece en ninguna tabla de bytes.

    Acoplamiento de tu dominio. Si la lógica de decisión de tu negocio vive dentro de las clases de un tercero, no eres dueño de tu arquitectura. Esto es lo mismo que llevamos treinta años diciendo de los ORM y de los frameworks de UI, y aplica igual.

    Y en la otra dirección: hay problemas donde un grafo de estados expresa cosas que un while no expresa bien —ramificaciones, reanudar tras una pausa humana, estado explícito entre pasos—. Si tu bucle ya se está llenando de banderas, esa es la señal.

    Si lo que quieres es el bucle explícito bien hecho, con control de pasos y detección de estancamiento, está entero en Agentic Loop en TypeScript.


    Mide el tuyo antes de opinar

    El arnés completo cabe en un archivo. Levanta el servidor de arriba, apunta tu cliente a BASE en lugar de a la API real, lanza una petición representativa y mira el cuerpo:

    const cuerpo = capturas.pop();
    const j = JSON.parse(cuerpo);
    
    console.log("total  :", cuerpo.length, "bytes");
    console.log("system :", (j.system ? JSON.stringify(j.system).length : 0), "bytes");
    console.log("tools  :", (j.tools ? JSON.stringify(j.tools).length : 0), "bytes");
    console.log("mensajes:", JSON.stringify(j.messages).length, "bytes");
    

    Cuatro líneas y dejas de discutir de oídas. Y si el bloque de esquemas te sorprende, el sitio donde arreglarlo es el diseño de tus contratos: los patrones de Zod para que un esquema diga lo justo están en el curso de Zod para TypeScript.

    Definir esas interfaces antes de escribir el agente es lo que evita acabar con veinte tools que nadie recuerda para qué son, y es la metodología del libro de Spec-Driven Development. El flujo completo con agentes CLI lo enseño en el curso Construye con IA.

    En Dominicode Labs comparto las mediciones reales de los agentes que tengo corriendo.

    La conclusión que me llevo no es "framework sí" ni "framework no". Es que llevábamos dos años repitiendo un número que nadie había comprobado, y que el sitio donde de verdad se te va el contexto —los esquemas de tus herramientas— no sale en ningún hilo.


    Preguntas frecuentes

    ¿Es verdad que LangChain inyecta prompts ocultos en cada petición?

    En las versiones medidas para este post, no. Con langchain 1.5.10 y @langchain/anthropic 1.5.8, tanto el modelo directo como el agente prefabricado mandan en el campo system exactamente lo que tú pones — y el agente prefabricado, cuando no le das mensaje de sistema, manda ese campo vacío. La afirmación de los "miles de tokens ocultos" no describe estas versiones.

    ¿Cuánto overhead añade entonces un framework?

    En la prueba, con una sola herramienta declarada: el bloque tools pasó de 213 bytes con el SDK oficial a 294 con Vercel AI SDK y 299 con LangChain, un 38% y un 40% más. En el cuerpo total de la petición, 393 bytes frente a 556. La diferencia viene de generar el JSON Schema a partir de Zod, que sale más verboso que un esquema escrito a mano.

    ¿Cómo mido el overhead de mi propio agente?

    Levanta un servidor HTTP local que responda con la forma de respuesta del proveedor, apunta tu cliente a esa URL con la opción baseURL, lanza una petición representativa y mide la longitud del cuerpo por campos: system, tools y messages. Son unas cuarenta líneas y te da el dato exacto de tu caso, que es el único que importa.

    ¿Merece la pena quitar el framework para ahorrar tokens?

    Casi nunca. La diferencia medida es real pero pequeña frente a otras decisiones. Si vas a quitarlo, que sea por depurabilidad, por no ir con retraso respecto a las capacidades nuevas de la API o por no acoplar tu lógica de negocio a un tercero. El ahorro de tokens es el peor de los argumentos disponibles.

    ¿Por qué el bloque de tools pesa más que el prompt de sistema?

    Porque describe una interfaz completa: nombre, descripción, tipos de cada parámetro, cuáles son obligatorios y las descripciones de cada campo. Y porque se manda en cada turno del bucle agéntico, no una vez por conversación. Con quince o veinte herramientas, ese bloque es la mayor parte del contexto fijo que pagas en cada llamada.

  • ¿Es Grok 4.6 el mejor modelo para programar? Editor sí, terminal no

    ¿Es Grok 4.6 el mejor modelo para programar? Editor sí, terminal no

    xAI publicó Grok 4.6 el 12 de agosto de 2026, treinta y cinco días después de Grok 4.5.

    Y como pasa siempre, en cuestión de horas ya circulaban capturas de tablas de barras diciendo que es el mejor modelo del mundo para programar.

    La pregunta está mal formulada.

    No porque Grok 4.6 sea malo —no lo es, y en una de las dos medidas que importan está arriba— sino porque "programar" no es una sola tarea, y los benchmarks que la miden no puntúan lo mismo.

    Hay dos cifras públicas de Grok 4.6 que responden a la pregunta mejor que cualquier hilo de X. Una la publica xAI. La otra la mide un tercero. Y entre las dos hay una brecha que te dice exactamente cuándo te conviene este modelo y cuándo no.

    Vamos con las dos.


    Qué ha publicado xAI y qué ha medido alguien más

    Antes de mirar un solo número, la distinción de siempre: no es lo mismo una cifra que publica el fabricante en su propia nota de prensa que una cifra medida por un tercero con un harness que no controla el fabricante.

    Las dos sirven. Pero no valen igual, y mezclarlas en la misma tabla es la forma más común de sacar una conclusión equivocada. Si quieres el criterio completo para separarlas, lo desarrollé al analizar las cifras de Grok 4.5, Fable 5 y DeepSeek V4, y el caso más descarado de tabla propia puntuando a los rivales lo tienes en la tabla de Alibaba para Qwen3.8-Max.

    Con Grok 4.6, esto es lo que hay a 24 de agosto de 2026.

    Autoreportado por xAI (su propia nota de lanzamiento):

    Benchmark Grok 4.6 Qué mide
    CursorBench v3.2 69,9 % Edición de código dentro del editor
    DeepSWE v1.1 65,9 % Ingeniería de software autónoma
    FrontierCode v1.1 61,3 % Código de dificultad alta
    APEX-Agents 57,5 % Tareas agénticas de horizonte largo
    APEX-SWE 56,4 % Ingeniería de software agéntica
    Terminal-Bench v3.0 26 % Trabajo real en terminal

    Medido por terceros:

    • Artificial Analysis Intelligence Index: 61. Verificado de forma independiente.
    • Terminal-Bench 3.0: 26,5 % en el snapshot público del leaderboard, actualizado el 20 de agosto de 2026 (el benchmark lo desarrolla el equipo de Harbor junto a Laude Institute, Snorkel AI y Turing).

    Fíjate en que la última fila de la tabla de xAI y la medición externa coinciden: 26 % frente a 26,5 %. Aquí no hay discusión metodológica ni harness sospechoso. xAI reporta su peor número con honestidad, y el tercero lo confirma.

    Ese es el número del que nadie hizo captura.


    La brecha: 69,9 % en el editor, 26,5 % en la terminal

    Pon las dos medidas juntas y el modelo se parte en dos.

      Grok 4.6, dos medidas del mismo modelo
    
      Editor    (CursorBench v3.2)   69,9 %
      ████████████████████████
    
      Terminal  (Terminal-Bench 3.0) 26,5 %
      █████████
    

    El mismo modelo, la misma semana, con 43 puntos de diferencia según lo que le pidas.

    Y para saber si ese 26,5 % es bueno o malo hace falta el contexto del leaderboard completo. Esta es la foto de Terminal-Bench 3.0 al 20 de agosto de 2026:

    # Modelo Terminal-Bench 3.0
    1 Claude Opus 5 42,7 %
    2 GPT-5.6 Sol 34,6 %
    3 Claude Fable 5 34,0 %
    4 GLM-5.3 32,4 %
    5 Grok 4.6 26,5 %
    6 Claude Opus 4.8 21,1 %
    7 GPT-5.6 Terra 20,8 %
    8 SWE-1.7 Lightning 18,6 %
    9 Grok 4.5 15,7 %
    10 Claude Sonnet 5 14,6 %
    11 GPT-5.6 Luna 14,3 %
    12 GLM-5.2 4,6 %

    Dos lecturas, y las dos son verdad.

    La mala: Grok 4.6 queda quinto, a 16,2 puntos de Claude Opus 5. En trabajo de terminal saca el 62 % de la puntuación del líder. No está cerca.

    La buena, y es la que casi nadie contó: Grok 4.5 estaba en 15,7 %. Grok 4.6 está en 26,5 %. Son 10,8 puntos de salto en treinta y cinco días, el mayor avance generacional de toda la tabla. De paso, Grok 4.6 ya pasa por delante de Claude Opus 4.8 (21,1 %) y de GPT-5.6 Terra (20,8 %).

    xAI lo respalda con su propia medición en la misma dirección: APEX-Agents sube de 47,1 % en Grok 4.5 a 57,5 % en 4.6, otros 10,4 puntos.

    Es decir: el trabajo agéntico es exactamente donde xAI ha metido el esfuerzo de esta versión, y se nota. Simplemente partían muy por detrás y todavía no han llegado.


    Por qué el editor y la terminal no miden lo mismo

    Esta es la parte que convierte una tabla en una decisión.

    Un benchmark de edición en el editor te pone delante un cambio acotado: aquí está el archivo, aquí está el contexto, escribe el diff. Una o pocas pasadas. El estado del mundo no cambia mientras trabajas. Si el modelo razona bien y conoce el lenguaje, acierta.

    Un benchmark de terminal es otro deporte:

      EDITOR                    TERMINAL
      ─────────                 ────────
      contexto dado             hay que descubrirlo
      1 pasada                  decenas de pasos
      estado fijo               estado que tú mutas
      fallo = diff malo         fallo = entorno roto
    

    En la terminal el modelo tiene que decidir qué comando lanzar, leer una salida que no esperaba, entender que algo ha cambiado por su propia acción anterior y corregir el rumbo sin perder el objetivo. Terminal-Bench 3.0 aprieta justo ahí: incluye nodos con GPU, topologías multi-contenedor, microservicios vivos y una corrección estricta que solo da el punto si el resultado final es exactamente el pedido.

    Ahí no se premia saber programar. Se premia no perder el hilo durante cuarenta pasos y verificar tu propio trabajo antes de seguir. xAI lo reconoce en su nota: dicen que en trayectorias largas empezaron a ver al modelo autoverificándose más.

    Que un modelo se caiga de 69,9 % a 26,5 % entre esos dos escenarios no es una contradicción. Es la descripción de dónde está su límite. Y si tú operas agentes que leen, escriben y ejecutan tests sobre tu repositorio, el número que te afecta es el segundo, no el primero.

    Por qué un bucle agéntico largo es tan frágil, y qué controles hay que ponerle, lo desmenucé en el agentic loop en producción con TypeScript.


    Lo que cuesta

    Grok 4.6 en la API de xAI, tarifa estándar por millón de tokens:

    Entrada Entrada en caché Salida
    Grok 4.6 $2 $0,50 $6
    Claude Opus 5 $5 $25

    Ventana de contexto: 500K tokens.

    Y el detalle que se come presupuestos: a partir de 200K tokens de prompt, la petición entera pasa a la banda de contexto largo. No se encarece solo el tramo que excede el umbral: se recalculan todos los tokens de esa petición a la tarifa alta. Es el mismo mecanismo que ya tenía Grok 4.5 y que expliqué con números en el análisis de Grok 4.5. Si tu agente arrastra contexto acumulado, cruzas ese umbral sin darte cuenta.

    Ahora, la comparación honesta. Grok 4.6 cuesta 2,5 veces menos en entrada y 4,2 veces menos en salida que Opus 5. Si divides el precio de salida entre los puntos de Terminal-Bench que consigue cada uno, sale esto:

    • Grok 4.6: $6 / 26,5 = $0,23 por punto
    • Claude Opus 5: $25 / 42,7 = $0,59 por punto

    Grok 4.6 rinde 2,6 veces más barato por punto de terminal. Esa cifra la he derivado yo de las dos tablas de arriba, no la publica nadie, y tiene una trampa importante: en trabajo agéntico, el modelo que falla es el más caro de todos, porque cada intento fallido se paga entero y además te consume el tiempo de revisión. El precio por punto es una buena guía para elegir modelo en tareas que puedes verificar barato, y una guía pésima para elegirlo en tareas que se rompen caro.

    Ese cálculo, hecho por tarea completada y no por token, es el que decide de verdad, y lo desarrollé en el coste de los subagentes al cambiar de modelo.


    Entonces, ¿es el mejor modelo para programar?

    Con los datos públicos a 24 de agosto de 2026:

    Sí, es una opción muy competitiva para:

    • Escribir y editar código dentro del editor, con el contexto ya delante.
    • Algoritmos, refactors acotados, scripts aislados y consultas complejas.
    • Volumen alto de tareas verificables donde el precio por token pesa y un fallo se detecta en segundos.
    • Contextos grandes de lectura, siempre que vigiles el umbral de 200K.

    No, no lidera para:

    • Agentes autónomos que corren durante decenas de pasos sobre tu repositorio.
    • Trabajo de terminal con estado mutable: contenedores, servicios, migraciones.
    • Cualquier flujo donde el coste de un fallo silencioso sea alto.

    Y esta es la conclusión incómoda para los titulares: Grok 4.6 no compite con Claude Opus 5 en la fila que más importa si tu trabajo es agéntico, pero ha recortado más distancia en un mes que ningún otro modelo de la tabla. Si xAI mantiene ese ritmo, la comparación de dentro de dos versiones puede ser otra.

    Para decidir modelo por tipo de trabajo en lugar de por titular, tengo el marco completo en Opus 5 vs GPT-5.6 vs Kimi K3.


    Cómo comprobarlo en tu proyecto en una tarde

    Ningún leaderboard puntúa tu repositorio. Esto sí:

    1. Coge tres tareas reales ya resueltas de tu historial de Git, con su diff final conocido. Una acotada de editor, una de refactor medio y una que toque terminal o migraciones.
    2. Lánzalas al mismo harness, cambiando solo el modelo. El harness pesa tanto como el modelo: si cambias las dos cosas a la vez, no estás midiendo nada.
    3. Puntúa por tarea completada, no por impresión. Pasó los tests o no pasó. Y anota el coste total de cada intento, fallos incluidos.

    Con nueve ejecuciones tienes más información sobre tu caso que con todos los benchmarks de este post.

    Y la parte que no cambia sea cual sea el modelo: si el requerimiento es ambiguo, fallan todos. Cuando cierras el alcance y las interfaces en un spec.md antes de ejecutar, cualquier modelo de frontera sube su tasa de acierto. Tienes la metodología completa en el libro de Spec-Driven Development, y el pipeline práctico con herramientas CLI agénticas en el curso Construye con IA: de la idea al producto con Claude Code.

    En Dominicode Labs vamos pasando cada modelo nuevo por proyectos reales y compartimos los resultados: qué entra en el stack, qué se queda fuera y por qué.

    Prueba Grok 4.6. Pero mide la fila que se corresponde con tu trabajo, no la que mejor queda en una captura.


    Preguntas frecuentes

    ¿Cuánto ha mejorado Grok 4.6 respecto a Grok 4.5 en trabajo de terminal?

    Ha subido de 15,7 % a 26,5 % en Terminal-Bench 3.0, según el snapshot público del leaderboard del 20 de agosto de 2026. Son 10,8 puntos en treinta y cinco días, el mayor salto generacional de la tabla. xAI reporta una mejora en la misma dirección con su propia medición de APEX-Agents: de 47,1 % a 57,5 %.

    ¿Por qué Grok 4.6 saca 69,9 % en CursorBench y solo 26,5 % en Terminal-Bench 3.0?

    Porque miden trabajos distintos. CursorBench evalúa edición de código con el contexto ya dado y en pocas pasadas. Terminal-Bench 3.0 evalúa trayectorias largas en un entorno con estado mutable —contenedores, servicios vivos, nodos con GPU— y solo concede el punto si el resultado final es exactamente el pedido. El primer escenario premia saber programar; el segundo, no perder el hilo durante decenas de pasos.

    ¿El contexto de 500K de Grok 4.6 cambia algo para trabajar sobre un repositorio grande?

    Ayuda a leer, pero ojo con la factura: a partir de 200K tokens de prompt, xAI recalcula todos los tokens de esa petición a la tarifa de contexto largo, no solo el exceso. Un agente que acumula contexto cruza ese umbral sin avisar. Y una ventana grande no arregla el problema de fondo del trabajo agéntico, que es mantener el objetivo, no almacenar texto.

    ¿Qué es APEX-Agents y por qué xAI lo destaca?

    Es un benchmark de tareas agénticas de horizonte largo, y xAI lo destaca porque es donde más ha mejorado: 57,5 % frente al 47,1 % de Grok 4.5. Es una cifra autoreportada por xAI, no verificada por un tercero, así que conviene leerla como una señal de la dirección del trabajo del proveedor y no como una medición neutral.

    ¿Cuándo me conviene Grok 4.6 en lugar de Claude Opus 5?

    Cuando tu trabajo sea acotado y verificable barato: edición en el editor, algoritmos, refactors pequeños, volumen alto de tareas que fallan de forma visible. Ahí el precio marca la diferencia, porque Grok 4.6 cuesta $2/$6 por millón frente a $5/$25 de Opus 5. Si tu trabajo es un agente autónomo corriendo sobre tu repositorio, los 16,2 puntos de diferencia en Terminal-Bench se pagan en fallos silenciosos y en tu tiempo de revisión, y ahí sale más caro lo barato.

  • LangGraph TypeScript: cuándo un grafo gana al while loop

    LangGraph TypeScript: cuándo un grafo gana al while loop

    Tenía un agente que revisaba pull requests. Cincuenta líneas de TypeScript, un while, tres tools. Funcionaba.

    Hasta que un PR tocó el módulo de autenticación y el agente hizo lo correcto: parar y pedir aprobación humana. El problema es que "parar" significaba dejar un proceso de Node vivo esperando un webhook que llegó dieciocho horas después. El proceso ya no existía. El contexto tampoco.

    Reinicié. Volvió a analizar el PR desde cero, volvió a gastar tokens, volvió a pedir aprobación. Mi loop no tenía un bug: tenía un límite arquitectónico.

    LangGraph TypeScript existe para ese límite exacto. Y lo adoptas sin comprar la casa entera para usar el garaje.

    LangGraph es la librería de orquestación de agentes de LangChain, disponible para TypeScript y Python, que modela un agente como un grafo de estados: los nodos son funciones que reciben y devuelven estado, las aristas deciden qué nodo va después, y un checkpointer persiste el estado tras cada paso. Ese checkpointer es lo que permite pausar una ejecución hoy y reanudarla dentro de tres días, en otra máquina.

    El loop explícito resuelve la mayoría de los agentes

    Empecemos por lo incómodo: en los proyectos que he tocado, la gran mayoría de los agentes no necesitan un framework de orquestación. Necesitan esto.

    type ToolCall = { id: string; name: string; args: unknown };
    type Msg =
      | { role: "user" | "assistant" | "system"; content: string }
      | { role: "assistant"; content: string; toolCalls: ToolCall[] }
      | { role: "tool"; toolCallId: string; content: string };
    
    export async function agente(prompt: string): Promise<string> {
      const messages: Msg[] = [{ role: "user", content: prompt }];
      let turno = 0;
    
      while (turno++ < 10) {
        const res = await llm.complete(messages);
    
        if (!res.toolCalls?.length) return res.content;
    
        messages.push({
          role: "assistant",
          content: res.content,
          toolCalls: res.toolCalls,
        });
    
        for (const call of res.toolCalls) {
          const tool = tools[call.name];
          // El nombre de la tool lo elige el modelo. Si alucina uno, se lo devuelves
          // como error para que se corrija, en vez de reventar a mitad de ejecución.
          const salida = tool
            ? await tool(call.args)
            : `Error: la herramienta "${call.name}" no existe.`;
          messages.push({ role: "tool", toolCallId: call.id, content: salida });
        }
      }
    
      throw new Error("Límite de turnos alcanzado");
    }
    

    Eso es un agente. Lo depuras con console.log, lo entiendes entero en treinta segundos y no tiene una capa de orquestación que pueda romperte en la siguiente minor.

    Yo defiendo este loop, y lo he defendido por escrito: en multi-agente sin orquestador explico por qué la mayoría de los sistemas "multi-agente" son un for con buen marketing. Sigo pensando lo mismo.

    El loop no falla por complejidad. Falla por duración.

    Cuándo usar LangGraph en vez de un while loop

    Usa LangGraph cuando tu agente cumpla al menos uno de estos tres síntomas. Si no cumple ninguno, quédate con el while. El punto de inflexión no es "mi agente hace muchas cosas": es uno de estos tres, y basta con uno.

    1. El estado tiene que sobrevivir al proceso. Si tu agente vive más que un request HTTP —minutos, horas, días— el array messages en memoria es una bomba de relojería. Un deploy, un reinicio, un pod que se recicla, y perdiste la ejecución.
    2. La ramificación es real, no cosmética. Un if dentro del loop está bien. Pero cuando el camino A y el camino B tienen pasos distintos, reintentos distintos y puntos de salida distintos, el loop se convierte en un árbol de condicionales que nadie quiere tocar.
    3. Un humano tiene que decidir en mitad de la ejecución. No al principio ni al final. En mitad. Y puede tardar un día en contestar.
    while loop explícito LangGraph (StateGraph)
    Estado entre pasos Array en memoria Campos tipados con reducers
    Sobrevive a un reinicio No Sí, con checkpointer
    Pausar y reanudar Lo escribes tú interrupt() + Command({ resume })
    Ramificación if anidados addConditionalEdges tipado
    Depuración console.log Inspección del grafo y del checkpoint
    Dependencias Ninguna @langchain/langgraph + @langchain/core
    Coste de entrada Cero Una tarde por tramo migrado

    Si no tienes ninguno de los tres, cierra esta pestaña y quédate con tu loop. Hablo en serio. Ese es justamente el argumento que defiendo en el stack de IA agéntica que uso: la capa de orquestación es la última que deberías añadir, no la primera.

    Un apunte de vocabulario, porque genera confusión real: aquí "grafo" significa grafo de orquestación —qué nodo se ejecuta después de cuál—. No tiene nada que ver con el grafo de recuperación del que hablé en qué es graph engineering, que va de qué código llega al contexto del modelo. Misma palabra, dos capas distintas del sistema.

    El estado primero, el grafo después

    En LangGraph el estado no es un detalle de implementación: es el contrato. Y en la v1 —@langchain/langgraph 1.4.10, agosto de 2026— se declara con StateSchema, aceptando esquemas de Zod campo a campo.

    import {
      StateSchema,
      MessagesValue,
      ReducedValue,
    } from "@langchain/langgraph";
    import { z } from "zod";
    
    const RevisionState = new StateSchema({
      messages: MessagesValue,
      pr: z.string(),
      riesgo: z.enum(["bajo", "alto"]).default("bajo"),
      hallazgos: new ReducedValue(z.array(z.string()).default(() => []), {
        reducer: (actual: string[], nuevo: string[]) => actual.concat(nuevo),
      }),
      aprobado: z.boolean().default(false),
    });
    
    type Revision = typeof RevisionState.State;
    

    Fíjate en ReducedValue. Esa es la pieza que no tiene equivalente limpio en el loop: define cómo se combinan las actualizaciones de un campo. Los nodos devuelven trozos de estado y el reducer decide si se sobrescriben o se acumulan. Sin eso, dos nodos que escriben en hallazgos se pisan.

    Y sí, es Zod de verdad: .default(), .enum(), refinamientos. El estado del agente es un contrato de datos como cualquier otro, y aquí es donde se nota tenerlos bien tipados — es el mismo músculo que entreno en el curso de Zod para TypeScript.

    Verás mucho tutorial con Annotation.Root({ ... }). Sigue funcionando y sigue compilando, pero es la sintaxis anterior. Si empiezas hoy, empieza con StateSchema.

    Nodos, aristas y la decisión que el loop no sabe expresar

    Un nodo es una función que recibe el estado y devuelve un trozo de estado. Nada más.

    import {
      StateGraph, START, END, MemorySaver, interrupt, Command,
    } from "@langchain/langgraph";
    
    async function analizar(state: Revision) {
      const tocaAuth = state.pr.includes("auth");
      return {
        hallazgos: ["Cobertura de tests: 62%"],
        riesgo: tocaAuth ? ("alto" as const) : ("bajo" as const),
      };
    }
    
    async function aprobarAuto(_state: Revision) {
      return { aprobado: true };
    }
    
    function enrutar(state: Revision): "aprobarAuto" | "revisionHumana" {
      return state.riesgo === "alto" ? "revisionHumana" : "aprobarAuto";
    }
    
    const grafo = new StateGraph(RevisionState)
      .addNode("analizar", analizar)
      .addNode("aprobarAuto", aprobarAuto)
      .addNode("revisionHumana", revisionHumana)
      .addEdge(START, "analizar")
      .addConditionalEdges("analizar", enrutar, ["aprobarAuto", "revisionHumana"])
      .addEdge("aprobarAuto", END)
      .addEdge("revisionHumana", END)
      .compile({ checkpointer: new MemorySaver() });
    

    addConditionalEdges recibe el nodo origen, la función que decide y la lista de destinos posibles. Esa lista no es decorativa: es lo que hace que el enrutado sea tipado y que el grafo sea inspeccionable antes de ejecutarlo.

    Y ahí está compile({ checkpointer }). Esa línea es la que justifica todo lo demás. Sin checkpointer tienes un runner de funciones con sintaxis rara. Con checkpointer tienes una máquina de estados que se puede pausar y reanudar.

    MemorySaver es para desarrollo —vive en RAM y muere con el proceso—. Para producción usa los checkpointers persistentes, que van en paquetes aparte: @langchain/langgraph-checkpoint-postgres (1.0.4) o @langchain/langgraph-checkpoint-sqlite (1.0.3).

    Human-in-the-loop en LangGraph: la funcionalidad que justifica el cambio

    El human-in-the-loop en LangGraph se implementa con interrupt(): el nodo lanza la pausa, el grafo guarda el estado en el checkpointer y la ejecución termina. Cuando llega la respuesta humana, se reanuda con Command({ resume }) sobre el mismo thread_id.

    Aquí es donde mi PR de las dieciocho horas deja de ser un problema.

    type PeticionRevision = {
      pr: string;
      hallazgos: string[];
      pregunta: string;
    };
    
    async function revisionHumana(state: Revision) {
      const decision = interrupt<PeticionRevision, { aprobado: boolean }>({
        pr: state.pr,
        hallazgos: state.hallazgos,
        pregunta: "Este PR toca auth. ¿Lo apruebas?",
      });
    
      return { aprobado: decision.aprobado };
    }
    

    Cuando la ejecución llega a interrupt(), el grafo persiste el estado exacto y para. No bloquea un proceso: termina. El estado queda guardado bajo un thread_id.

    const config = { configurable: { thread_id: "pr-482" } };
    
    await grafo.invoke({ pr: "feat/auth-refresh-token" }, config);
    
    const pausa = await grafo.getState(config);
    console.log(pausa.next);                          // [ 'revisionHumana' ]
    console.log(pausa.tasks[0]?.interrupts[0]?.value); // el payload de la pregunta
    
    // Horas o días después, otro proceso, otro deploy:
    const final = await grafo.invoke(
      new Command({ resume: { aprobado: true } }),
      config
    );
    console.log(final.aprobado); // true
    

    Léelo otra vez. El segundo invoke puede ocurrir en otra máquina, la semana siguiente, después de tres despliegues. El grafo continúa donde estaba: analizar no se vuelve a ejecutar y no gastas otra vez esos tokens.

    Eso, en el loop, no lo montas en un rato. Escribes tu propio serializador de estado, tu propio registro de "en qué paso iba" y tu propia lógica de reanudación. Es decir: escribes un checkpointer peor.

    Tres avisos que cuestan tiempo:

    1. El nodo que contiene el interrupt() sí se re-ejecuta entero al reanudar. El grafo no repite los nodos anteriores, pero este arranca otra vez desde su primera línea. Si pones un INSERT, un webhook o un cobro antes de la llamada, ocurre dos veces. Todo efecto secundario va después del interrupt(), nunca antes.
    2. No envuelvas interrupt() en un try/catch: señaliza la pausa con una excepción y te la comerías.
    3. Lo que le pasas debe ser serializable a JSON.

    Cuándo NO montar el grafo de estados en LangGraph

    No lo montes porque el proyecto "va a crecer". Móntalo cuando tengas uno de los tres síntomas delante.

    Y no confundas esto con adoptar el ecosistema entero. Ya dejé claro mi veredicto sobre la librería base en el stack de IA agéntica que uso: demasiada abstracción sobre abstracciones. LangGraph es otra cosa. Es una máquina de estados con persistencia, y puedes usarla sin tocar el resto.

    Un detalle actual que evita un error frecuente: el prebuilt createReactAgent de @langchain/langgraph/prebuilt está marcado como deprecado. Se movió al paquete langchain como createAgent. Si sigues un tutorial de hace un año, vas a copiar un import obsoleto.

    Y antes de dibujar un solo nodo, escribe qué estados existen y qué transiciones son legales. Un grafo mal pensado es peor que un loop, porque además parece serio. Esa disciplina de definir el contrato antes de escribir la implementación es la misma que defiendo en el libro de Spec-Driven Development, y aquí paga doble.

    Qué hacer con esto hoy

    Abre tu agente y busca una sola cosa: un punto donde la ejecución tenga que sobrevivir a un reinicio. Una aprobación, una espera larga, un proceso por lotes que tarda horas.

    Si no lo encuentras, tu loop está bien. Cierra el editor.

    Si lo encuentras, no reescribas el agente entero. Extrae solo ese tramo a un StateGraph con checkpointer, deja el resto como está y quédate con las tools intactas. Migrar un tramo cuesta una tarde. Migrar por moda cuesta un trimestre.

    Si quieres ver este tipo de decisiones tomadas en proyectos reales —cuándo meter un framework y cuándo no—, es justo lo que trabajo en Construye con IA, y en Dominicode Labs montamos estos grafos con el código completo delante.

    Preguntas frecuentes

    ¿Cuándo usar LangGraph en vez de un while loop?

    Cuando la ejecución tenga que sobrevivir al proceso, cuando la ramificación tenga pasos y salidas realmente distintas, o cuando un humano deba decidir en mitad del flujo. Con uno solo de esos tres basta. Si tu agente empieza y termina dentro del mismo request, el while explícito es mejor opción: se depura con console.log y no tiene una capa de orquestación que se rompa en la siguiente minor. LangGraph no gana por complejidad, gana por duración.

    ¿Necesito un checkpointer para usar interrupt() en LangGraph?

    Sí, y no es opcional. interrupt() funciona persistiendo el estado del grafo y terminando la ejecución. Sin un checkpointer en compile() no hay dónde guardar ese estado, así que no hay nada que reanudar. En desarrollo te vale MemorySaver; en producción necesitas uno con almacenamiento real, o perderás las pausas en cada despliegue.

    ¿StateSchema con Zod sustituye a Annotation.Root en LangGraph TypeScript?

    Es la forma actual de declarar el estado y la que deberías usar en código nuevo. Annotation.Root sigue exportándose y sigue compilando, así que no tienes que migrar nada con prisa. La diferencia práctica es que con StateSchema reutilizas esquemas de Zod que probablemente ya tienes en el proyecto, con sus default() y sus validaciones, en lugar de aprender una segunda sintaxis solo para el estado del grafo.

    ¿Qué checkpointer uso en producción con LangGraph JS?

    MemorySaver viene en el paquete principal pero guarda en RAM: sirve para tests y ejemplos, no para producción. Los checkpointers persistentes van en paquetes aparte, @langchain/langgraph-checkpoint-postgres y @langchain/langgraph-checkpoint-sqlite. Si ya tienes Postgres en el stack, esa es la respuesta fácil, porque el estado del agente pasa a ser una tabla más que respaldas y auditas como cualquier otra.

    ¿Puedo migrar mi while loop a LangGraph sin reescribir las tools?

    Sí, y es la vía que recomiendo. Las tools son funciones con un esquema de entrada; no les afecta quién las llama. Lo que cambia es el orquestador: el bucle pasa a ser nodos y aristas, y el array de mensajes pasa a ser un campo del estado. Puedes migrar un solo tramo del flujo —el que necesita pausarse— y dejar el resto del agente exactamente como está.

    ¿Necesito LangChain para usar LangGraph en TypeScript?

    No. @langchain/langgraph declara @langchain/core como peer dependency —de ahí salen los tipos de mensajes y modelos— pero no requiere el paquete langchain ni sus cadenas y abstracciones: una instalación limpia trae @langchain/core, langgraph-checkpoint y langgraph-sdk, y ahí se acaba. Puedes montar un StateGraph llamando dentro de tus nodos al SDK del proveedor que ya uses. Un nodo es una función asíncrona: lo que hagas dentro es cosa tuya.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • ChatGPT Business Premium Seats: Precio Real y Cuándo Conviene

    ChatGPT Business Premium Seats: Precio Real y Cuándo Conviene

    Hace dos meses hablé con el CTO de una empresa de 25 personas. Tenían a 14 empleados pagando cuentas individuales de ChatGPT Plus con la tarjeta de la empresa.

    Cada uno con su login personal. Cada uno compartiendo fragmentos de código, contratos y datos de clientes en chats que OpenAI, por defecto en planes personales, podía usar para entrenar sus modelos. Cero control de accesos, cero logs de auditoría y $280 al mes tirados en cuentas aisladas.

    Cuando OpenAI renombró su plan Team a ChatGPT Business y lanzó ChatGPT Business Premium seats como upgrade dentro de ese mismo workspace —junto al contrato Enterprise para volumen alto— la promesa fue sencilla: orden corporativo, privacidad estricta y capacidad computacional dedicada.

    La pregunta que todo líder técnico se hace es otra: ¿te conviene pagar una suscripción mensual fija por cada asiento o es más rentable montar herramientas internas sobre la API?

    Vamos a desglosar los precios reales, las novedades técnicas de estos asientos y el criterio exacto para decidir sin quemar presupuesto.


    La estructura de precios de ChatGPT para empresas

    Para entender dónde encajan los asientos Premium en entornos de trabajo, primero hay que ubicar la pirámide de planes actual de OpenAI:

    Nivel Precio por usuario Compromiso mínimo Privacidad de datos Modelos y Capacidad
    ChatGPT Plus $20 / mes 1 usuario ❌ Opt-out manual necesario Límites estándar de mensajes
    ChatGPT Business (asiento estándar) $20 / mes (anual) / $25 (mensual) Mínimo 2 usuarios ✅ SOC 2 Tipo II + cero entrenamiento Límite de uso de 5h + Workspace compartido
    ChatGPT Business — Asiento Premium $100 / mes (anual) / $125 (mensual) Add-on dentro del mismo workspace ✅ SOC 2 Tipo II + cero entrenamiento 5x más uso, sin límite de 5h
    ChatGPT Enterprise Cotización a medida (mercado: ~$45-75/asiento) Mínimo ~150 licencias ✅ SLA dedicado + BAA HIPAA Ventana 128K-196K + Computación dedicada

    Nota: ChatGPT Team se renombró a ChatGPT Business en agosto de 2025 — no son dos planes distintos, es el mismo workspace con precio actualizado.

    El asiento Premium —lanzado el 10 de agosto de 2026 como upgrade dentro del mismo workspace de Business— cubre la brecha que existía entre el límite de 5 horas del asiento estándar, que a veces frena a los usuarios más intensivos en picos de trabajo, y un contrato Enterprise con comerciales y un mínimo de ~150 licencias.


    Qué trae de nuevo ChatGPT Business Premium seats

    No estás pagando solo "más mensajes por hora". La diferencia técnica está en el aislamiento de infraestructura y las herramientas de gobierno corporativo.

           [ Workspace Corporativo ]
                      │
      ┌───────────────┼───────────────┐
      ▼               ▼               ▼
    SSO / SCIM    Retención Cero  GPTs Internos
    (Okta, Azure)  (No Training)  (Conectores RBAC)
      │               │               │
      └───────────────┬───────────────┘
                      ▼
          Capa de Cómputo Prioritario
    (Modelos de razonamiento sin throttling)
    

    1. Garantía contractual de no entrenamiento y cumplimiento

    En las cuentas personales de ChatGPT Plus, los datos se usan para entrenar futuros modelos a menos que el usuario desactive el historial manualmente.

    En los asientos de empresa (Business, estándar o Premium, y Enterprise), la cláusula es contractual:

    • Cero entrenamiento con tus prompts, código o archivos subidos.
    • Cumplimiento SOC 2 Tipo II, RGPD y opciones de acuerdos de procesamiento de datos (DPA).
    • Retención de datos configurable por política de la empresa (por ejemplo, purgado automático a los 30 o 90 días).

    2. Capacidad dedicada para modelos de razonamiento y Canvas

    Los modelos con cadena de pensamiento profunda y las interfaces interactivas como Canvas consumen órdenes de magnitud más cómputo que un modelo estándar.

    El asiento estándar de Business tiene un límite de uso de 5 horas que frena a los usuarios más intensivos en picos de trabajo. El asiento Premium lo elimina: otorga 5 veces más capacidad de uso y ejecución prioritaria incluso en horas punta globales.

    3. Directorio interno de Custom GPTs y conectores seguros

    En lugar de que cada miembro cree asistentes aislados, el espacio corporativo permite:

    • Desplegar GPTs internos accesibles solo para correos bajo el dominio de la empresa.
    • Asignar permisos basados en roles (RBAC) a fuentes de conocimiento internas.
    • Evitar que un empleado comparta accidentalmente un asistente con datos confidenciales hacia el exterior.

    4. Aprovisionamiento centralizado (SSO y SCIM)

    Si alguien abandona la compañía, revocar su cuenta de Google Workspace o Microsoft Entra ID (Azure AD) cancela automáticamente su acceso a los chats y documentos del workspace de IA, evitando fugas de información.


    Asientos por suscripción vs. Consumo por API: la comparativa real

    Aquí es donde los equipos de desarrollo cometen el error más costoso: asumir que toda la empresa necesita el mismo tipo de acceso.

    Un desarrollador senior no interactúa con la IA igual que un responsable de marketing o un analista financiero.

    PERFIL DE USUARIO          HERRAMIENTA ÓPTIMA              MODELO DE COSTE
    ─────────────────────────────────────────────────────────────────────────────
    Desarrollador              Claude Code / Cursor / CLI      API / Tokens
    Product Manager / Copy     ChatGPT Business / Premium      Tarifa fija ($20-125/mes)
    Automatizaciones Backend   Scripts propios + SDK           Pago por token puro
    

    Si compras un asiento Premium de $125/mes para un developer que pasa el 90% de su día dentro de la terminal o el editor de código, estás pagando un sobreprecio injustificado. Ese desarrollador obtendrá diez veces más valor con herramientas especializadas conectadas a claves de API, donde solo pagas por los tokens reales que entran y salen.

    Si quieres el desglose técnico de cuándo conviene saltar directo a la API en vez de la interfaz de chat, lo cubrimos con ejemplos reales en GPT-5.6 vía API: guía práctica para developers.

    Esta es la base metodológica que trabajamos en el curso Construye con IA: De la Idea al Producto con Claude y Specs: separar las interfaces genéricas de chat de los flujos de ingeniería guiados por especificaciones y agentes en terminal.


    Cuándo conviene contratar ChatGPT Business Premium seats

    Para tomar una decisión clara sin perder semanas en comités internos, aplica esta matriz:

    ✅ Contrata ChatGPT Business (estándar o Premium) si:

    1. Tienes perfiles no técnicos: Producto, marketing, recursos humanos, soporte y ventas que necesitan una interfaz web lista para usar sin configurar entornos ni gestionar claves de API.
    2. Manejas datos confidenciales: Necesitas un acuerdo DPA y la garantía legal de que la información corporativa no alimentará los modelos públicos de OpenAI.
    3. Quieres centralizar costes: Es más fácil aprobar una factura única consolidada con IVA desglosado que reembolsar 20 notas de gastos individuales de $20 cada mes.

    ❌ NO compres asientos Premium si:

    1. Tu equipo son exclusivamente programadores: Para escribir código, refactorizar arquitecturas y revisar pull requests, herramientas como Claude Code, Cursor o plugins con claves de API dedicadas son infinitamente superiores a una ventana de chat en el navegador.
    2. Tu volumen de uso es esporádico: Si un usuario hace 5 consultas a la semana, pagar $20-$125 al mes por asiento es quemar dinero cuando esa misma interacción en la API costaría menos de 50 céntimos.
    3. Buscas automatizaciones masivas: Para procesar miles de tickets o clasificar bases de datos, el chat web no sirve; necesitas pipelines backend con llamadas estructuradas y, antes de escalarlas, medir cuánto estás gastando realmente en tokens.

    Si quieres analizar patrones de costes y arquitecturas eficientes para equipos que integran agentes en producción, en Dominicode Labs evaluamos mensualmente los números reales de operar con modelos propietarios y locales.


    Cómo hacer la migración en 3 pasos

    Si decides unificar tu equipo bajo un workspace corporativo:

    1. Haz inventario de cuentas personales: Identifica cuántos miembros ya tienen ChatGPT Plus pagado por la empresa y fija una fecha límite para cancelarlas.
    2. Arranca con el asiento estándar de ChatGPT Business: No saltes directo a contratos Enterprise a menos que tengas más de 100-150 usuarios y requisitos estrictos de compliance (SLA dedicado, BAA HIPAA). El asiento estándar a $20-25/usuario/mes ofrece la misma garantía SOC 2 y suele ser más que suficiente; sube a Premium solo para quien tope el límite de 5 horas.
    3. Establece directrices de uso: Define qué perfiles operan en el chat corporativo y qué perfiles técnicos deben usar herramientas de terminal conectadas a la API con presupuestos monitorizados.

    Preguntas frecuentes

    ¿Los planes ChatGPT Business y Enterprise usan mis datos para entrenar a la IA?

    No. A diferencia de las cuentas gratuitas y de ChatGPT Plus, en ChatGPT Business (asiento estándar o Premium) y en Enterprise OpenAI tiene el compromiso explícito de no utilizar las conversaciones, archivos ni código para entrenar sus modelos.

    ¿Cuál es el número mínimo de usuarios para contratar ChatGPT Business?

    ChatGPT Business (el plan que hasta agosto de 2025 se llamaba Team) requiere un mínimo de 2 asientos. Si eres un único profesional independiente, la opción estándar sigue siendo ChatGPT Plus o el consumo directo mediante API.

    ¿Puedo tener usuarios con asientos estándar y usuarios con asientos Premium en el mismo workspace?

    Sí. Dentro de un mismo workspace de Business puedes mezclar, asignar y reasignar asientos estándar y Premium según el rol de cada empleado desde el panel de administración, sin necesidad de separar equipos en distintos workspaces ni saltar a Enterprise.

    ¿Qué diferencia hay entre pagar ChatGPT Plus y usar la API?

    ChatGPT Plus es una tarifa plana con interfaz de chat, navegación web y herramientas visuales. La API es un servicio para desarrolladores con cobro exacto por token consumido, mayor flexibilidad de integración y parámetros técnicos de control (temperatura, function calling, structured outputs).


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • TDD con IA: valida el código autogenerado antes de mergear

    TDD con IA: valida el código autogenerado antes de mergear

    Revisé una Pull Request generada por un asistente de IA hace un par de semanas.

    El autor de la PR estaba fascinado: "Mira qué limpio quedó el algoritmo de descuentos por volumen. La IA lo escribió en 15 segundos".

    El código tenía nombres impecables, comentarios en JSDoc y tipado de TypeScript sin un solo error. Le faltaba lo único que sostiene el TDD con IA: tests.

    Escribí una prueba unitaria pasando una compra con descuento de cliente VIP combinado con un cupón del 100%. El sistema devolvió un saldo negativo donde la tienda terminaba debiéndole dinero al comprador.

    El modelo de IA no tenía mala intención: simplemente no sabía qué reglas de negocio proteger porque nadie se las había formulado como una prueba ejecutable.

    En la era de los asistentes de código, Test-Driven Development (TDD) no está muerto; es más indispensable que nunca. Aquí tienes el flujo exacto para combinar TDD con IA.


    El nuevo ciclo Red-Green-Refactor con Agentes de Código

    El ciclo clásico de TDD se transforma radicalmente cuando tienes un agente a tu lado:

    ┌─────────────────────────────────────────────────────────────┐
    │                 FLUJO TDD POTENCIADO POR IA                 │
    │                                                             │
    │  1. HUMANO (Diseño)  ──>  Escribe el Test Unitario (ROJO)   │
    │                                   │                         │
    │                                   ▼                         │
    │  2. AGENTE (Código)  ──>  Genera la Implementación (VERDE)  │
    │                                   │                         │
    │                                   ▼                         │
    │  3. DÚO (Calidad)    ──>  Refactoriza con Seguridad         │
    └─────────────────────────────────────────────────────────────┘
    

    En lugar de delegar el diseño a ciegas, el desarrollador asume el rol de arquitecto: define el contrato y los casos de borde en una prueba. El agente asume el trabajo pesado de implementar la sintaxis.


    Ejemplo Práctico: Implementando una lógica de negocio paso a paso

    Paso 1: Escribe el test en fallo (Rojo con Vitest)

    Antes de crear el archivo de lógica, defines el comportamiento esperado:

    // src/pricing/discount-calculator.spec.ts
    import { describe, it, expect } from 'vitest';
    import { calculateTotalWithDiscounts } from './discount-calculator';
    
    describe('calculateTotalWithDiscounts', () => {
      it('aplica descuento por volumen del 10% en compras mayores a $100', () => {
        const total = calculateTotalWithDiscounts({ subtotal: 150, isVip: false, couponPercent: 0 });
        expect(total).toBe(135);
      });
    
      it('nunca devuelve un total negativo incluso con cupones acumulados', () => {
        const total = calculateTotalWithDiscounts({ subtotal: 50, isVip: true, couponPercent: 120 });
        expect(total).toBe(0); // Regla de negocio crítica
      });
    });
    

    Al ejecutar bun test, el test falla inmediatamente porque la función ni siquiera existe.

    Paso 2: Pasa el test al agente como contrato ejecutable

    Invocas a tu agente de IA en la terminal con una instrucción cerrada:

    claude "Lee discount-calculator.spec.ts. Crea el archivo discount-calculator.ts con la implementación mínima necesaria para que los tests pasen en verde. Prohibido modificar el archivo de tests."
    

    Paso 3: El agente genera el código para poner el test en verde

    El agente analiza la firma de tipos esperada y las aserciones, generando la lógica requerida:

    // src/pricing/discount-calculator.ts
    export interface PricingOptions {
      subtotal: number;
      isVip: boolean;
      couponPercent: number;
    }
    
    export function calculateTotalWithDiscounts(options: PricingOptions): number {
      const { subtotal, isVip, couponPercent } = options;
      
      let discount = 0;
      if (subtotal > 100) discount += subtotal * 0.10;
      if (isVip) discount += subtotal * 0.05;
      if (couponPercent > 0) discount += subtotal * (couponPercent / 100);
    
      const finalTotal = subtotal - discount;
      return Math.max(0, finalTotal); // Respeta el caso de borde
    }
    

    El agente ejecuta el test runner de forma autónoma y confirma que la suite está en verde.


    Por qué este flujo recorta los bugs que llegan a producción

    1. Elimina la alucinación de requisitos: El modelo no tiene margen para inventar parámetros porque el test ya definió la interfaz y los valores esperados.
    2. Aislamiento de contexto: No necesitas explicar la arquitectura completa de tu empresa; solo entregas el archivo de prueba.
    3. Refactorización sin miedo: Si mañana quieres optimizar el rendimiento del algoritmo, puedes pedirle a la IA que lo refactorice sabiendo que cualquier regresión encenderá una alarma roja de inmediato.

    Que quede claro: esto no lleva los bugs a cero. Ningún flujo lo hace. Lo que hace es mover el error de "se descubre en producción tres semanas después" a "se descubre en el segundo en que el agente ejecuta la suite". Los fallos que se te escapan siguen siendo los casos que no se te ocurrió escribir.

    Para que el ciclo funcione, la suite tiene que correr en milisegundos, no en minutos: aquí tienes cómo montar pruebas unitarias ultrarrápidas con Vitest. Si el agente tarda 90 segundos en saber si acertó, el bucle rojo-verde deja de ser un bucle.

    En el curso de Testing en Angular con Jest y Testing Library enseñamos a estructurar suites de pruebas profesionales para frontend y backend preparadas para integrarse con flujos automatizados de CI/CD.

    Este enfoque de validación es también uno de los pilares centrales de nuestro libro de Spec-Driven Development (SDD).

    Para descargar pipelines de automatización con Vitest y plantillas de pruebas para agentes, visita Dominicode Labs.


    Qué hacer hoy con esto

    Para la próxima función o endpoint que vayas a programar:

    1. No escribas la implementación.
    2. Escribe primero dos tests unitarios en Vitest: uno para el caso feliz y otro para el caso borde más peligroso.
    3. Pásaselo a tu asistente de IA y pídele que escriba la función que los cumpla.

    Comprobarás dos cosas: que el primer diff llega mucho más cerca de lo que querías, y que las rondas de corrección se reducen a una o dos.

    Si además quieres que el agente derive los tests de una especificación en vez de escribirlos tú a mano, ese es el siguiente escalón: TDD y Spec-First aplicados al desarrollo con IA.


    Preguntas frecuentes

    ¿Por qué TDD es especialmente útil al programar con IA?

    Porque un test unitario actúa como una especificación matemática ejecutable. Los modelos de lenguaje responden con muchísima mayor precisión cuando tienen un criterio binario de éxito (el test pasa o falla) que cuando reciben instrucciones en lenguaje natural ambiguo.

    ¿Se debe permitir que la IA modifique los tests unitarios?

    No. Los tests unitarios deben ser diseñados y aprobados por el desarrollador. Si permites que la IA modifique los tests para que "pasen en verde", corres el riesgo de que relaje las aserciones y oculte errores de negocio.

    ¿Qué framework de tests es más rápido para iterar con agentes de IA?

    Vitest es actualmente la opción más recomendada en el ecosistema TypeScript por su velocidad de arranque instantánea, compatibilidad nativa con ESM y excelente integración en terminales CLI.

    ¿Puede la IA escribir también los tests en lugar del desarrollador?

    Puede escribir el andamiaje y los casos evidentes, pero no debe decidir qué se protege. Si el modelo escribe los tests y la implementación, ambos comparten el mismo malentendido y la suite en verde no demuestra nada. El desarrollador define los casos de borde; la IA rellena el resto.

    ¿Cuántos tests hacen falta antes de pasarle la tarea al agente?

    Dos suelen bastar para arrancar: el caso feliz y el caso de borde más caro si falla. Con eso el agente ya tiene una interfaz cerrada y un criterio binario de éxito. Ampliar la cobertura tiene más sentido después, cuando ya sabes por dónde se rompe la implementación real.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • 5 errores fatales al refactorizar código legacy con IA

    5 errores fatales al refactorizar código legacy con IA

    Hace unos meses me contrataron para modernizar un módulo de facturación escrito en 2019.

    Eran cerca de 3.000 líneas de TypeScript sin tipar, callbacks anidados y lógica de negocio repartida entre controladores y servicios. Pensé: "Le paso esto a un modelo de lenguaje moderno y en 10 minutos lo tengo convertido a funciones puras y tipadas".

    Refactorizar código legacy con IA parecía trivial. Le pedí al modelo que reescribiera el archivo y el resultado parecía una obra de arte: código limpio, nombres elegantes y cero warnings en el editor.

    Desplegamos en staging. A las dos horas saltó la primera alerta: los clientes con direcciones fiscales internacionales no podían facturar. El modelo había considerado que una comprobación con == null de un campo antiguo era "código redundante" y la había borrado, rompiendo seis años de retrocompatibilidad silenciosa.

    Si vas a meter agentes de IA en proyectos legacy, aquí tienes los 5 errores fatales que no puedes permitirte.


    Error 1: Alucinación de versiones y APIs incompatibles

    Los modelos de IA fueron entrenados con millones de repositorios que mezclan código de 2020 con código de 2026.

    Cuando le pides a una IA que modifique un proyecto antiguo de Node.js o Angular:

    • Asume que puedes usar métodos modernos de JavaScript (Array.prototype.toSorted(), Object.groupBy()) en entornos que corren en runtimes sin soporte.
    • Intenta importar métodos de librerías modernas (como rxjs/operators reubicados o versiones incompatibles de Axios).
    // ❌ Código sugerido por IA para un proyecto en Node 18
    const groupedOrders = Object.groupBy(orders, (item) => item.status);
    // En runtime: TypeError: Object.groupBy is not a function
    

    Cómo evitarlo: Especifica siempre el target exacto en tus prompts y configuraciones: "Target Node 18 LTS, ECMAScript 2022. Prohibido usar APIs de ECMAScript 2024+".

    El mecanismo de fondo lo desgrané en por qué la IA se inventa cosas: el modelo no miente, completa el patrón más probable. Y en un repo de 2019, el patrón más probable es el de 2026.


    Error 2: Pérdida silenciosa de contratos y el peligro del any encubierto

    El código legacy suele tener tipos implícitos o estructuras heterogéneas. Cuando la IA intenta "limpiar" esos tipos, con frecuencia toma atajos peligrosos:

    // Antes: código legacy feo, pero con un caso borde que lleva años en producción
    function parseUser(data: Record<string, unknown>) {
      return data.legacy_id ?? data.id;
    }
    
    // ❌ Refactor 'limpio' de la IA que destruye ese caso borde
    interface User { id: string; }
    function parseUser(data: User): User {
      return { id: data.id }; // Se perdió el soporte de legacy_id
    }
    

    La IA optimiza para la legibilidad del código presente, no para la historia oculta de los bugs pasados.


    Error 3: Refactorizar sin Tests de Caracterización previos

    El error más destructivo es pedirle a la IA que reescriba código antes de tener una red de seguridad.

    Si el código no tiene tests, no puedes refactorizar con IA. Punto.

    El protocolo correcto exige crear primero Characterization Tests (Tests de Caja Negra):

    // test/billing.characterization.spec.ts
    import { calculateInvoice } from '../src/legacy/billing';
    
    describe('Billing Legacy Characterization Tests', () => {
      it('preserva el comportamiento exacto para clientes extranjeros', () => {
        const input = { amount: 100, country: 'DE', taxExempt: true };
        const result = calculateInvoice(input);
        expect(result).toMatchSnapshot(); // Congela el comportamiento real antes de tocar nada
      });
    });
    

    Si la suite tarda minutos en correr, nadie la ejecutará antes de cada refactor. Aquí tienes cómo dejar los tests unitarios en milisegundos con Vitest: con IA de por medio, la velocidad del test runner deja de ser comodidad y pasa a ser el límite de tu ciclo de trabajo.

    En el curso de Testing en Angular con Jest y Testing Library dedicamos un módulo completo a blindar código histórico mediante tests de regresión antes de aplicar cualquier modernización.


    Error 4: Saturación y degradación de la ventana de contexto

    En repositorios con cientos de archivos interconectados, pasarle al agente archivos gigantes (1.000+ líneas) provoca pérdida de atención (lost in the middle).

    El agente empieza a ignorar imports cruciales o inventa interfaces auxiliares en lugar de reutilizar las del proyecto.

    Regla de oro: No pidas "refactoriza el módulo de pagos". Pide "extrae el cálculo de impuestos de este archivo a una función pura aislada y valida que el test adjunto siga en verde".


    Error 5: Aceptar Diffs extensos sin revisión granular

    Aceptar un diff de 400 líneas generado por IA sin revisarlo línea a línea es una negligencia profesional.

    ┌─────────────────────────────────────────────────────────────┐
    │                 PROTOCOLO DE REFACTOR CON IA                │
    │                                                             │
    │  1. Test de Caracterización (Fija el comportamiento)       │
    │  2. Spec Técnica (Define lo que se puede y no se puede tocar)│
    │  3. Refactorización atómica (Menos de 80 líneas por paso)  │
    │  4. Verificación de Test Runner en verde                   │
    └─────────────────────────────────────────────────────────────┘
    

    Este es exactamente el enfoque que explicamos en el libro de Spec-Driven Development (SDD): tratar las modificaciones de código como contratos medibles con límites inquebrantables.


    Qué hacer hoy con esto

    Si tienes que tocar un módulo legacy esta semana:

    1. No abras la IA todavía.
    2. Escribe tres tests que cubran los casos de uso principales y los casos de borde más raros que conozcas.
    3. Ejecuta los tests y asegúrate de que pasan.
    4. Solo entonces, entrega el código y los tests a tu agente de IA con la instrucción explícita de no romper la suite.

    Para acceder a checklists de refactorización segura y scripts de validación automática para proyectos empresariales, únete a Dominicode Labs.


    Preguntas frecuentes

    ¿Por qué la IA rompe código legacy que antes funcionaba?

    Porque los modelos de lenguaje intentan simplificar lo que parece "código redundante" sin entender los parches históricos o edge cases que ese código resolvía en producción.

    ¿Qué es un Characterization Test y por qué es indispensable?

    Es una prueba automatizada que captura el comportamiento actual del sistema (con sus virtudes y sus defectos) para garantizar que una refactorización no altere inadvertidamente el resultado final.

    ¿Cómo evitar que la IA use versiones incompatibles de librerías?

    Configurando un archivo de contexto claro (como CLAUDE.md o reglas de proyecto) donde se especifique la versión exacta de Node.js, TypeScript y el target ECMAScript soportado.

    ¿Cuánto código conviene pasarle a la IA en cada refactorización?

    Menos de lo que crees. Por debajo de 80 líneas por paso el diff se revisa entero en un vistazo y cualquier regresión se localiza de inmediato. Con diffs de 300 o 400 líneas nadie revisa de verdad: se aprueba por cansancio.

    ¿Se puede refactorizar código legacy con IA sin tests de ningún tipo?

    No de forma responsable. Si no hay tests, el primer trabajo del agente no es refactorizar sino generar tests de caracterización que congelen el comportamiento actual. Solo cuando esa red está en verde tiene sentido tocar la implementación.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Roadmap del developer con IA: de junior a fullstack agentic

    Roadmap del developer con IA: de junior a fullstack agentic

    En 2011 mi trabajo diario como programador consistía en memorizar la sintaxis de jQuery, lidiar con los bugs de Internet Explorer 8 y escribir bucles for a mano.

    Si en aquel momento alguien me hubiera dicho que 15 años después un modelo de lenguaje escribiría un algoritmo completo en dos segundos, habría pensado que la profesión de programador iba a desaparecer de la faz de la tierra.

    La realidad ha sido muy distinta, y por eso el roadmap del developer con IA no se parece en nada al de hace cinco años: programar no ha muerto, pero el acto de mecanografiar código se ha convertido en un commodity.

    El desarrollador que solo sabe traducir un ticket de Jira a líneas de JavaScript está en una posición vulnerable. En cambio, el perfil que está multiplicando su valor en el mercado es el Fullstack Agentic Developer: el profesional que diseña la arquitectura, establece los contratos y dirige un ejército de agentes de IA para construir productos en tiempo récord.

    Aquí tienes la hoja de ruta clara para hacer esa transición.


    La Evolución del Perfil: De Codificador a Director de Agentes

    ┌─────────────────────────────────────────────────────────────┐
    │               EVOLUCIÓN DEL ROL DE DEVELOPER                │
    │                                                             │
    │  AYER (Programador Tradicional)                            │
    │  [Escribir sintaxis] ──> [Recordar APIs] ──> [Debug manual] │
    │                                                             │
    │  HOY & MAÑANA (Agentic Developer)                           │
    │  [Diseñar Specs] ──> [Dirigir Agentes/MCP] ──> [TDD & CI]   │
    └─────────────────────────────────────────────────────────────┘
    

    La ventaja competitiva ya no es recordar de memoria los parámetros de un método de array. Tu valor reside en tu criterio técnico para decidir qué construir, con qué arquitectura y bajo qué límites de seguridad.


    Las 4 Habilidades Indispensables para los Próximos 3 Años

    1. Spec-Driven Development (SDD) y Diseño de Contratos

    Tu capacidad para redactar especificaciones técnicas precisas (spec.md) determinará la calidad del software que generen tus agentes. Si no sabes definir límites de dominio, flujos de datos y escenarios WHEN/THEN, los modelos alucinarán y perderás horas corrigiendo código basura.

    Es la habilidad con más retorno de las cuatro. Si empiezas hoy, empieza por aquí: Spec-Driven Development con agentes de IA.

    2. Fundamentos Sólidos de Arquitectura y Tipado Estricto

    Para evaluar si el código generado por un agente es seguro para producción necesitas dominar:

    • Clean Architecture y separación de capas (Domain, Application, Infrastructure).
    • TypeScript estricto, tipos discriminados y esquemas de validación en runtime con Zod.
    • Patrones de concurrencia y diseño de bases de datos relacionales.

    3. Testing Automatizado y Validación Determinista (TDD)

    La IA es probabilística; el software de producción debe ser determinista. La única forma de desplegar a producción sin miedo es contar con suites de pruebas automatizadas con Vitest o Jest que actúen como un guardián implacable ante cualquier regresión.

    4. Orquestación de Agentes, Herramientas y Protocolos MCP

    Aprender a conectar agentes CLI (como Claude Code) con bases de datos, APIs de terceros y herramientas de terminal mediante el Model Context Protocol (MCP) y la creación de custom skills (SKILL.md).

    El salto de nivel aquí está en dejar de escribir prompts y empezar a construir herramientas: cómo crear skills y subagentes personalizados para que tu flujo diario se ejecute solo.


    La Hoja de Ruta (Roadmap) Paso a Paso

    FASE 1: Fundamentos Modernos
    ├── TypeScript 5+ Estricto (Satisfies, Discriminated Unions, Generics)
    ├── Frameworks Reactivos (Angular Signals / Next.js 16 App Router)
    └── Validación de Esquemas con Zod
    
    FASE 2: Red de Seguridad y Metodología
    ├── TDD con Vitest / Jest (Escribir tests antes de generar código)
    └── Flujo SDD (Spec ➔ Plan ➔ Tasks versionados en Git)
    
    FASE 3: Operaciones Agénticas
    ├── Dominio de agentes CLI (Claude Code, Cursor, terminal tools)
    ├── Creación de Custom Skills y Subagentes especializados
    └── Conexión de servidores MCP para acceso a bases de datos y APIs
    
    FASE 4: Producción y Negocio
    ├── Despliegues Serverless, Edge Functions y bases de datos relacionales
    └── Entrega continua (CI/CD) con validación automática de agentes
    

    Para recorrer este camino con proyectos prácticos de extremo a extremo, en el curso Construye con IA: De la Idea al Producto con Claude Code te guiamos paso a paso en la transición hacia el desarrollo agentico.

    Si buscas una comunidad activa donde compartimos arquitecturas reales, plantillas de agentes y debates técnicos semanales, únete a Dominicode Labs.

    También puedes seguir todos nuestros tutoriales y directos gratuitos en el Canal de YouTube de Dominicode.


    Qué hacer hoy con esto

    Elige un proyecto personal o una tarea pequeña de tu trabajo.

    No intentes escribir cada línea de código a mano por nostalgia, ni tampoco le pidas a la IA que haga todo sin supervisión.

    Asume el rol de arquitecto: redacta la especificación, diseña los tests de validación y delega la implementación sintáctica a tu agente. Ese es el nuevo estándar de la ingeniería de software.


    Preguntas frecuentes

    ¿Los agentes de IA van a sustituir a los desarrolladores juniors?

    No van a sustituir a los desarrolladores, pero sí sustituirán el modelo tradicional de trabajo junior basado exclusivamente en escribir sintaxis básica. Los juniors que adopten metodologías estructuradas (SDD, TDD) y aprendan a orquestar agentes avanzarán mucho más rápido hacia niveles senior.

    ¿Por qué aprender TypeScript y testing si la IA puede escribir el código?

    Porque la IA comete errores sutiles y alucinaciones. Sin conocimientos profundos de TypeScript y testing automatizado, no tendrás el criterio técnico necesario para auditar el código generado ni detectar fallos antes de que lleguen a producción.

    ¿Qué es un Servidor MCP (Model Context Protocol)?

    Es un estándar abierto desarrollado por Anthropic que permite a los asistentes de IA conectarse de forma segura con herramientas locales, bases de datos (Postgres, SQLite), repositorios Git y APIs de servicios externos.

    ¿Cuánto se tarda en recorrer este roadmap?

    Depende del punto de partida, pero las cuatro fases no son secuenciales en el tiempo: puedes empezar a escribir specs y tests la semana que viene mientras sigues consolidando fundamentos. Lo que no funciona es saltar a la Fase 3 sin las dos primeras, porque sin criterio técnico no puedes auditar lo que el agente produce.

    ¿Hace falta ser senior para trabajar con agentes de código?

    No, pero sí hace falta saber leer código mejor de lo que lo escribes. Un junior que domina testing y sabe redactar una especificación clara saca más partido a un agente que un senior que le pide código a ciegas y acepta el diff sin revisarlo.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Búsqueda Híbrida y Embeddings en Supabase: Cómo construir un sistema RAG en producción

    Búsqueda Híbrida y Embeddings en Supabase: Cómo construir un sistema RAG en producción

    Hace poco estaba revisando el motor de búsqueda interna de una plataforma técnica. El equipo había montado un sistema de Generación Aumentada por Recuperación (RAG) impecable basado únicamente en embeddings vectoriales almacenados en PostgreSQL.

    Si buscabas "¿Cómo corregir errores de autenticación?", el sistema devolvía los artículos de documentación exactos. La búsqueda semántica funcionaba a las mil maravillas.

    Pero el desastre ocurrió cuando un usuario buscó el código de error numérico exacto: ERR_401_EXPIRED_TOKEN.

    El motor de búsqueda vectorial devolvió artículos sobre contraseñas olvidadas y verificación en dos pasos, pero omitió el artículo que contenía la constante exacta ERR_401_EXPIRED_TOKEN.

    ¿Por qué ocurrió esto? Porque las búsquedas vectoriales entienden el significado de las frases, pero son pésimas encontrando términos exactos, códigos de producto, nombres de variables o números de serie.

    La solución definitiva para llevar sistemas RAG a producción se llama Búsqueda Híbrida (Hybrid Search).

    Por qué la Búsqueda Vectorial Pura Falla en Producción

    Los modelos de embeddings transforman fragmentos de texto en vectores numéricos dentro de un espacio multidimensional.

    • Búsqueda Vectorial (Cosimilitud / Distancia Euclídea): Excelente para capturar conceptos relacionados. Si buscas "vehículo ecológico", encontrará documentos sobre "coches eléctricos".
    • Búsqueda por Texto Completo (Full-Text Search / BM25): Excelente para palabras clave exactas. Si buscas "SKU-9942", encontrará la fila que contiene esa cadena sin intentar interpretar su significado.

    Un sistema RAG profesional necesita combinar ambas estrategias.

                      ┌──────────────────────────────────────────┐
                      │ Consulta del Usuario: "ERR_401 token"    │
                      └────────────────────┬─────────────────────┘
                                           │
                ┌──────────────────────────┴──────────────────────────┐
                ▼                                                     ▼
    ┌──────────────────────────┐                               ┌──────────────────────────┐
    │ Búsqueda Vectorial       │                               │ Búsqueda Texto Completo  │
    │ (pgvector / HNSW)        │                               │ (tsvector / BM25)        │
    └───────────┬──────────────┘                               └───────────┬──────────────┘
                │                                                          │
                └──────────────────────────┬───────────────────────────────┘
                                           ▼
                      ┌──────────────────────────────────────────┐
                      │ Fusion de Rangos Recíprocos (RRF en SQL) │
                      └────────────────────┬─────────────────────┘
                                           ▼
                      ┌──────────────────────────────────────────┐
                      │ Contexto Ideal para el Modelo LLM        │
                      └──────────────────────────────────────────┘
    

    Implementación de Búsqueda Híbrida en Supabase & PostgreSQL

    Supabase incluye la extensión pgvector sobre PostgreSQL nativo. Podemos implementar Búsqueda Híbrida directamente en la base de datos con una función SQL almacenada que ejecute Reciprocal Rank Fusion (RRF).

    1. Habilitar la extensión y crear la tabla con vector y tsvector

    -- Habilitar la extensión pgvector
    CREATE EXTENSION IF NOT EXISTS vector;
    
    -- Tabla de documentos para RAG
    CREATE TABLE documentos (
      id BIGSERIAL PRIMARY KEY,
      contenido TEXT NOT NULL,
      embedding VECTOR(1536), -- Dimensión para text-embedding-3-small de OpenAI
      fts TSVECTOR GENERATED ALWAYS AS (to_tsvector('spanish', contenido)) STORED
    );
    
    -- Crear índice vectorial HNSW y de texto completo GIN
    CREATE INDEX idx_documentos_embedding ON documentos USING hnsw (embedding vector_cosine_ops);
    CREATE INDEX idx_documentos_fts ON documentos USING gin (fts);
    

    2. Función Almacenada RPC de Fusión Híbrida (RRF)

    CREATE OR REPLACE FUNCTION busqueda_hibrida_documentos(
      query_text TEXT,
      query_embedding VECTOR(1536),
      match_count INT DEFAULT 5,
      rrf_k INT DEFAULT 60
    )
    RETURNS TABLE (id BIGINT, contenido TEXT, score FLOAT)
    LANGUAGE sql AS $$
    WITH full_text AS (
      SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank_cd(fts, websearch_to_tsquery('spanish', query_text)) DESC) AS rank
      FROM documentos
      WHERE fts @@ websearch_to_tsquery('spanish', query_text)
      LIMIT 20
    ),
    vector_search AS (
      SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> query_embedding) AS rank
      FROM documentos
      ORDER BY embedding <=> query_embedding
      LIMIT 20
    )
    SELECT 
      d.id, 
      d.contenido,
      COALESCE(1.0 / (rrf_k + ft.rank), 0.0) + COALESCE(1.0 / (rrf_k + vs.rank), 0.0) AS score
    FROM documentos d
    LEFT JOIN full_text ft ON d.id = ft.id
    LEFT JOIN vector_search vs ON d.id = vs.id
    WHERE ft.id IS NOT NULL OR vs.id IS NOT NULL
    ORDER BY score DESC
    LIMIT match_count;
    $$;
    

    3. Invocación desde TypeScript

    import { createClient } from '@supabase/supabase-js';
    
    const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
    
    async function buscarContextoRAG(query: string, embedding: number[]) {
      const { data, error } = await supabase.rpc('busqueda_hibrida_documentos', {
        query_text: query,
        query_embedding: embedding,
        match_count: 5,
      });
    
      if (error) throw new Error(`Fallo en la búsqueda RAG: ${error.message}`);
      return data;
    }
    

    Al aplicar programación defensiva en TypeScript, aseguras que los vectores devueltos cumplan estrictamente con las dimensiones de tu modelo de embedding antes de invocar la consulta RPC.

    Optimización de RAG y Control de Tokens

    1. Aislamiento de Grafos: Combina la búsqueda híbrida con principios de graph engineering para que la base de datos devuelva únicamente los nodos de información directamente relacionados con la consulta.
    2. Presupuesto de Tokens: Filtrar los 5 mejores resultados consolidados por la función RRF reduce drásticamente el volumen de datos enviado en la ventana de contexto. Como analizamos en nuestro post sobre el coste de subagentes al cambiar de modelo, reducir el exceso de contexto optimiza los tiempos de respuesta y ahorra costes en tu API de IA.

    La Búsqueda Híbrida combina lo mejor de dos mundos: la comprensión conceptual de los embeddings y la precisión milimétrica del texto completo.

    Si quieres dominar el desarrollo de sistemas RAG y arquitecturas backend avanzadas con PostgreSQL y Supabase, explora los Cursos de Dominicode. Y si quieres construir productos reales de IA junto a otros ingenieros senior, te esperamos en Dominicode Labs.

    Preguntas frecuentes

    ¿Por qué usar pgvector en Supabase en lugar de una base de datos vectorial dedicada como Pinecone o Chroma?

    Utilizar pgvector en PostgreSQL/Supabase te permite mantener todos tus datos relacionales, usuarios y vectores en la misma base de datos. Esto elimina la necesidad de sincronizar dos bases de datos distintas, reduce los costes de infraestructura y permite hacer JOINs nativos entre tablas relacionales y embeddings.

    ¿Qué es el valor rrf_k en la función Reciprocal Rank Fusion?

    rrf_k es una constante de suavizado (por defecto 60) utilizada en el algoritmo Reciprocal Rank Fusion. Sirve para evitar que un documento clasificado en la posición #1 en un método domine desproporcionadamente sobre un documento que quedó en posición #2 en ambos métodos.

    ¿Qué dimensión debe tener la columna VECTOR en PostgreSQL?

    La dimensión depende exclusivamente del modelo de embeddings que utilices. Por ejemplo, text-embedding-3-small de OpenAI usa 1536 dimensiones, text-embedding-3-large usa 3072 dimensiones, y modelos locales ligeros como all-MiniLM-L6-v2 usan 384 dimensiones.

    ¿Cómo afecta el índice HNSW al rendimiento de inserción en Supabase?

    El índice HNSW (Hierarchical Navigable Small World) ofrece consultas de búsqueda vectorial ultrarrápidas en tiempo de lectura, a costa de un ligero aumento en el tiempo de inserción de filas. Para aplicaciones con muchas lecturas y pocas escrituras masivas, HNSW es la opción óptima frente al índice IVFFlat tradicional.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Los tres niveles de Spec-Driven Development (y por qué casi todos estamos en el primero)

    Los tres niveles de Spec-Driven Development (y por qué casi todos estamos en el primero)

    Hace unas semanas abrí un repo mío de febrero. Fui a la carpeta specs/. Ahí seguía todo: spec.md, plan.md, tasks.md.

    El spec.md describía tres endpoints. El código tenía once.

    La spec no estaba mal escrita. Estaba muerta. Cinco meses sin tocarla mientras el código crecía por su cuenta. Y lo peor es que todo funcionaba: los tests pasaban, el deploy iba, nadie se enteró de nada.

    Yo llevaba meses diciendo que hacía SDD. No lo hacía. Hay tres niveles de Spec-Driven Development y yo estaba en el primero convencido de estar en el segundo.

    Esto no va de qué es SDD. Va de diagnóstico: en qué nivel estás de verdad y a cuál te conviene subir. Que no siempre es el de arriba.

    El test de los 30 segundos: borra la carpeta specs/

    Antes de leer nada más, hazte esta pregunta.

    Si borras la carpeta specs/ de tu proyecto ahora mismo, ¿se rompe algo del pipeline?

    Si la respuesta es no —si el build sigue verde, los tests pasan y el deploy sale— entonces tu spec es un documento, no un artefacto de ingeniería. Eres spec-first. Da igual lo bien escrita que esté. Da igual que tengas constitution.md y siete plantillas.

    Nada que se pueda borrar sin consecuencias forma parte del sistema.

    Y ojo, que esto no es un insulto. Spec-first es un nivel legítimo y para la mitad de tus proyectos es exactamente el que necesitas. El problema no es estar ahí. El problema es estar ahí creyendo que estás dos escalones más arriba, y por tanto confiando en garantías que no tienes.

    Qué son los tres niveles de rigor de especificación

    Deepak Babu Piskala publicó el 30 de enero de 2026 el preprint Spec-Driven Development: From Code to Contract in the Age of AI Coding Assistants (arXiv:2602.00180, cs.SE). Es el primer sitio donde he visto puesto por escrito, con nombres, lo que la mayoría hacemos por intuición.

    El paper define tres niveles de rigor de especificación: spec-first, spec-anchored y spec-as-source. Lo único que cambia entre ellos es cuánta autoridad tiene la spec sobre el código — el eje de su primera figura se llama literalmente increasing specification authority.

    No son fases de madurez que haya que recorrer. Son opciones, y cada una tiene un coste.

    Nivel La spec es… ¿Quién escribe el código? ¿Qué pasa con el drift? Es tu nivel si…
    Spec-first Un briefing inicial Tú o el agente al arrancar; después, solo tú Ocurre en silencio, nadie se entera Prototipos, features puntuales, exploración
    Spec-anchored Un contrato vivo Tú, con la spec como referencia obligatoria Lo detecta el CI si lo automatizas; si no, rot La mayoría de sistemas en producción
    Spec-as-source El único artefacto que un humano edita Nadie. Se genera No existe por construcción Automoción, embebidos, dominios certificados

    Spec-first: la spec guía el arranque

    Definición del paper: la especificación se escribe antes de programar para guiar la implementación inicial.

    Ahí está la palabra clave: inicial. La spec hace su trabajo en el minuto cero y después su vida útil se acaba. El agente genera el código, tú lo revisas, y desde ese momento el código es la única fuente de verdad.

    El paper es explícito: spec-first funciona en desarrollo inicial de features con asistentes de IA, y en prototipos y features de usar y tirar.

    Es donde está casi todo el mundo que usa Claude Code o Cursor con un spec.md delante. Y para mucho de lo que hacemos, está perfecto. Escribes la spec, el agente construye, tú corriges, sigues adelante. Es el flujo que enseño en el curso de Construye con IA para ir de idea a producto sin caos.

    El fallo no es usar spec-first. El fallo es usar spec-first en un sistema que va a vivir tres años y con cuatro personas tocándolo.

    Spec-anchored: la spec vive con el código

    Definición del paper: la especificación se mantiene junto al código durante todo el ciclo de vida del sistema.

    Y aquí viene la frase que a mí me hizo replantearme cosas. El paper llama a spec-anchored el punto óptimo para la mayoría de sistemas en producción, porque te da los beneficios de documentación clara y requisitos verificables sin exigir que el código se genere entero.

    Traducido: tienes las garantías sin renunciar a escribir código.

    El riesgo de este nivel tiene nombre propio en el paper: specification rot. La podredumbre de la especificación, que aparece cuando los equipos no actualizan las specs a medida que el código cambia. Exactamente lo que le pasó a mi repo de febrero.

    Y la solución que propone el paper no es disciplina. Es automatización: los tests imponen la alineación entre spec y código, con escenarios BDD funcionando como tests automáticos que corren en cada commit.

    Esa es la diferencia real entre los dos primeros niveles. No es cuánto cuidas la spec. Es si la alineación depende de tu voluntad o de un check que falla el build.

    Spec-as-source: la spec es el código

    Definición del paper: la especificación es el único artefacto que los humanos editan directamente. El código se genera enteramente a partir de la spec.

    La regla operativa que da el paper es tajante: si quieres cambiar la funcionalidad, cambias la spec y regeneras. Nunca editas el código generado directamente.

    El drift desaparece. No se gestiona, no se detecta: no puede existir. Como el código se regenera en lugar de editarse a mano, spec y código están siempre alineados por construcción.

    Suena a futuro lejano. No lo es, y esto es lo que más me sorprendió del paper.

    Spec-as-source ya existe. Y una parte ya la haces

    Hay una idea instalada de que spec-as-source es hacia dónde vamos cuando los LLM sean lo bastante buenos.

    Falso. El paper lo desmonta con una frase: spec-as-source ya es práctica estándar en dominios con generación de código bien definida, y pone dos ejemplos. Uno es generar código embebido certificado desde modelos de Simulink. En la capa de control, el ingeniero rara vez escribe a mano el C que acaba en la ECU: escribe el modelo, y el generador produce el C.

    El otro ejemplo del paper es generar los stubs de servidor desde un openapi.yaml.

    Eso también es spec-as-source. Y llevas años haciéndolo sin llamarlo así: editas el contrato, regeneras, nunca tocas a mano lo generado. Es exactamente la regla del nivel tres.

    La diferencia es qué generas. Ahí generas el andamio. Nadie ha certificado un generador para la lógica de negocio.

    Entonces, ¿por qué no puedes hacer lo mismo con la lógica de tu app de Next.js?

    Porque, según el paper, spec-as-source solo es práctico hoy en dominios donde esa confianza está establecida. El paper no entra en por qué, pero la respuesta no está en el modelo: está en el toolchain. Generadores cualificados bajo norma, trazabilidad auditable y décadas de proceso detrás.

    Tu lógica de negocio no tiene eso. No porque la IA no dé la talla, sino porque no hay un organismo que responda cuando el código generado la líe en producción.

    Así que spec-as-source completo no es tu nivel hoy si haces web. Y no pasa nada. Perseguirlo con las herramientas actuales es la forma más rápida de acabar con el peor de los dos mundos: código generado que nadie entiende y una spec que tampoco es la fuente real de verdad.

    Qué cuesta subir de spec-first a spec-anchored

    Este es el salto que sí te interesa. Y es más barato de lo que parece, porque no va de escribir más documentación. Va de cerrar el bucle.

    El paper describe un flujo de cuatro fases: Specify → Plan → Implement → Validate.

    La mayoría hacemos tres. Especificamos, planificamos, implementamos, y en cuanto la feature funciona nos vamos a la siguiente. Validate se queda sin hacer. Y para mí, Validate es la fase que convierte spec-first en spec-anchored.

    En un proyecto normal de TypeScript, el salto son tres movimientos concretos.

    Uno: los criterios de aceptación de la spec dejan de ser prosa y pasan a ser tests. Cada comportamiento descrito en la spec tiene un test que lo verifica. Si la spec dice que un usuario sin permisos recibe un 403, hay un test que lo comprueba. Si no puedes escribir ese test, tu spec no era verificable — que es uno de los motivos por los que una spec falla con un agente de IA aunque esté impecablemente redactada.

    Dos: los contratos se validan contra la implementación. El paper lista aquí las herramientas por categoría: OpenAPI y Swagger, GraphQL SDL o Protocol Buffers para las specs de API, y Pact o Specmatic para contract testing. Tu openapi.yaml deja de ser documentación y pasa a ser el árbitro. Si el backend devuelve un campo que el contrato no declara, falla.

    Tres: eso corre en CI y rompe el build.

    # .github/workflows/ci.yml
    on: [push, pull_request]
    
    jobs:
      spec-alignment:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v5
          - run: npm ci
          - run: npm run test:contract     # implementación vs openapi.yaml
          - run: npm run test:acceptance   # escenarios derivados de la spec
    

    Ese bloque es la frontera entre los dos niveles. El día que alguien añade un endpoint sin tocar el contrato, el build se pone rojo antes de que llegue a review. La alineación deja de depender de que te acuerdes.

    Sobre el retorno de esto, el paper documenta un caso de estudio de microservicios API-first con OpenAPI y Specmatic con una reducción del 75% en el tiempo de ciclo de integración. Es un caso concreto del paper, no una media del sector, y conviene leerlo como lo que es: una señal de dónde está el valor, no una promesa.

    La parte incómoda es que este salto se apoya en tener una cultura de testing decente. Si tu suite de tests es frágil, spec-anchored no te va a salvar: vas a tener dos cosas rotas en vez de una. Arregla primero los tests — y si tu stack es Angular, esa base la trabajo entera con Jest y Testing Library en el curso de Testing en Angular, que es la misma disciplina en cualquier proyecto de TypeScript.

    El fallo que sobrevive a todos los niveles

    Hay una trampa que no se arregla subiendo de nivel, y el paper la nombra sin anestesia: los tests de spec que pasan no garantizan software correcto si las specs están mal.

    Falsa confianza. Para mí es el fallo más caro de los cuatro que lista el paper —junto a la sobre-especificación, la podredumbre de la spec y convertir las specs en burocracia— porque los otros tres se notan y este no.

    Tienes el CI verde, el contrato validado, los escenarios BDD pasando. Y estás construyendo con enorme rigor exactamente lo que el negocio no pidió.

    Por eso el paper reformula el rol del developer: pasamos de programar a mano a orquestar especificaciones, revisar salidas de IA y centrarnos en el diseño de alto nivel. Si tu spec es mala, subir de nivel solo automatiza el error y le pone un sello de calidad encima.

    La regla de oro del Spec-Driven Development: usa el mínimo rigor

    El paper cierra con un marco de decisión que merece la pena tener a mano. SDD aporta valor cuando hay asistencia de IA de por medio, requisitos complejos, sistemas de vida larga, varios mantenedores, generación de código viable o integración complicada. Y hay que saltárselo en prototipos desechables, trabajo en solitario de vida corta, código exploratorio o CRUD simple con requisitos evidentes.

    Que es básicamente lo que ya defendí en su día al hablar de cuándo no usar Spec-Driven Development, y me alegra ver que el paper llega a la misma conclusión.

    Porque el principio rector que se lleva el paper, y el que yo me he apuntado, es este:

    Usa el mínimo nivel de rigor de especificación que elimine la ambigüedad en tu contexto.

    Subir de nivel no es mejor. Es más caro. Spec-anchored en un script que vas a borrar en dos semanas no es madurez profesional, es ceremonia. Y spec-first en la plataforma que factura no es agilidad, es deuda con fecha de vencimiento.

    Lo que puedes hacer hoy, en diez minutos: coge tu proyecto más importante y aplícale el test de los 30 segundos. Borra mentalmente la carpeta specs/. Si no se rompe nada y ese proyecto va a vivir más de seis meses con más de una persona tocándolo, ya sabes cuál es tu siguiente PR. No es escribir más spec. Es añadir el check que la vuelve obligatoria.

    Si quieres el método completo —cómo redactar specs que un agente ejecuta sin inventarse la mitad y cómo mantenerlas vivas sin que se conviertan en burocracia— lo desarrollo entero en el libro de Spec-Driven Development. Y en Dominicode Labs tienes los proyectos donde esto está montado tal cual lo uso en producción, con el CI incluido.

    Preguntas frecuentes

    ¿Cuáles son los tres niveles de Spec-Driven Development?

    Spec-first, spec-anchored y spec-as-source. En spec-first la spec guía la implementación inicial y después puede quedar obsoleta. En spec-anchored la spec se mantiene junto al código durante todo el ciclo de vida y hay tests que verifican la alineación. En spec-as-source la spec es el único artefacto que edita un humano y el código se genera entero a partir de ella. Los definió Deepak Babu Piskala en el preprint arXiv:2602.00180.

    ¿Spec-first significa que lo estoy haciendo mal?

    No. Spec-first es un nivel legítimo y el paper lo recomienda explícitamente para prototipos, features de usar y tirar y desarrollo inicial con asistentes de IA. El problema aparece cuando aplicas spec-first a un sistema de vida larga y asumes garantías de trazabilidad que ese nivel no te da.

    ¿Cómo sé si mi spec está viva o solo bien escrita?

    Comprueba si algo del pipeline depende de ella. Si puedes borrar la spec y el build sigue verde, la spec es documentación. Una spec viva rompe algo cuando desaparece o cuando el código se desvía de ella, porque hay tests o validaciones de contrato que la usan como referencia.

    ¿Necesito Cucumber o BDD para ser spec-anchored?

    No obligatoriamente. El paper menciona los frameworks BDD (Cucumber, SpecFlow, Behave) como la forma habitual de que los escenarios se conviertan en tests automáticos, pero lo que define el nivel es que exista una verificación automática de la alineación, no la herramienta concreta. Con contract testing sobre OpenAPI usando Pact o Specmatic ya cumples el requisito.

    ¿Spec-as-source llegará algún día al desarrollo web?

    En parte ya llegó: generar los stubs de servidor desde un openapi.yaml es el ejemplo de spec-as-source que el propio paper pone, y es desarrollo web. Lo que no ha llegado es la lógica de negocio, y el cuello de botella no es la capacidad del modelo sino la confianza en el generador. En automoción y embebidos spec-as-source ya es práctica estándar desde hace años con Simulink o SCADE, y una de las razones es que esos generadores están cualificados bajo norma y auditados.

    Si mis tests de spec pasan, ¿está el software correcto?

    No. El paper lo advierte de forma directa: que los tests de spec pasen no garantiza que el software sea correcto si las propias specs son incorrectas. Verificar que cumples la spec y validar que la spec era la adecuada son dos problemas distintos, y el segundo sigue siendo humano.

    ¿Merece la pena spec-anchored si trabajo solo?

    Depende de la vida del proyecto, no del tamaño del equipo. El paper desaconseja SDD en trabajo en solitario de vida corta, pero si eres solo tú manteniendo algo durante años, el "otro mantenedor" eres tú dentro de ocho meses sin recordar nada. Ahí el contrato en CI te protege igual que protegería a un equipo.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.