Módulo 11: Deep Agents

Proyecto Evolutivo: Versión Deep Agent (v6)

Descripción del proyecto

Has llegado al proyecto final del Módulo 11 y al momento pedagógico más importante de la guía.

En los módulos 6-10, tu AI Research Assistant creció pieza a pieza: búsqueda básica con Functional API (v1), retry y branching (v2), checkpointing y crash recovery (v3), HITL con approvals (v4), y multi-agente con supervisor y especialistas (v5). Aproximadamente 150 líneas de código para un sistema que planifica, busca, analiza, escribe, y se recupera de fallos. Diseñaste cada nodo, cada edge, cada condición de routing. Lo entiendes porque lo construiste.

Ahora vas a reimplementar ese mismo sistema como Deep Agent. ~40 líneas. El mismo resultado funcional — investigación multi-fuente con reporte consolidado — pero con un trade-off fundamental: ganaste velocidad de desarrollo y perdiste control sobre cada decisión del flujo.

El valor de este proyecto no es el código. Es la comparación. Poner la v5 y la v6 lado a lado y poder articular: "gané X, perdí Y, y elegiría Z para este caso de uso." Ese es el criterio que te convierte en AI Engineer. No el que sabe usar un framework — el que sabe elegir el framework correcto.


Objetivo del proyecto

Reimplementar el AI Research Assistant como Deep Agent (v6) y comparar directamente con la versión LangGraph (v5), articulando los trade-offs de cada enfoque.

Al completar este proyecto:

  • Crearás un Deep Agent con planning, filesystem, subagent spawning, y memory configurados
  • Ejecutarás la misma consulta en v5 (LangGraph) y v6 (Deep Agent) para comparar resultados
  • Articularás exactamente qué ganaste (velocidad de desarrollo, simplicidad) y qué perdiste (control, debuggabilidad)
  • Tendrás DOS versiones funcionales del Research Assistant en tu portfolio

Antes y después

v5 (Módulo 10): ~150 líneas, control total

research-assistant-v5/
├── agents/
│   ├── researcher.py         ← Agente especializado en búsqueda
│   ├── analyst.py            ← Agente especializado en análisis
│   ├── writer.py             ← Agente especializado en redacción
│   └── supervisor.py         ← Coordinador del sistema
├── tools/
│   ├── search_tools.py       ← web_search, arxiv_search
│   ├── analysis_tools.py     ← compare_sources, detect_patterns
│   └── writing_tools.py      ← format_report
├── state/
│   └── multi_agent_state.py  ← Estado compartido tipado
├── tracing/
│   ├── agent_logger.py       ← Logging por agente
│   └── flow_tracer.py        ← Tracing del flujo
└── main.py                   ← Orquestación + CLI

Tú diseñaste: qué agente hace qué, en qué orden, cuándo hacer retry, cuándo pedir aprobación, cómo loguear, y cómo combinar resultados.

v6 (Este proyecto): ~40 líneas, el framework decide

research-assistant-v6/
├── .env                      ← API keys
├── requirements.txt          ← deep-agents, langchain-openai, python-dotenv
├── agent_memory/             ← Directorio de memoria (auto-generado)
└── main.py                   ← Todo el agente en un archivo

El framework decide: cómo descomponer la tarea, qué archivos crear, cuándo delegar, y cómo organizar los resultados.


Especificaciones técnicas

ComponenteVersiónPropósito
Python3.11+Runtime
deep-agentsv0.2+Framework de Deep Agents
langchain-openailatestProveedor de modelos
langchain-communitylatestTavilySearchResults
python-dotenvlatestVariables de entorno

Instalación

pip install deep-agents langchain-openai langchain-community python-dotenv

Variables de entorno

# .env
OPENAI_API_KEY=sk-...
TAVILY_API_KEY=tvly-...

Paso 1: Definir el Deep Agent con planning

El primer paso es crear el agente con instrucciones que guíen el planning. Las instrucciones son el equivalente a diseñar el workflow en LangGraph — en lugar de nodos y edges, escribes qué quieres que el agente haga.

"""
main.py
Research Assistant v6 — Deep Agent version.
"""
from dotenv import load_dotenv
load_dotenv()

from deep_agents import create_deep_agent
from deep_agents.memory import FilesystemMemoryBackend
from langchain_community.tools import TavilySearchResults

web_search = TavilySearchResults(max_results=5)

memory = FilesystemMemoryBackend(
    base_path="./agent_memory",
    max_memories=200,
    max_memory_age_days=90,
)

agent = create_deep_agent(
    "openai:gpt-4.1",
    tools=[web_search],
    name="Research Assistant v6",
    instructions=(
        "Eres un asistente de investigación especializado. "
        "Para cada tema de investigación: "
        "1) Descompone la investigación en pasos claros con write_todos. "
        "2) Busca fuentes diversas: web general, artículos técnicos, reportes. "
        "3) Escribe los hallazgos de cada búsqueda en archivos separados dentro de research/. "
        "4) Si el tema tiene múltiples dimensiones, delega búsquedas a subagentes especializados. "
        "5) Analiza y sintetiza todos los hallazgos en analysis/synthesis.md. "
        "6) Genera un reporte final estructurado en output/report.md con: "
        "   - Resumen ejecutivo "
        "   - Hallazgos principales "
        "   - Análisis "
        "   - Conclusiones "
        "   - Fuentes consultadas "
        "Recuerda las preferencias del usuario entre sesiones."
    ),
    memory=memory,
    max_iterations=15,
)

Qué pasa cuando el agente recibe una tarea

Al ejecutar agent.run("Investiga el estado de AI agents en producción en 2025"), el agente:

  1. Lee memorias relevantes — si el usuario investigó antes, recupera preferencias
  2. Ejecuta write_todos — descompone la tarea:
Todos generados automáticamente:
1. [pending] Definir alcance: AI agents en producción, 2025
2. [pending] Buscar frameworks de agentes principales
3. [pending] Buscar casos de uso en producción documentados
4. [pending] Buscar challenges y limitaciones reportadas
5. [pending] Sintetizar hallazgos
6. [pending] Generar reporte final
  1. Ejecuta cada paso — buscando, escribiendo archivos, y actualizando todos
  2. Re-planifica si necesario — si una búsqueda revela una dimensión inesperada, agrega pasos

Comparación con v5

En v5, tú definiste este workflow como un grafo:

builder.add_edge(START, "plan")
builder.add_edge("plan", "researcher")
builder.add_edge("researcher", "analyst")
builder.add_edge("analyst", "writer")
builder.add_conditional_edges("writer", evaluate_quality, ...)

En v6, el equivalente es la sección de instrucciones. El agente traduce tus instrucciones en un plan de ejecución. Menos preciso que edges explícitos, pero más flexible — si la tarea cambia, el plan se adapta sin modificar código.


Paso 2: Configurar el virtual filesystem

El virtual filesystem es el equivalente al estado del grafo en LangGraph. En v5, los hallazgos vivían en state["findings"]. En v6, viven en archivos.

Estructura esperada de archivos

Cuando el agente completa una investigación, el filesystem se ve así:

workspace/
├── research/
│   ├── web_general.md         ← Hallazgos de búsqueda web
│   ├── frameworks.md          ← Información sobre frameworks específicos
│   └── production_cases.md    ← Casos de uso en producción
├── analysis/
│   └── synthesis.md           ← Análisis cruzado de todas las fuentes
└── output/
    └── report.md              ← Reporte final consolidado

Ventaja: context offloading

En v5, todos los hallazgos están en state["findings"] — una lista que crece con cada búsqueda. Si tienes 10 fuentes con 500 tokens cada una, son 5,000 tokens en el context window permanentemente.

En v6, cada hallazgo está en un archivo. El agente lee solo el archivo que necesita para el paso actual. El context window se mantiene lean.

v5 (LangGraph):
  Context window: [system prompt] + [state con todos los findings] + [instrucción actual]
  Tamaño: crece con cada paso

v6 (Deep Agent):
  Context window: [system prompt] + [archivo actual] + [instrucción actual]
  Tamaño: constante (~misma cantidad de tokens por paso)

Inspeccionar archivos generados

result = agent.run("Investiga AI agents en producción en 2025")

for path, content in result.files.items():
    print(f"\n{'='*60}")
    print(f"Archivo: {path}")
    print(f"Tamaño: {len(content)} caracteres")
    print(f"Preview: {content[:200]}...")
# Output esperado (varía según el modelo):
# ============================================================
# Archivo: research/web_general.md
# Tamaño: 2340 caracteres
# Preview: # Búsqueda Web: AI Agents en Producción
#
# ## Fuentes encontradas
# 1. **LangChain Blog** — "Agents in Production: Lessons Learned"
#    Key insight: La mayoría de agentes en producción usan...
#
# ============================================================
# Archivo: research/frameworks.md
# Tamaño: 1890 caracteres
# Preview: # Frameworks de AI Agents
#
# ## Principales frameworks en 2025
# | Framework | Enfoque | Adopción |...
#
# ============================================================
# Archivo: analysis/synthesis.md
# Tamaño: 3100 caracteres
# Preview: # Síntesis: AI Agents en Producción (2025)
#
# ## Patrones identificados
# 1. La mayoría de implementaciones en producción son...
#
# ============================================================
# Archivo: output/report.md
# Tamaño: 4200 caracteres
# Preview: # AI Agents en Producción: Estado Actual (2025)
#
# ## Resumen Ejecutivo
# Los AI agents han transitado de demos a producción...

Paso 3: Habilitar subagent spawning

En v5, los agentes especializados (researcher, analyst, writer) estaban definidos en build time. Tú decidiste qué agente existía y qué hacía.

En v6, el agente principal decide en runtime si necesita delegar. La instrucción "delega búsquedas a subagentes especializados cuando el tema es amplio" le da permiso pero no obligación.

Cómo funciona internamente

Main Agent: "Investigar AI agents en producción"
  │
  ├─ write_todos: 6 pasos
  │
  ├─ Paso 1: Define scope → ejecuta directamente
  │
  ├─ Paso 2: "Buscar frameworks" → decide que es específico
  │   └─ spawn: framework_researcher
  │       └─ Instrucciones: "Busca los principales frameworks de AI agents en 2025"
  │       └─ Tools: [web_search]
  │       └─ Retorna: hallazgos sobre LangGraph, CrewAI, AutoGen...
  │       └─ Main Agent escribe resultado en research/frameworks.md
  │
  ├─ Paso 3: "Buscar casos de producción" → decide que es diferente de paso 2
  │   └─ spawn: production_researcher
  │       └─ Instrucciones: "Busca empresas usando AI agents en producción"
  │       └─ Tools: [web_search]
  │       └─ Retorna: hallazgos sobre casos reales...
  │       └─ Main Agent escribe resultado en research/production_cases.md
  │
  ├─ Paso 4-6: Sintetiza y genera reporte → ejecuta directamente
  │
  └─ Resultado: 6/6 todos completados, 2 subagentes spawned

Control sobre subagentes

agent = create_deep_agent(
    "openai:gpt-4.1",
    tools=[web_search],
    name="Research Assistant v6",
    instructions="...",
    memory=memory,
    max_iterations=15,
    max_subagents=3,
    subagent_timeout=60,
)
  • max_subagents=3 — máximo 3 subagentes simultáneos (previene explosión de costos)
  • subagent_timeout=60 — cada subagente tiene 60 segundos antes de ser terminado

Comparación con v5

Aspectov5 (LangGraph)v6 (Deep Agent)
Agentes definidos enBuild time (código)Runtime (el framework decide)
RolesFijos: researcher, analyst, writerDinámicos: el agente crea lo que necesita
CoordinaciónSupervisor con edges explícitosMain agent coordina con write_todos
ControlTú defines quién hace quéEl framework decide, tú guías con instructions
DebuggingLog por agente, sabes qué nodo fallóLog de subagent spawning, menos granular

Paso 4: Configurar long-term memory

La memoria permite que el agente recuerde preferencias entre sesiones. En v5, esto requería un Store con namespaces y lógica de load/save. En v6, es una línea de configuración.

Configuración (ya incluida en Paso 1)

memory = FilesystemMemoryBackend(
    base_path="./agent_memory",
    max_memories=200,
    max_memory_age_days=90,
)

Ejemplo de memoria en acción

Sesión 1:

result = agent.run(
    "Investiga RAG techniques. Prefiero fuentes académicas de arxiv y NeurIPS."
)
print(result.output[:200])
# Output esperado (varía según el modelo):
# ## AI Research Report: RAG Techniques
#
# ### Resumen Ejecutivo
# Las técnicas de Retrieval-Augmented Generation han evolucionado...
# (prioriza fuentes de arxiv y NeurIPS como solicitado)

Sesión 2 (días después):

result = agent.run("Investiga AI safety")
print(result.output[:200])
# Output esperado (varía según el modelo):
# ## AI Research Report: AI Safety
#
# ### Resumen Ejecutivo
# El campo de AI safety ha experimentado avances significativos...
# (automáticamente prioriza arxiv y NeurIPS por la memoria de sesión 1)

No le repetiste la preferencia. El agente la recuperó del filesystem backend.

Inspeccionar memorias

import json
import os

memory_dir = "./agent_memory/memories"
if os.path.exists(memory_dir):
    for f in os.listdir(memory_dir):
        with open(os.path.join(memory_dir, f)) as fh:
            mem = json.load(fh)
            print(f"  [{mem['type']}] {mem['content'][:80]}...")
# Output esperado:
#   [preference] El usuario prefiere fuentes académicas de arxiv y NeurIPS...

Paso 5: Código completo (~40 líneas)

Este es el agente completo. Compáralo mentalmente con las ~150 líneas de v5.

"""
main.py
Research Assistant v6 — Deep Agent version.
Reimplementación completa del Research Assistant como Deep Agent.
"""
from dotenv import load_dotenv
load_dotenv()

from deep_agents import create_deep_agent
from deep_agents.memory import FilesystemMemoryBackend
from langchain_community.tools import TavilySearchResults

web_search = TavilySearchResults(max_results=5)

memory = FilesystemMemoryBackend(
    base_path="./agent_memory",
    max_memories=200,
    max_memory_age_days=90,
)

agent = create_deep_agent(
    "openai:gpt-4.1",
    tools=[web_search],
    name="Research Assistant v6",
    instructions=(
        "Eres un asistente de investigación especializado. "
        "Para cada tema de investigación: "
        "1) Descompone la investigación en pasos claros con write_todos. "
        "2) Busca fuentes diversas: web general, artículos técnicos, reportes. "
        "3) Escribe los hallazgos de cada búsqueda en archivos separados dentro de research/. "
        "4) Si el tema tiene múltiples dimensiones, delega búsquedas a subagentes especializados. "
        "5) Analiza y sintetiza todos los hallazgos en analysis/synthesis.md. "
        "6) Genera un reporte final estructurado en output/report.md con: "
        "   Resumen ejecutivo, Hallazgos principales, Análisis, Conclusiones, Fuentes. "
        "Recuerda las preferencias del usuario entre sesiones."
    ),
    memory=memory,
    max_iterations=15,
    max_subagents=3,
    subagent_timeout=60,
)

if __name__ == "__main__":
    topic = input("Tema de investigación: ")
    result = agent.run(topic)

    print(f"\n{'='*60}")
    print(f"Investigación completada")
    print(f"{'='*60}")
    print(f"Archivos generados: {list(result.files.keys())}")
    print(f"Todos: {sum(1 for t in result.todos if t['status'] == 'completed')}/{len(result.todos)}")
    print(f"Subagentes usados: {len(result.subagents_spawned)}")
    print(f"\nReporte final:")
    print(result.files.get("output/report.md", "No se generó reporte")[:500])
python main.py
# Input: Investiga el estado de AI agents en producción en 2025
# Output esperado:
# ============================================================
# Investigación completada
# ============================================================
# Archivos generados: ['research/web_general.md', 'research/frameworks.md', 'research/production_cases.md', 'analysis/synthesis.md', 'output/report.md']
# Todos: 6/6
# Subagentes usados: 2
#
# Reporte final:
# # AI Agents en Producción: Estado Actual (2025)
#
# ## Resumen Ejecutivo
# Los AI agents han transitado de prototipos a producción...

40 líneas. Planning, filesystem, subagentes, memoria, y CLI — todo incluido.


Paso 6: Comparación side-by-side

Este es EL momento del módulo. Pon ambas versiones frente a frente.

Líneas de código

v5 (LangGraph):
  state/multi_agent_state.py   ←  25 líneas
  agents/researcher.py         ←  35 líneas
  agents/analyst.py            ←  30 líneas
  agents/writer.py             ←  25 líneas
  agents/supervisor.py         ←  40 líneas
  tools/*.py                   ←  45 líneas
  tracing/*.py                 ←  30 líneas
  main.py                      ←  50 líneas
  ─────────────────────────────────────────
  Total:                       ~280 líneas (con tracing), ~150 sin tracing

v6 (Deep Agent):
  main.py                      ←  40 líneas
  ─────────────────────────────────────────
  Total:                       ~40 líneas

Tabla de análisis

Aspectov5 (LangGraph)v6 (Deep Agent)Ganador
Líneas de código~150 (sin tracing)~40v6 (73% menos código)
Tiempo de desarrollo~2-4 horas~20 minutosv6
Control sobre el flujoTotal — cada nodo y edge definidoParcial — instructions guíanv5
DebuggingExcelente — log por agente, estado por nodoAceptable — logs de planningv5
Branching condicionalSí — route_by_quality, evaluateNo — el framework decidev5
HITLGranular — interrupt() en puntos específicosGeneral — apruebas la tareav5
Multi-agenteRoles fijos, coordinación explícitaDinámico, el framework decideDepende
PersistenciaCheckpointer + StoreFilesystem + memory backendEmpate
EscalabilidadManual — agregas nodos/edgesAutomática — el agente se adaptav6
Costo por ejecuciónMedio (~$0.05-0.10)Alto (~$0.10-0.30)v5
MantenibilidadMás código = más que mantenerMenos código = menos que mantenerv6
TestingUnit tests por nodoIntegration tests del resultadov5

Análisis de trade-offs

Lo que ganaste con v6:

  • Velocidad de desarrollo: 20 minutos vs 2-4 horas. Si necesitas un prototipo rápido, v6 gana
  • Simplicidad: 40 líneas que un nuevo developer entiende en 5 minutos
  • Adaptabilidad: si la tarea cambia, solo modificas instructions. En v5, editas nodos, edges, y condiciones
  • Filesystem: los archivos son inspeccionables, no necesitas acceder al estado del grafo
  • Memory built-in: una línea vs ~80 líneas de setup manual

Lo que perdiste con v6:

  • Control fino: no decides "si quality_score < 0.7, busca más fuentes." El framework decide cuándo re-buscar
  • HITL granular: no puedes pedir aprobación antes de que el analyst genere conclusiones. Apruebas la tarea completa o nada
  • Debugging preciso: en v5, sabes que "el analyst recibió 8 hallazgos correctos pero su conclusión fue incorrecta." En v6, ves que "el agente generó un reporte con un error"
  • Testing unitario: en v5, testeas researcher_node() independientemente. En v6, solo testeas el resultado final
  • Costos predecibles: v5 tiene un número fijo de LLM calls (plan + search + analyze + write). v6 tiene un número variable (depende del planning del agente)
  • Modelos por paso: en v5, analyst usa gpt-4.1 y los demás gpt-4.1-mini. En v6, el mismo modelo para todo

Ejecución comparativa

Ejecuta la misma consulta en ambas versiones:

from dotenv import load_dotenv
load_dotenv()

import time

QUERY = "Investiga el estado de AI agents en producción en 2025"

print("=" * 60)
print("v6 (Deep Agent)")
print("=" * 60)

start = time.time()

from deep_agents import create_deep_agent
from deep_agents.memory import FilesystemMemoryBackend
from langchain_community.tools import TavilySearchResults

agent_v6 = create_deep_agent(
    "openai:gpt-4.1",
    tools=[TavilySearchResults(max_results=5)],
    name="Research Assistant v6",
    instructions=(
        "Investiga temas complejos. Descompone en pasos con write_todos. "
        "Escribe hallazgos en archivos. Delega a subagentes cuando sea necesario. "
        "Genera un reporte final en output/report.md."
    ),
    memory=FilesystemMemoryBackend(base_path="./memory_v6"),
    max_iterations=15,
)

result_v6 = agent_v6.run(QUERY)
time_v6 = time.time() - start

print(f"Tiempo: {time_v6:.1f}s")
print(f"Archivos: {len(result_v6.files)}")
print(f"Todos: {sum(1 for t in result_v6.todos if t['status'] == 'completed')}/{len(result_v6.todos)}")
print(f"Subagentes: {len(result_v6.subagents_spawned)}")
print(f"Reporte: {len(result_v6.files.get('output/report.md', ''))} chars")
# Output esperado (varía):
# Tiempo: ~45-90s
# Archivos: 4-5
# Todos: 5-6/5-6
# Subagentes: 1-3
# Reporte: ~3000-5000 chars

La comparación cuantitativa te da datos concretos para articular los trade-offs.


Criterios de éxito

Tu proyecto está completo cuando puedes responder SÍ a cada pregunta:

  • ✅ ¿El Deep Agent genera un reporte de investigación funcional?
  • ✅ ¿El agente usa write_todos para descomponer la tarea?
  • ✅ ¿Los hallazgos se escriben en archivos separados (no todo en context window)?
  • ✅ ¿El agente spawna al menos un subagente para búsquedas especializadas?
  • ✅ ¿La memoria persiste preferencias entre sesiones?
  • ✅ ¿Puedes articular 3 ventajas y 3 desventajas de v6 vs v5?
  • ✅ ¿Tienes ambas versiones (v5 y v6) funcionales?

Escenarios de prueba

Ejecuta estos escenarios para validar que tu agente funciona en diferentes tipos de tareas.

Escenario 1: Investigación simple

result = agent.run("¿Cuál es el estado actual de LangGraph?")
assert len(result.todos) >= 3, "Debe planificar al menos 3 pasos"
assert "output/report.md" in result.files, "Debe generar reporte"
print("✅ Escenario 1 pasó")

Escenario 2: Investigación multi-dimensión

result = agent.run(
    "Compara 3 enfoques de RAG: naive RAG, advanced RAG, y modular RAG. "
    "Para cada uno, investiga: arquitectura, pros, contras, y casos de uso."
)
assert len(result.files) >= 3, "Debe generar múltiples archivos de investigación"
assert len(result.subagents_spawned) >= 1, "Debe delegar al menos una búsqueda"
print("✅ Escenario 2 pasó")

Escenario 3: Memoria entre sesiones

result1 = agent.run("Investiga AI safety. Prefiero papers de arxiv.")

result2 = agent.run("Investiga AI governance")
report = result2.files.get("output/report.md", "")
print("✅ Escenario 3 pasó" if "arxiv" in report.lower() else "❌ Memoria no funciona")

Escenario 4: Re-planning

result = agent.run(
    "Investiga el impacto de AI en educación superior. "
    "Si encuentras que hay diferencias significativas entre regiones, "
    "investiga Europa y América Latina por separado."
)
assert len(result.todos) > 5, "Debe haber re-planificado con más pasos"
print("✅ Escenario 4 pasó")

Errores comunes

1. El agente no genera archivos — responde directamente

Causa: Las instrucciones no enfatizan suficiente el uso del filesystem.

Solución: Sé explícito en las instrucciones:

instructions=(
    "SIEMPRE escribe los hallazgos en archivos. "
    "NUNCA pongas toda la investigación en una sola respuesta. "
    "Cada fuente → un archivo en research/. "
    "El reporte final → output/report.md."
)

2. Demasiados subagentes — costos altos

Causa: No limitaste max_subagents o las instrucciones son muy amplias.

Solución:

agent = create_deep_agent(
    ...,
    max_subagents=3,
    subagent_timeout=60,
    instructions=(
        "Delega a subagentes SOLO cuando el tema tiene dimensiones "
        "claramente diferentes que requieren búsquedas especializadas."
    ),
)

3. La memoria no persiste entre ejecuciones

Causa: Estás creando un nuevo FilesystemMemoryBackend con un path diferente cada vez.

Solución: Usa siempre el mismo base_path:

memory = FilesystemMemoryBackend(base_path="./agent_memory")

4. El plan tiene demasiados pasos — se vuelve lento

Causa: Las instrucciones son demasiado detalladas y el agente crea un paso por cada sub-instrucción.

Solución: Simplifica las instrucciones y limita iteraciones:

agent = create_deep_agent(
    ...,
    max_iterations=10,
    instructions=(
        "Investiga el tema en 4-5 pasos máximo. "
        "No descompongas innecesariamente."
    ),
)

5. El reporte es superficial comparado con v5

Causa: Un solo modelo maneja todo. En v5, gpt-4.1 hacía análisis profundo.

Solución: Usa gpt-4.1 (no mini) como modelo principal para investigaciones complejas:

agent = create_deep_agent("openai:gpt-4.1", ...)

El trade-off: más caro pero mejor calidad de razonamiento.

6. No puedes comparar con v5 porque no la tienes funcionando

Causa: No completaste el proyecto del Módulo 10.

Solución: La comparación es el punto central de este proyecto. Si no tienes v5, vuelve al Módulo 10 y complétala. La comparación sin ambas versiones pierde todo su valor pedagógico.

7. Los archivos del filesystem se mezclan entre ejecuciones

Causa: No limpias el workspace entre ejecuciones diferentes.

Solución: Usa --output-dir diferente por investigación, o limpia manualmente:

import shutil
if os.path.exists("./workspace"):
    shutil.rmtree("./workspace")

8. El agente ignora las instrucciones de formato

Causa: Las instrucciones son demasiado largas y el modelo pierde contexto.

Solución: Prioriza las instrucciones más importantes al inicio del prompt:

instructions=(
    "FORMATO: Reporte con Resumen, Hallazgos, Análisis, Conclusiones, Fuentes. "
    "SIEMPRE usa write_todos. SIEMPRE escribe en archivos. "
    "Luego: busca fuentes diversas, delega cuando sea necesario."
)

Perspectiva de portfolio

Ahora tienes DOS versiones del Research Assistant:

Tu portfolio:
├── Research Assistant v5 (LangGraph)
│   ├── ~150 líneas de código
│   ├── 4 agentes especializados + supervisor
│   ├── Custom workflow con edges y condiciones
│   ├── HITL granular, retry con quality evaluation
│   └── Demuestra: "Sé construir sistemas complejos desde cero"
│
└── Research Assistant v6 (Deep Agent)
    ├── ~40 líneas de código
    ├── Planning, filesystem, subagentes, memory
    ├── Framework decide el flujo
    └── Demuestra: "Sé usar herramientas de alto nivel eficientemente"

En una entrevista, puedes decir:

"Construí el mismo Research Assistant de dos formas. La versión LangGraph tiene 150 líneas — diseñé cada nodo, edge, y condición. La versión Deep Agent tiene 40 líneas — el framework maneja planning, filesystem, y subagentes. Puedo articular los trade-offs: LangGraph me da control total sobre debugging, HITL, y flujo. Deep Agents me da velocidad de desarrollo y adaptabilidad. Elijo según el caso de uso."

Eso demuestra criterio, no dependencia de un framework.


Lo que viene: Módulo 12 — LangSmith y Producción

Tu Research Assistant ahora existe en dos versiones. Ambas funcionan. Pero ninguna está lista para producción.

¿Cuánto cuesta una investigación? ¿Cuántos tokens usa cada paso? ¿El reporte es consistentemente bueno o varía? ¿Cómo detectas cuando el agente "alucina" una fuente? ¿Cómo mides si v5 produce mejores reportes que v6?

El Módulo 12 agrega LangSmith: tracing completo de cada llamada al LLM, evaluation automatizada de la calidad de los reportes, token tracking por sesión, rate limiting, y un production checklist. Funciona con ambas versiones — LangGraph y Deep Agent.

M11: Construiste el agente (v5 y v6)
  ↓
M12: Lo haces observable y deployable
  ↓
  Resultado: un agente en producción que puedes monitorear, evaluar, y mejorar

Es el módulo que transforma tu proyecto de aprendizaje en un sistema que podrías deployar.


Recursos del proyecto

  1. Deep Agents — Documentation — API reference completa de create_deep_agent
  2. Deep Agents — Planning — Documentación de write_todos y re-planning
  3. Deep Agents — Filesystem — Virtual filesystem API y mejores prácticas
  4. LangGraph vs Deep Agents — Artículo oficial sobre cuándo usar cada abstracción
  5. Building Effective Agents (Anthropic) — Framework de decisión para complejidad de agentes
  6. Cognitive Architectures for Language Agents — Paper sobre planning, memory, y tool use en agentes

Módulo 11 — LangChain & LangGraph: From Chains to Agents