< BACK Ingeniería de Prompts para Código en Producción: Lecciones Difíciles -- ilustración de arte lineal

Ingeniería de prompts para código en producción: lecciones difíciles

Eran las 11:43pm de un jueves y estaba mirando 340 líneas de código React que GPT-4 había generado con total confianza. Limpio. Bien comentado. Completamente roto en producción. El hook personalizado estaba manejando el estado de una manera que causaba bucles silenciosos de re-renderizado, el tipo que no lanza errores, simplemente se comen silenciosamente tu rendimiento hasta que un cliente te llama el viernes por la mañana preguntando por qué su página de checkout tarda nueve segundos en cargar.

Esa noche me enseñó más sobre ingeniería de prompts que cualquier tutorial de YouTube o hilo de Twitter jamás lo ha hecho. Y he tenido muchas de esas noches desde entonces.

Llevo nueve años construyendo en la web. En Seahawk Media hemos implementado más de 12,000 sitios, WordPress, builds headless, aplicaciones React personalizadas, tiendas WooCommerce manejando volumen de transacciones serio. Los asistentes de codificación con IA entraron adecuadamente en mi flujo de trabajo alrededor de principios de 2023, y he oscilado entre pensar que son milagrosos y querer tirar mi laptop al Támesis.

Aquí está lo que realmente he aprendido. De la manera difícil.

---

El Modelo No Conoce Tu Codebase. Tienes Que Decirle.

Suena obvio. No lo es, no en la práctica.

El error más grande que veo cometer a los desarrolladores, incluyéndome a mí mismo durante los primeros seis meses, es tratar un LLM como un ingeniero senior que ya ha leído todo tu código. Preguntas "escribe una función para manejar la autenticación del usuario" y escribe algo técnicamente correcto en el vacío. Pero tu proyecto usa Supabase, no Firebase. Tus tokens viven en cookies httpOnly, no en localStorage. Tu formato de error es { status, message, data }, no lo que el modelo asumió por defecto.

El modelo no está equivocado. Solo no te conoce.

Dale un Preámbulo del Proyecto, Cada Maldita Vez

Ahora comienzo cada sesión de código significativa con lo que llamo un "bloque de contexto." Toma alrededor de 90 segundos escribirlo. Se ve algo como:

  • Stack: Next.js 14 (App Router), TypeScript, Supabase, Tailwind CSS 3.4
  • State: Zustand, sin Redux en ningún lado
  • Auth: Supabase Auth con cookies httpOnly vía middleware
  • Error shape: { success: boolean, error?: string, data?: unknown }
  • Convención de estilos: utility-first, sin archivos CSS personalizados a menos que sea absolutamente necesario

Pega eso antes de cualquier solicitud no trivial. Lo hago en Cursor manteniendo un archivo _context.md en la raíz del proyecto. Dos pulsaciones de tecla para pegar. La calidad del output salta notablemente, menos suposiciones, menos cosas que tengo que arrancar.

---

La especificidad es todo el juego

Allá por 2022, antes de usar IA intensivamente, un cliente me pasó un brief que literalmente tenía dos oraciones: "Construye un sistema de reservas. Hazlo bien." Pasamos tres semanas discutiendo el alcance. Esa experiencia se me quedó grabada, y moldea directamente cómo escribo prompts ahora.

Prompt vago → código vago. Siempre.

"Escribe una función que obtenga órdenes" te dará algo. "Escribe una función asincrónica de TypeScript llamada fetchOrdersByUser que acepte un userId: string, consulte la tabla orders en Supabase donde user_id coincida y status no sea cancelled, ordene resultados por created_at descendente, y retorne Order[] o lance un error tipado" te dará algo que realmente puedes desplegar.

La diferencia no es la capacidad del modelo. Es la especificidad del prompt.

Qué incluir en un prompt de código

  1. Nombre de la función y firma, no dejes que el modelo invente convenciones de nombres
  2. Tipos de entrada y tipos de salida, genéricos de TypeScript si es relevante
  3. La fuente de datos, qué tabla, qué endpoint de API, qué capa de caché
  4. Casos extremos que ya conoces, "maneja el caso donde el array está vacío"
  5. Qué NO hacer: "no uses useEffect para esto, usa una server action"

Ese último punto importa más de lo que la gente se da cuenta. Decirle al modelo qué evitar ahorra un tiempo enorme. He empezado a mantener una nota pequeña de "anti-patrones" por proyecto, cosas como "sin componentes de cliente a menos que la interacción del usuario lo requiera", e incluyo líneas relevantes en los prompts de ese proyecto.

---

Encadena Tus Prompts. No Pidas Todo de Una Vez.

Seahawk tuvo un cliente fintech a finales de 2023, no diré quién, donde estábamos construyendo un flujo KYC de múltiples pasos. Cosas complejas. Carga de documentos, integración de verificación de vida, polling de estado. Cometí el error al principio de pedirle a GPT-4 que "construyera el componente de flujo KYC completo". Produjo 600 líneas de basura de aspecto heroico. Lógica enredada, preocupaciones mezcladas, sin separación real entre estado de UI y lógica de negocio.

Así que lo descarté y comencé de nuevo con una cadena.

Primer prompt: "Diseña la máquina de estados para un flujo KYC de 4 pasos. Pasos: identidad, carga de documento, verificación de presencia, revisión. Dame solo el tipo de estado y las transiciones, sin UI."

Segundo prompt: "Dado este estado máquina [pegar], escribe el store de Zustand."

Tercer prompt: "Dado este store [pegar], escribe el componente StepIdentity. Solo este paso."

El output del enfoque encadenado fue usable. No perfecto, aún reescribí alrededor del 30%, pero usable. El enfoque monolítico no me dio nada.

La propia orientación de Anthropic sobre prompting habla de dividir tareas complejas en subtareas, y honestamente, esto se alinea exactamente con lo que encontré por prueba y error. Divide el problema antes de dividir tu base de código.

---

Haz que Discuta Consigo Mismo

Aquí hay uno en el que me topé completamente por accidente. Estaba revisando una función utilidad generada y en lugar de simplemente ejecutarla, añadí un prompt de seguimiento: "¿Cuáles son los posibles bugs o casos límite en el código que acabas de escribir?"

El modelo encontró tres problemas que no había considerado. Uno de ellos fue un problema genuino, una condición de carrera en un loop asincrónico que hubiera sido una pesadilla para debugguear en producción.

Ahora hago esto de forma rutinaria. Escribo el código, luego le pido que critique el código. Luego le pido que arregle la crítica. Se siente levemente absurdo, pedirle al modelo que revise su propio trabajo, pero consistentemente saca a la luz cosas que solo habría atrapado después de una sesión de debugging dolorosa.

Puedes llevar esto más lejos. Después de obtener una función funcional, intenta: "Reescribe esto enfocándote en rendimiento" o "¿Cómo se comportaría esto bajo alta concurrencia?" Las respuestas no siempre son aplicables, pero aproximadamente el 40% de las veces sacan a la luz algo que vale la pena actuar.

---

El marco "Rol + Restricción"

Hay un patrón de prompts que uso constantemente ahora y que desearía haber descubierto en el primer año. Va así: "Eres un [tipo específico de ingeniero]. Tu restricción es [regla inamovible]. Ahora [tarea]."

Ejemplo: "Eres un ingeniero backend que se preocupa profundamente por la eficiencia de consultas de base de datos. Tu restricción es que no puedes obtener más de lo que se necesita para este render, sin over-fetching. Escribe una consulta Supabase para el dashboard de admin que devuelva el conteo de órdenes, el ingreso total, y las cinco órdenes más recientes."

Ese encuadre hace dos cosas. Alinea la "persona" del modelo con lo que realmente necesito. Y la restricción actúa como barrera de seguridad, algo que el modelo explícitamente verifica contra sí mismo mientras genera.

Las mejores prácticas de prompting de OpenAI describen una idea similar sobre darle al modelo una personalidad con instrucciones explícitas. Vale la pena leer si no lo has hecho, aunque diría que el aspecto de restricción está subestimado en su documentación.

Compara el output de ese prompt enmarcado con "escribe una consulta de Supabase para el dashboard administrativo." Noche y día. De verdad.

---

Cuándo dejar de hacer prompts y simplemente escribir el código

Esta es la parte que nadie quiere decir en voz alta.

Las herramientas de IA para código son brillantes en: boilerplate, operaciones CRUD, funciones utilitarias, escribir tests para código que ya escribiste, traducir entre formatos (esquema JSON a tipo TypeScript, SQL a consulta Supabase, etc.), y primeros borradores de cosas que modificarás mucho.

Son genuinamente malas en: entender la arquitectura real de tu app, saber qué trade-off importa para tu escala específica, escribir cualquier cosa que toque una interacción stateful complicada sin mucha guía, y cualquier cosa donde la especificación es fundamentalmente ambigua.

Tengo una regla personal ahora: si envié más de cuatro prompts de seguimiento intentando que un pedazo de código funcione, cierro el chat y lo escribo yo mismo. El costo de tiempo del prompt debugging puede exceder el costo de tiempo de solo escribirlo, especialmente para cualquier cosa menor a unos 50 líneas.

La Encuesta de Desarrolladores de Stack Overflow 2024 encontró que el 76% de los desarrolladores están usando o planeando usar herramientas de IA, pero los mismos datos mostraron confianza relativamente baja en la precisión. Esa brecha entre uso y confianza es exactamente dónde vive la buena ingeniería de prompts.

---

Versioná Tus Prompts Como Versionás Tu Código

El año pasado comencé a mantener una carpeta prompts/ en proyectos donde la asistencia de IA es significativa. Archivos Markdown. Uno por cada área de feature importante. Cuando un prompt produce output particularmente bueno, lo guardo. Cuando encuentro una versión mejor, actualizo el archivo.

Suena obsesivo. Me ha ahorrado probablemente seis horas en el último proyecto grande solo, una construcción WooCommerce headless para un minorista que se mudaba desde Shopify. Reusé un prompt de consulta de productos (con ediciones menores) en cuatro componentes diferentes en lugar de re-ingeniering el contexto desde cero cada vez.

Contrólalo con Git. En serio. La calidad de los prompts es reproducible si los tratas como artefactos en lugar de inputs desechables. Las plantillas de prompts de LangChain formalizan esta idea en un contexto de framework, pero no necesitas ningún framework, una carpeta de archivos Markdown es suficiente para la mayoría de flujos de trabajo de agencias.

---

FAQ

¿La ingeniería de prompts es realmente una habilidad transferible o solo depende del modelo?

Mayormente transferible. Los principios core —especificidad, establecimiento de contexto, encadenamiento, loops de crítica— aplican en GPT-4, Claude 3.5 Sonnet, Gemini, lo que venga después. La sintaxis varía un poco y algunos modelos responden mejor a ciertos enfoques, pero la lógica subyacente se mantiene. He notado que Claude responde bien a restricciones explícitas; GPT-4 responde bien a ejemplos. Diferencias menores, fundamentos iguales.

¿Cómo manejas el código generado por IA en la revisión de código?

Igual que cualquier otro código. Si va a producción, se revisa. Punto. He dejado de señalar "esto fue generado por IA" en PRs en Seahawk porque se convirtió en una distracción, los revisores lo escrutinizaban diferente, a veces injustamente, a veces no lo suficiente. El código vale o no vale por sus propios méritos. Lo que sí señalo: cualquier sección donde la lógica no sea obvia y no haya añadido comentarios inline explicando el razonamiento.

¿Usas prompts del sistema o solo prompts de chat?

Ambos. En Cursor me apoyo en el archivo .cursorrules para instrucciones persistentes a nivel de proyecto, cosas que de otro modo estaría pegando cada vez. Para tareas puntuales en la web UI de ChatGPT o Claude, todo va en el chat. El enfoque .cursorrules ha reducido significativamente la repetición y el modelo se mantiene más consistente a lo largo de una sesión larga.

¿Cuál es tu opinión honesta sobre la IA reemplazando desarrolladores?

Está reemplazando ciertas tareas, no desarrolladores. Los juicios de valor, qué construir, cómo arquitectarlo, cuál trade-off se ajusta a la situación real de este cliente, eso está lejos de estar automatizado. Si acaso, los desarrolladores que están siendo presionados son los que eran puramente orientados a ejecución, no a diseño o arquitectura. Afila la capa de juicio. Ese es el bit defensible.

---

Nueve años construyendo cosas en la web, y la lección fundamental se repite constantemente: la calidad de tu output está determinada por la calidad de tus inputs. Era verdad cuando eran briefings de clientes. Ahora es verdad con los prompts.

El modelo es un desarrollador junior rápido, ocasionalmente brillante, frecuentemente demasiado confiado. Manéjalo en consecuencia.

Lecturas relacionadas: Construir un sitio de subastas en tiempo real con Next.js & Supabase, Cómo calcular el costo de software personalizado en 2026: Un estimador funcional para, y desarrollo web personalizado.

< BACK