Organización de código en LangGraph para sistemas complejos de AI
Clase 11 de 26 • Curso para Crear Agentes de AI con LangGraph
Resumen
Escalar un sistema con múltiples nodos, prompts, RAGs y tools exige una organización clara. Aquí verás cómo refactorizar hacia una arquitectura modular en Landgraf para mejorar mantenimiento, visibilidad de la orquestación y crecimiento controlado, separando agente, estado, nodos, prompts y tools en carpetas consistentes.
¿Por qué reorganizar el código para escalar en Landgraf?
Una sola base de código en un archivo se vuelve frágil cuando crecen los nodos y las dependencias. La propuesta: convertir cada agente en una carpeta con subcarpetas por nodo y archivos específicos para estado, grafo, prompts y tools. Así:
- Mantenibilidad: localizar y mejorar un nodo es inmediato.
- Escalabilidad: añadir nodos no rompe la base existente.
- Claridad: cada responsabilidad vive en su lugar: estado, grafo, nodo, prompt, tools.
- Visibilidad: entender qué pasa con los nodos y la orquestación es más simple.
Conceptos clave integrados: agente y grafo del flujo, nodos con su propio large language model (LLM), system prompt, tools y manejo del estado del mensaje. También se menciona el uso de LangGraph UI para depurar y validar el flujo.
¿Cómo estructurar agentes, nodos y prompts para RAG?
La idea central: el agente “Support” deja de ser un archivo y pasa a ser una carpeta. Dentro, se separan el estado, el grafo y los nodos. Cada nodo tiene su propio prompt y, si aplica, sus tools.
¿Qué carpetas y archivos crear?
Estructura sugerida para “Support”:
agents/
support/
__init__.py
state.py # estado del mensaje.
agent.py # construcción del grafo del agente.
nodos/
extractor/
__init__.py
node.py # lógica del nodo extractor.
prompt.py # system prompt del extractor.
conversation/
__init__.py
node.py # lógica del nodo conversation.
prompt.py # system prompt del conversation.
tools.py # tools ligadas a este nodo.
Puntos clave: - Cada nodo es una carpeta con su node.py, prompt.py y, si aplica, tools.py. - Los imports se corrigen para apuntar a paths claros: por ejemplo, al estado desde "agents.support.state". - Se evita crear carpetas innecesarias como “rutas” si aún no se usan.
¿Cómo separar prompts y tools por nodo?
- Prompt por nodo: se define un archivo prompt.py por nodo con su system prompt declarado de forma explícita.
- Tools por nodo: en conversation/tools.py se listan las tools y se exportan en un array para inyectarlas al LLM del nodo.
Ejemplo mínimo de prompt y combinación con historial del estado:
# extractor/prompt.py
SYSTEM_PROMPT = """
Tú eres un asistente que ayuda a extraer información dada una conversación.
"""
# extractor/node.py
from agents.support.state import message_state
from .prompt import SYSTEM_PROMPT
# history proviene del estado; se concatena al prompt del sistema.
def build_messages(history):
return [SYSTEM_PROMPT] + history
Notas prácticas: - Se usa un system prompt claro para guiar el nodo extractor. - La concatenación del system prompt con el history puede requerir ajustarlo a tu API de mensajes: array de uno o tupla, según el formato que uses.
¿Cómo se construye el agente con el grafo?
- agent.py importa el estado y cada nodo ya modularizado.
- Cada nodo declara su propio LLM: por ejemplo, conversation con OpenAI para habilitar tools.
- Se inyectan prompts y tools en el nodo correspondiente, manteniendo la configuración aislada.
Ejemplo mínimo del nodo conversation con tools:
# conversation/tools.py
# Define y exporta las tools de este nodo.
tools = [
# ...instancias de tools específicas del nodo...
]
# conversation/node.py
from .tools import tools
from .prompt import SYSTEM_PROMPT
def configure_conversation_node(llm):
llm_with_tools = llm.bind_tools(tools)
# se inyecta el system prompt simple; la dinamización llegará después.
return {"llm": llm_with_tools, "system_prompt": SYSTEM_PROMPT}
¿Qué prácticas aplicar para mantener y crecer el proyecto?
- Un agente, una carpeta: facilita navegación y escalabilidad.
- Estado centralizado: un state.py con el message state único.
- Nodo autocontenido: cada nodo con su node.py, prompt.py y tools.py si aplica.
- LLM por nodo: declarar en el nodo el large language model que usará.
- Prompts declarativos: mantener el system prompt por archivo y por nodo.
- Tools agrupadas: exportar un array de tools por nodo y enlazarlas al LLM.
- Imports limpios: rutas explícitas evitan confusiones y errores.
- Refactor incremental: trasladar estado, luego nodos, luego prompts y tools.
- Prueba continua: validar en LangGraph UI y en el debugger que todo sigue funcionando.
- Preparación para prompts dinámicos: dejar el system prompt simple ahora y planear la inyección de variables después.
Si te sirvió esta guía práctica de organización y refactor, cuéntame en comentarios qué nodo planeas modularizar primero y por qué.