La diferencia entre un LLM que genera código aceptable y uno que genera código que pasa code review casi nunca está en el modelo. Está en cómo le pides el trabajo.
Cualquier modelo decente puede escribir una función que compila. Pasar code review es otra cosa: el código tiene que encajar con el repo, con las convenciones del equipo, con los edge cases que no estaban en el prompt, y con el contexto que el reviewer humano da por sentado. Eso no sale de un prompt vago; sale de un prompt diseñado.
Aquí hay cinco prácticas que repetidamente reducen los rounds de revisión cuando trabajo con Claude —o cualquier LLM serio— en código real.
1. Pega contexto del repo, no solo la tarea
El error más común es escribir "agrégame un endpoint que haga X" sin mostrarle al modelo cómo se ven los otros endpoints del proyecto. El resultado es código que funciona pero usa otra estructura de carpetas, otro patrón de validación, otro estilo de manejo de errores. Lo señala el reviewer, vas y lo corriges a mano, pierdes media hora.
Un prompt útil empieza con un fragmento real del repo: un endpoint vecino, la interfaz del repository, cómo se devuelven los errores. Cuesta 30 segundos pegarlo y el modelo entrega código que ya mimetiza el estilo. La regla mental es simple: si el reviewer humano necesita ver el archivo X para entender el cambio, el modelo también lo necesita.
Esto se cumple incluso para cambios chicos. "Agregar logging aquí" sin mostrarle cómo se loguea en el resto del módulo termina en código con console.log o un wrapper inventado.
2. Haz explícitas las restricciones que el equipo da por hecho
Las convenciones de un equipo casi nunca están en un README. Están en cabezas. Cosas como "no usamos any en TypeScript", "los errores de dominio se devuelven como Result<T, DomainError> no como excepciones", "los nombres de columnas en la base son snake_case pero las propiedades de la entidad camelCase y el mapeo lo hace el ORM en este archivo".
El modelo no las puede inferir. Y si las omite, el código va a fallar el review por las razones obvias. La inversión es chica: una sección "Reglas" con tres a cinco bullets al final del prompt y la mitad de los problemas desaparecen.
3. Pasa ejemplos negativos cuando hay un patrón que rechazas
Decir "no quiero un switch gigante" es ambiguo. Mostrar un fragmento de código y decir "no aceptaría este patrón porque cada caso nuevo obliga a tocar este archivo" es accionable. El modelo ve el shape del problema y produce una alternativa que ya evita esa trampa específica.
Lo mismo aplica para librerías: "no uses moment" funciona; "ya migramos todo a date-fns, muéstrame el cambio que rompería esto" funciona mejor porque le hace pensar en el riesgo, no solo en el listado de banned imports.
4. Pídele que valide assumptions antes de codear
Esta es la práctica que más reduce tiempo perdido. Antes de generar el código, pídele al modelo que enuncie sus tres assumptions más fuertes y te pregunte si son correctas.
Funciona porque el LLM revela ahí mismo si entendió mal el dominio. "Asumo que el usuario ya está autenticado en este endpoint" es una assumption que vale la pena confirmar antes de escribir cien líneas que la dan por hecho. Si tú respondes "no, este endpoint también lo llaman desde un webhook sin auth", el modelo cambia toda la estructura del código antes de generarlo, no después.
Es un round extra de chat pero ahorra el segundo round de revisión humana.
5. Cierra el prompt con el criterio de aceptación
Lo más cercano a un test que tiene un LLM es saber cómo vas a juzgar el output. Termina el prompt con dos o tres bullets que digan qué tiene que cumplir el código para que lo aceptes:
- Compila sin warnings con la config TS estricta del repo.
- Maneja explícitamente el caso
entity not found(404, no excepción). - No agrega dependencias nuevas.
El modelo prioriza esos criterios sobre lo demás. Si pone una dependencia nueva, lo justifica en su respuesta. Si no puede cumplir uno, te lo dice. Es lo más cercano a TDD que se puede hacer en un prompt.
El anti-patrón que arruina todo lo anterior
Hay un patrón que veo a menudo y que neutraliza todas las prácticas de arriba: pedirle al modelo que "haga esto rápido" o "una solución simple". Suena pragmático, pero le da permiso al LLM de saltarse validaciones, manejo de errores, y edge cases que el reviewer va a marcar inmediatamente.
Si la solución tiene que ser realmente simple, deja que sea el código quien lo demuestre. Pídele el shape correcto y vas a recibir algo simple porque el problema es simple. Pedirle "rápido y simple" es pedirle "salta los pasos que después tengo que hacer yo".
Lo que está debajo de todas estas prácticas
Las cinco se reducen a un mismo principio: tratar al modelo como un colaborador que leyó mucho pero no conoce este repo, este equipo, ni este dominio en particular. La gente con esa mezcla existe en la vida real: alguien que llega a un proyecto en su primera semana. Nadie le pediría a esa persona "impleméntame el endpoint" sin antes mostrarle el código del módulo, las convenciones del equipo, y qué patrones evitamos.
Ese mismo nivel de inducción es lo que falta en los prompts que producen código que no pasa review. Y es la única razón por la que prácticas tan obvias mueven tanto la aguja.
Ningún LLM va a inferir lo que tu equipo da por hecho. Pero sí puede leer y respetar lo que hagas explícito en treinta segundos.