Objetivo de la sesión
Al terminar esta sesión serás capaz de:
- Organizar un proyecto que incluya agentes IA con estructura clara y mantenible
- Separar lógica de negocio, lógica de agentes y configuración de prompts
- Diseñar un sistema de prompts versionado y auditable
- Aplicar el patrón monorepo vs multi-repo con criterio
- Crear un scaffold reutilizable para futuros proyectos IA
Vídeo: Anatomía de un proyecto IA bien estructurado
La estructura que escala
3:00 min
Screencast mostrando un proyecto real con agentes: carpetas, donde va cada cosa, como fluye una petición desde el frontend hasta el agente y de vuelta. Mostrar que pasa cuando esta mal estructurado (todo en un archivo) vs bien estructurado (separado por dominio).
Próximamente
1. El error del archivo único
Como empieza todo el mundo
# main.py — 800 lineas con todo mezclado
from openai import OpenAI
from fastapi import FastAPI
app = FastAPI()
client = OpenAI()
SYSTEM_PROMPT = """Eres un asistente que analiza documentos..."""
@app.post("/analyze")
async def analyze(text: str):
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text}
]
)
# ... 200 lineas mas de logica mezclada
Funciona para un prototipo. Se convierte en pesadilla cuando:
- Necesitas cambiar el prompt sin tocar código
- Otro agente necesita una variación del mismo flujo
- Quieres probar otro modelo sin romper todo
- Alguien nuevo se une al proyecto y no entiende nada
La regla de separación
Logica de negocio ≠ Logica de agentes ≠ Prompts ≠ Configuracion ≠ Datos
Cada cosa en su sitio. Un cambio en un prompt no deberia requerir tocar código de negocio.
2. Estructura recomendada: proyecto fullstack con IA
mi-proyecto/
CLAUDE.md
PRODUCT.md
docker-compose.yml
frontend/ ← Next.js / Astro / React
src/
app/
components/
lib/
backend/ ← FastAPI / Hono
app/
main.py
config.py
api/
v1/
routes/
analyze.py ← Endpoints
agents.py
deps.py ← Dependencies (auth, db)
agents/ ← LOGICA DE AGENTES (separada)
base.py ← Clase base de agente
analyzer/
agent.py ← Logica del agente analyzer
tools.py ← Tools que usa este agente
config.py ← Configuracion especifica
classifier/
agent.py
tools.py
config.py
prompts/ ← PROMPTS SEPARADOS DEL CODIGO
analyzer/
system_v1.0.txt ← Prompt versionado
system_v1.1.txt
few_shot_examples.json
classifier/
system_v1.0.txt
services/ ← LOGICA DE NEGOCIO (sin IA)
document_service.py
user_service.py
models/ ← Modelos DB
schemas/ ← Schemas request/response
workers/ ← Tareas async
tests/
test_agents/
test_services/
evals/ ← EVALUACIONES DE AGENTES
analyzer/
golden_dataset.jsonl
eval_config.yaml
infra/ ← Docker, deploy, IaC
Dockerfile
nginx.conf
Por que esta estructura
| Carpeta | Responsabilidad | Quien la toca |
|---|---|---|
agents/ | Como funciona cada agente (orquestación, tools) | Developer |
prompts/ | Que dice cada agente (instrucciones, ejemplos) | Developer o product |
services/ | Lógica de negocio sin IA | Developer |
evals/ | Como sabemos que el agente funciona bien | Developer o QA |
api/routes/ | Como se expone al exterior | Developer |
3. Prompts: versionados, fuera del código
Por que los prompts no van en el código
Si el prompt esta hardcodeado en el archivo Python/TypeScript:
- Cambiar el prompt = hacer commit + deploy
- No puedes hacer A/B testing de prompts fácilmente
- No tienes historial de versiones del prompt
- Product no puede ajustar el prompt sin pedir un deploy
Sistema de prompts recomendado
prompts/
analyzer/
system_v1.0.txt ← Version inicial
system_v1.1.txt ← Mejora tras evaluacion
system_v2.0.txt ← Cambio mayor
few_shot_examples.json ← Ejemplos para few-shot
config.yaml ← Que version es la activa
classifier/
system_v1.0.txt
config.yaml
config.yaml:
active_version: "v1.1"
model: "claude-sonnet-4-6"
temperature: 0.3
max_tokens: 2000
Cargar en código:
import yaml
from pathlib import Path
def load_prompt(agent_name: str) -> dict:
base = Path("prompts") / agent_name
config = yaml.safe_load((base / "config.yaml").read_text())
version = config["active_version"]
prompt = (base / f"system_{version}.txt").read_text()
return {"prompt": prompt, **config}
Naming de versiones
v1.0 → Primera version funcional
v1.1 → Ajuste menor (tono, formato, restriccion)
v2.0 → Cambio mayor (nuevo enfoque, nuevas instrucciones)
Cada versión es un archivo nuevo. Nunca sobreescribas: así siempre puedes volver atrás.
4. Agentes: el patrón coordinator + workers
Agente simple (1 archivo)
Para tareas sencillas, un agente es una función:
# agents/summarizer/agent.py
from lib.llm import call_llm
from prompts import load_prompt
async def summarize(document: str) -> str:
config = load_prompt("summarizer")
return await call_llm(
prompt=config["prompt"],
user_message=document,
model=config["model"],
temperature=config["temperature"]
)
Multi-agente (coordinator + workers)
Para tareas complejas, un coordinador reparte trabajo entre agentes especializados:
agents/
coordinator/
agent.py ← Decide que worker usar
router.py ← Logica de routing
workers/
analyzer/
agent.py ← Analiza documentos
tools.py ← Herramientas del analyzer
classifier/
agent.py ← Clasifica contenido
generator/
agent.py ← Genera contenido
Regla: El coordinator NUNCA hace trabajo. Solo decide quien lo hace. Los workers NUNCA deciden. Solo ejecutan.
Tools: herramientas de los agentes
# agents/analyzer/tools.py
def search_database(query: str) -> list:
"""Busca en la base de datos de documentos."""
# logica real
pass
def extract_entities(text: str) -> dict:
"""Extrae entidades nombradas del texto."""
# logica real
pass
# Registro de tools para el agente
TOOLS = [
{"function": search_database, "description": "Busca documentos relevantes"},
{"function": extract_entities, "description": "Extrae entidades del texto"},
]
5. Monorepo vs multi-repo
Cuando monorepo
| Situación | Monorepo? |
|---|---|
| Equipo de 1-5 personas | Si |
| Frontend + backend comparten tipos | Si |
| Deploy acoplado (frontend necesita backend nuevo) | Si |
| Proyecto en fase MVP o early stage | Si |
Cuando multi-repo
| Situación | Multi-repo? |
|---|---|
| Equipos independientes por servicio | Si |
| Cada servicio tiene su ciclo de deploy | Si |
| Servicios en lenguajes diferentes sin dependencia | Si |
| Proyecto enterprise con múltiples equipos | Si |
Recomendación para builders
Empieza con monorepo. Siempre. Separar es fácil. Unir es difícil. Un monorepo con buena estructura de carpetas es suficiente para el 95% de proyectos hasta que tengas 10+ developers.
6. Evaluaciones: como saber que tu agente funciona
Golden dataset
Un archivo con pares input-output esperados:
{"input": "Contrato de alquiler 24 meses...", "expected": {"tipo": "alquiler", "duracion": "24 meses", "riesgo": "bajo"}}
{"input": "NDA con clausula de no competencia...", "expected": {"tipo": "NDA", "clausulas_riesgo": ["no competencia"], "riesgo": "medio"}}
Estructura de evals
tests/evals/
analyzer/
golden_dataset.jsonl ← Casos de prueba
eval_config.yaml ← Umbrales de calidad
run_eval.py ← Script que ejecuta y mide
results/
2026-08-28.json ← Resultados por fecha
eval_config.yaml:
thresholds:
accuracy: 0.85 # Minimo 85% de aciertos
latency_p95_ms: 5000 # Maximo 5 seg en p95
cost_per_eval_usd: 0.50 # Maximo 0.50 USD por ejecucion
run_before_deploy: true # Obligatorio antes de deploy
Regla: ningún cambio de prompt va a producción sin pasar evals
7. Lab práctico: Scaffold tu proyecto IA
Instrucciones
Crea la estructura completa de un proyecto con agentes. 30 minutos.
Paso 1: Define tu proyecto (5 min)
Nombre: _________________________________
Que hace: _________________________________
Agentes necesarios:
1. _________________________________ [que hace]
2. _________________________________ [que hace]
3. _________________________________ [que hace]
Stack: Frontend _______ + Backend _______ + DB _______
Paso 2: Crea la estructura de carpetas (15 min)
Usa la estructura de la sección 2 como base. Adapta a tu proyecto.
mkdir -p backend/app/{agents,prompts,services,models,schemas,workers}
mkdir -p backend/app/agents/{nombre_agente1,nombre_agente2}
mkdir -p backend/app/prompts/{nombre_agente1,nombre_agente2}
mkdir -p backend/tests/{test_agents,evals}
mkdir -p frontend/src/{app,components,lib}
mkdir -p infra
Paso 3: Crea los archivos base (10 min)
- CLAUDE.md con stack y convenciones
- Prompt v1.0 para tu agente principal
- config.yaml para el agente
- Al menos 3 casos en golden_dataset.jsonl
Entregable de la sesión
Tu scaffold de proyecto IA con estructura completa, prompts separados y evaluaciones configuradas.
SCAFFOLD PROYECTO IA
=====================
Proyecto: _________________________________
Estructura:
[ ] CLAUDE.md
[ ] Carpeta agents/ con _____ agentes
[ ] Carpeta prompts/ con versiones
[ ] Carpeta evals/ con golden dataset
[ ] Separacion negocio/agentes/prompts
Agentes definidos:
1. _____________ — prompt v___
2. _____________ — prompt v___
Tipo: [ ] Monorepo [ ] Multi-repo
Recursos descargables
- Scaffold templates (GitHub repo) — Estructura lista para clonar por tipo de proyecto (Next.js + FastAPI + agentes)
- Diagrama de referencia (PDF) — Flujo de datos frontend → API → agente → tools → respuesta
- Checklist estructura (PDF) — Verificación rápida de que no falta nada
Siguientes pasos
En la siguiente sesión (AB-05: Agentes y subagentes) vas a diseñar la lógica interna de los agentes: como orquestarlos, cuando usar subagentes, como gestionar worktrees y ejecución paralela.
Antes de pasar a AB-05:
- Has creado el scaffold de al menos 1 proyecto
- Has separado prompts del código
- Has creado al menos 3 casos de evaluación
Toolbox — Sesión 04 de 09
IAcademy — iacedemy.com