Escribir prompts no es magia. Es ingeniería. La diferencia entre un prompt mediocre y uno excelente puede ser la diferencia entre código que funciona y código que necesitas reescribir tres veces.
He iterado miles de prompts en producción. Estos son los patrones que funcionan consistentemente, con ejemplos reales y comparativas lado a lado.
La Anatomía de un Buen Prompt
Un prompt efectivo tiene cinco componentes:
- Contexto: Quién es el modelo y qué sabe
- Tarea: Qué necesitas que haga
- Formato: Cómo debe estructurar la respuesta
- Restricciones: Qué NO debe hacer
- Ejemplos: Casos concretos (cuando aplica)
Vamos componente por componente.
1. Contexto: Establecer el Rol
❌ Prompt Malo
Genera código para un componente de login✅ Prompt Bueno
Eres un desarrollador senior de React especializado en TypeScript y Next.js 14.Sigues las mejores prácticas de accesibilidad y seguridad.
Genera un componente de login usando:- Next.js 14 App Router- Server Actions para el form- shadcn/ui para los componentes- Zod para validación- React Hook Form para manejo del estadoDiferencia en output:
El primero te da un componente genérico con useState y fetch. El segundo te da exactamente lo que necesitas con el stack correcto.
2. Tarea: Ser Específico Sin Ser Verboso
❌ Prompt Malo
Explícame cómo funciona ReactDemasiado amplio. Obtienes una explicación genérica que no te sirve.
❌ Prompt Malo (en la otra dirección)
Necesito que me expliques el ciclo de vida completo de React, incluyendocada fase del render, reconciliation, commit phase, passive effects,layout effects, y cómo funcionan los hooks en cada una de estas fases,con detalles sobre el fiber tree y la arquitectura interna...Demasiado específico. Terminas con información que no necesitas.
✅ Prompt Bueno
Explica cómo React renderiza componentes desde que cambias el estadohasta que se actualiza el DOM. Usa un ejemplo concreto con useState.Máximo 3 párrafos.Específico, acotado, con ejemplo concreto.
3. Formato: Estructura la Respuesta
Ejemplo Real: Generando Documentación de API
❌ Sin Formato
Documenta esta función:
async function createUser(data) { const user = await db.user.create({ data }) return user}Output: Párrafo desestructurado que mezcla parámetros, retornos y descripción.
✅ Con Formato
Documenta esta función usando el siguiente formato:
## Descripción
[Una línea]
## Parámetros
- `nombre` (tipo): descripción
## Retorna
- tipo: descripción
## Ejemplo de uso
```typescript
// código
```
## Errores posibles
- ErrorName: cuándo ocurre
Función a documentar:
async function createUser(data) {
const user = await db.user.create({ data })
return user
}
## Errores posibles
- ErrorName: cuándo ocurre
Función a documentar:
async function createUser(data) {
const user = await db.user.create({ data })
return user
}
```
Output: Documentación estructurada, consistente y fácil de leer.
## 4. Restricciones: Lo Que NO Debe Hacer
Este es el secreto que pocos usan. Decirle al modelo qué NO hacer es tan importante como decirle qué hacer.
### Ejemplo Real: Generando Tests
### ❌ Sin Restricciones
```
Genera tests para esta función:
function sum(a, b) {
return a + b
}
```
Output: 20 tests incluyendo casos ridículos como "debería sumar números negativos imaginarios en sistemas no-euclidianos"
### ✅ Con Restricciones
```
Genera tests para esta función:
function sum(a, b) {
return a + b
}
Restricciones:
- Máximo 5 tests
- Solo casos realistas
- No uses números mayores a 1000
- No incluyas edge cases de tipos (eso se maneja con TypeScript)
- Usa describe/it de Jest
```
Output: Exactamente lo que necesitas, sin fluff.
## 5. Ejemplos: Few-Shot Prompting
Cuando quieres consistencia, dale ejemplos concretos.
### Caso Real: Generando Mensajes de Commit
### Zero-Shot (sin ejemplos)
```
Genera un mensaje de commit para estos cambios:
- Agregué validación de email
- Arreglé el bug del formulario
- Actualicé estilos
```
Output: "Updated form with email validation and styling fixes"
Meh. No sigue convenciones.
### Few-Shot (con ejemplos)
```
Genera mensajes de commit siguiendo estos ejemplos:
Ejemplo 1:
Cambios: Agregué autenticación con Google
Output: feat(auth): add Google OAuth integration
Ejemplo 2:
Cambios: Arreglé memory leak en el componente
Output: fix(components): resolve memory leak in UserList
Ejemplo 3:
Cambios: Actualicé README con nuevas instrucciones
Output: docs(readme): update setup instructions
Ahora genera para estos cambios:
- Agregué validación de email
- Arreglé el bug del formulario
- Actualicé estilos
```
Output:
```
feat(forms): add email validation
fix(forms): resolve submit bug
style(forms): update input styling
```
Perfecto. Consistente. Útil.
## Técnicas Avanzadas
### Chain of Thought (Razonamiento Paso a Paso)
Para problemas complejos, pídele que piense en voz alta.
```
Tengo este código que es lento:
function findDuplicates(arr) {
const duplicates = []
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j] && !duplicates.includes(arr[i])) {
duplicates.push(arr[i])
}
}
}
return duplicates
}
Analiza paso a paso:
1. ¿Cuál es la complejidad actual?
2. ¿Dónde están los cuellos de botella?
3. ¿Qué estructura de datos mejoraría esto?
4. Implementa la solución optimizada
```
Output:
```
1. Complejidad actual: O(n³)
- Doble loop: O(n²)
- includes() en cada iteración: O(n)
- Total: O(n³)
2. Cuellos de botella:
- Búsqueda lineal con includes()
- Comparaciones redundantes
3. Estructura de datos mejor: Set
- Búsqueda O(1)
- Elimina duplicados automáticamente
4. Solución optimizada:
function findDuplicates(arr) {
const seen = new Set()
const duplicates = new Set()
for (const item of arr) {
if (seen.has(item)) {
duplicates.add(item)
}
seen.add(item)
}
return Array.from(duplicates)
}
// Complejidad: O(n)
```
### Self-Consistency (Múltiples Perspectivas)
Para decisiones arquitectónicas:
```
Necesito decidir entre:
1. Monorepo con Turborepo
2. Múltiples repos independientes
Dame 3 análisis diferentes:
Análisis 1: Desde la perspectiva de un CTO preocupado por costos
Análisis 2: Desde la perspectiva de un developer que valora DX
Análisis 3: Desde la perspectiva de DevOps preocupado por CI/CD
Finalmente, dame una recomendación sintetizando los tres.
```
### Tree of Thoughts (Explorar Opciones)
Para generar alternativas:
```
Necesito nombrar una función que:
- Valida y transforma datos de usuario
- Hace sanitización
- Convierte a formato interno
Genera 5 nombres diferentes siguiendo cada uno de estos criterios:
1. Descriptivo y explícito (claridad sobre brevedad)
2. Conciso y común en la industria
3. Basado en verbos de acción
4. Siguiendo naming conventions de Domain-Driven Design
5. Tu mejor sugerencia considerando todo
Para cada uno explica en una línea por qué ese nombre.
```
Output estructurado con opciones reales para evaluar.
## Prompts para Casos de Uso Comunes
### Generación de Código
```typescript
// Prompt template para componentes
const componentPrompt = `
Genera un componente de React siguiendo estas especificaciones:
Contexto:
- Next.js 14 App Router
- TypeScript estricto
- Tailwind CSS
- Cliente component (usa 'use client')
Requisitos funcionales:
${requirements}
Requisitos técnicos:
- Props con TypeScript interface
- Manejo de estados de loading/error
- Accesibilidad (ARIA labels)
- Responsive design
Restricciones:
- No uses librerías externas excepto las mencionadas
- Máximo 100 líneas
- Incluye comentarios solo para lógica compleja
Formato de respuesta:
1. Interface de Props
2. Componente
3. Ejemplo de uso
`
// Uso
const code = await generateAI(
componentPrompt.replace('${requirements}', 'Un selector de fecha con rango')
)
```
### Code Review
```typescript
const reviewPrompt = `
Revisa este código como un senior developer:
${code}
Analiza:
1. Bugs potenciales
2. Problemas de performance
3. Vulnerabilidades de seguridad
4. Code smells
5. Mejoras en legibilidad
Para cada issue:
- Severidad (🔴 crítico, 🟡 moderado, 🟢 sugerencia)
- Línea aproximada
- Explicación
- Código corregido
No menciones issues que no existan. Sé directo.
`
```
### Debugging
```typescript
const debugPrompt = `
Tengo este error:
Error: ${errorMessage}
Stack trace:
${stackTrace}
Código relevante:
${code}
Estado de la aplicación:
${state}
Analiza paso a paso:
1. ¿Qué está causando el error exactamente?
2. ¿Por qué ocurre en este contexto?
3. ¿Cómo lo reproduzco consistentemente?
4. Dame 2-3 soluciones posibles ordenadas por probabilidad
5. ¿Cómo prevengo esto en el futuro?
No especules. Si no estás seguro, dilo.
`
```
### Optimización
```typescript
const optimizationPrompt = `
Este código funciona pero es lento:
${code}
Métricas actuales:
${metrics}
Optimiza considerando:
1. Complejidad algorítmica
2. Uso de memoria
3. Network requests (si aplica)
4. Re-renders (si es React)
Para cada optimización propuesta:
- Impacto estimado (alto/medio/bajo)
- Trade-offs
- Código optimizado
- Cómo medir la mejora
Prioriza optimizaciones con mayor ROI.
`
```
## Anti-Patterns: Lo Que NO Funciona
### 1. Prompts Demasiado Educados
```
❌ Por favor, si no es mucha molestia, podrías ayudarme a generar...
✅ Genera un componente de...
```
La cortesía no mejora el output. Sé directo.
### 2. Preguntas Retóricas
```
❌ ¿No crees que sería mejor usar TypeScript aquí?
✅ Usa TypeScript para este código.
```
No hagas preguntas si quieres una acción específica.
### 3. Contexto Irrelevante
```
❌ Estoy trabajando en un proyecto muy importante para mi startup que va a
revolucionar la industria del e-commerce con blockchain y AI. Necesito que
me ayudes a generar un botón...
✅ Genera un botón con estas características...
```
El modelo no se impresiona con tu pitch. Ve al grano.
### 4. Múltiples Tareas en Un Prompt
```
❌ Genera un componente de login, explica cómo funciona OAuth, dame mejores
prácticas de seguridad y también genera tests.
✅ [Un prompt para cada tarea]
```
Una tarea por prompt. Mejor calidad en cada una.
## Testing de Prompts: Cómo Iterar
No adivines. Mide. Así itero prompts en producción:
```typescript
// Función para testear prompts
async function testPrompt(
prompt: string,
testCases: Array<{ input: string; expected: string }>,
model: AIModel = 'claude-3-5-sonnet'
) {
const results = []
for (const testCase of testCases) {
const output = await generateAI(
prompt.replace('${input}', testCase.input),
model
)
const similarity = calculateSimilarity(output.text, testCase.expected)
results.push({
input: testCase.input,
output: output.text,
expected: testCase.expected,
similarity,
passed: similarity > 0.8
})
}
const passRate = results.filter(r => r.passed).length / results.length
return { results, passRate }
}
// Uso
const testCases = [
{
input: 'función que suma dos números',
expected: 'function sum(a: number, b: number): number'
},
// más casos...
]
const { passRate } = await testPrompt(myPrompt, testCases)
console.log(`Pass rate: ${passRate * 100}%`)
```
## Template de Prompt Universal
Esto funciona para el 80% de casos:
```
[CONTEXTO]
Eres un [rol] experto en [tecnologías].
Sigues [estándares/principios].
[TAREA]
[Verbo de acción] [objeto] que [requisitos].
[FORMATO]
Estructura la respuesta así:
[estructura específica]
[RESTRICCIONES]
- No [restricción 1]
- Máximo [límite]
- Solo [alcance]
[EJEMPLOS] (opcional)
Ejemplo: [input] → [output esperado]
[INPUT]
[Datos concretos con los que trabajar]
```
## Ejemplo Real: Prompt en Producción
Este es un prompt que uso en un SaaS real para generar copy de marketing:
```typescript
const marketingCopyPrompt = `
Eres un copywriter experto en SaaS B2B con 10+ años de experiencia.
Tu estilo es directo, orientado a beneficios, sin fluff.
Genera copy para [${section}] siguiendo estos principios:
- Enfócate en el outcome, no en features
- Usa voz activa
- Incluye números cuando sea posible
- Máximo 2 frases por párrafo
Target audience:
- Rol: ${targetRole}
- Pain point: ${painPoint}
- Nivel técnico: ${technicalLevel}
Formato:
1. Headline (máximo 60 caracteres)
2. Subheadline (máximo 120 caracteres)
3. Body (2-3 párrafos cortos)
4. CTA (máximo 30 caracteres)
Restricciones:
- No uses: "revolutionize", "game-changing", "cutting-edge"
- No exageres beneficios no comprobados
- No hagas comparaciones directas con competidores
Producto:
${productDescription}
Genera 3 variaciones para A/B testing.
`
// Este prompt tiene 95%+ de aprobación sin edición manual
```
## Conclusión: Principios Fundamentales
1. **Claridad > Brevedad:** Mejor un prompt largo y claro que uno corto y ambiguo
2. **Ejemplos > Explicaciones:** Mostrar es más efectivo que describir
3. **Restricciones > Libertad:** Los límites producen mejor output
4. **Iteración > Perfección:** El mejor prompt es el que has refinado 10 veces
5. **Medición > Intuición:** Testea, no adivines
El prompt engineering no es un arte. Es experimentación sistemática. Empieza con un prompt simple, mide el output, refina, repite.
Y recuerda: el mejor prompt es el que te hace el trabajo más rápido y mejor que si lo hicieras tú solo. Si no cumple eso, sigue iterando.