LangChain manejo de errores y depuración
En el desarrollo de Agent, inevitablemente se encontrarán varios errores. Este artículo recopila los tipos de errores comunes, métodos de depuración y mejores prácticas.
Tipos de errores comunes
| Tipo de error | Causa típica | Solución |
|---|---|---|
| ImportError | Paquete del proveedor no instalado | pip install langchain-deepseek, etc. |
| Error de API Key | .env no configurado o Key inválida | Verificar las variables de entorno y la validez de la Key |
| Error de tiempo de espera | Problema de red o respuesta lenta del modelo | Configurar el parámetro timeout |
| Límite de tokens excedido | Historial de mensajes demasiado largo | Usar trim_messages() para recortar |
| Error de llamada a herramienta | Excepción interna de la herramienta | Usar ToolException + handle_tool_errors |
| Formato de respuesta del modelo incorrecto | La salida del modelo no coincide con lo esperado | Usar salida estructurada + handle_errors |
ModelRetryMiddleware: reintento de llamadas al modelo
LangChain proporciona middleware de reintento integrado:
Ejemplo
from langchain.agents.middleware import ModelRetryMiddleware
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
# Middleware de reintento de modelo integrado
# Reintenta automáticamente cuando falla la llamada al modelo
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash", timeout=30, max_retries=2),
middleware=[
ModelRetryMiddleware(
max_retries=3, # Reintenta hasta 3 veces
backoff_factor=2.0, # Factor de retroceso (2s, 4s, 8s)
)
],
system_prompt="Eres el asistente del tutorial para novatos EJEMPLO.",
)
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
# Middleware de reintento de modelo integrado
# Reintenta automáticamente cuando falla la llamada al modelo
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash", timeout=30, max_retries=2),
middleware=[
ModelRetryMiddleware(
max_retries=3, # Reintenta hasta 3 veces
backoff_factor=2.0, # Factor de retroceso (2s, 4s, 8s)
)
],
system_prompt="Eres el asistente del tutorial para novatos EJEMPLO.",
)
ToolRetryMiddleware: reintento de llamadas a herramientas
Ejemplo
from langchain.agents.middleware import ToolRetryMiddleware
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[my_tool],
middleware=[
ToolRetryMiddleware(
max_retries=3,
backoff_factor=1.5,
)
],
)
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[my_tool],
middleware=[
ToolRetryMiddleware(
max_retries=3,
backoff_factor=1.5,
)
],
)
El RetryMiddleware integrado y los @wrap_model_call / @wrap_tool_call personalizados pueden coexistir. El middleware integrado se coloca al frente de la lista de middleware como la capa más externa de protección.
debug=True: registros detallados
Ejemplo
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
# Activa el modo debug y muestra registros detallados de ejecución
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash"),
debug=True, # Activa los registros de depuración
system_prompt="Eres el asistente del tutorial para novatos EJEMPLO.",
)
# Al ejecutar se imprimirá:
# - Estado de entrada de cada nodo
# - Estado de salida de cada nodo
# - Decisión de salto de las aristas (edge)
result = agent.invoke({
"messages": [HumanMessage(content="Hola")]
})
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
# Activa el modo debug y muestra registros detallados de ejecución
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash"),
debug=True, # Activa los registros de depuración
system_prompt="Eres el asistente del tutorial para novatos EJEMPLO.",
)
# Al ejecutar se imprimirá:
# - Estado de entrada de cada nodo
# - Estado de salida de cada nodo
# - Decisión de salto de las aristas (edge)
result = agent.invoke({
"messages": [HumanMessage(content="Hola")]
})
Ejemplo de salida con debug=True:
[DEBUG] Starting graph execution
[DEBUG] Executing node: model
[DEBUG] Node 'model' input: {'messages': [HumanMessage(content='你好')]}
[DEBUG] Node 'model' output: {'messages': [AIMessage(content='你好!...')]}
[DEBUG] Edge 'model' -> '__end__': routing to __end__
[DEBUG] Graph execution complete
stream_mode="debug": la información de depuración más detallada
Ejemplo
# Obtén la información más detallada mediante stream_mode="debug"
for event in agent.stream(
{"messages": [HumanMessage(content="Hola")]},
stream_mode="debug",
):
# event incluye: nombre del nodo, entrada, salida, marca de tiempo, información de la tarea, etc.
print(f"[{event['type']}] {event.get('name', '')}")
if 'input' in event:
print(f" Entrada: {event['input']}")
if 'output' in event:
print(f" Salida: {event['output']}")
for event in agent.stream(
{"messages": [HumanMessage(content="Hola")]},
stream_mode="debug",
):
# event incluye: nombre del nodo, entrada, salida, marca de tiempo, información de la tarea, etc.
print(f"[{event['type']}] {event.get('name', '')}")
if 'input' in event:
print(f" Entrada: {event['input']}")
if 'output' in event:
print(f" Salida: {event['output']}")
Solución de problemas comunes
Problema 1: El modelo sigue llamando a la herramienta sin detenerse
Posible causa: la información devuelta por la herramienta es insuficiente y el modelo no puede determinar si la tarea está completa. Solución:
- Hacer que la herramienta devuelva información más clara (por ejemplo, "tarea completada")
- Configurar la condición de detención en system_prompt
- Usar after_model para verificar el número de iteraciones, y después de superar el umbral usar jump_to="end"
Problema 2: El modelo llama a la herramienta o los parámetros incorrectos
Posible causa: la descripción de la herramienta no es clara. Solución:
- Mejorar el docstring de la función de la herramienta
- Usar args_schema para limitar el rango de parámetros
- Usar un modelo mejor (por ejemplo, deepseek-v4-pro en lugar de deepseek-v4-flash)
Problema 3: La memoria de conversación no funciona
Lista de verificación:
- ¿Se ha pasado el parámetro checkpointer?
- ¿Se ha utilizado el mismo thread_id cada vez?
- Si se usa SqliteSaver, ¿existe el archivo de base de datos y es escribible?