Gestión de Errores y Recuperación
Estrategias de gestión de errores en producción en chatflow-agent, jerarquía de excepciones del SDK, autocorrección de herramientas y reversión transaccional de turnos.
Construir sistemas multi-agente robustos exige una tolerancia a fallos estructurada. Caídas de proveedores de LLM, tiempos límite de red, argumentos inválidos de herramientas y excepciones imprevistas deben gestionarse de forma limpia sin corromper el estado de la conversación.
chatflow-agent implementa un modelo de recuperación por capas: los fallos no fatales de herramientas se retroalimentan al LLM para autocorrección autónoma, mientras que las fallas críticas del turno disparan reversiones (rollbacks) atómicas del estado.
Jerarquía de Excepciones del SDK
Todas las excepciones en chatflow-agent heredan de ChatFlowError. Esto permite que tu aplicación distinga entre errores propios del framework y excepciones genéricas de Python.
ChatFlowError (Base)
├── DependencyError (Dependencias opcionales faltantes de canales)
├── ToolExecutionError (Error no controlado durante ejecución de herramienta)
├── ToolSchemaError (Anotación de tipo de parámetro inválida) [v0.4.0rc1]
├── AgentHandoffError (Destino de handoff desconocido o bucle de transferencias)
├── ProviderError (Error de estado HTTP de API de LLM, fallo de red o tiempo límite)
├── ReentrantTurnError (Invocación de turno concurrente en sesión bloqueada) [v0.4.0rc1]
└── SessionDeletedError (Mensaje despachado a una sesión eliminada) [v0.4.0rc1]Tabla de Referencia de Excepciones
| Clase de Excepción | Hereda de | Generada Cuando | Estrategia de Recuperación |
|---|---|---|---|
ChatFlowError | Exception | Clase base para todas las excepciones del SDK. | Capturar en las fronteras superiores de petición. |
DependencyError | ChatFlowError | Un extra opcional de canal (ej. [telegram], [whatsapp]) no está instalado. | Instalar el extra requerido mediante pip install "chatflow-agent[extra]". |
ToolExecutionError | ChatFlowError | Una función de herramienta lanza una excepción no controlada en su ejecución. | Envuelto en ToolResult(is_error=True) para que el agente se autocorrija. |
ToolSchemaError Prerelease (0.4.0rc1) | ChatFlowError | Los argumentos de una función carecen de anotaciones de tipo válidas de Python. | Corregir las firmas de tipo de la función en tiempo de desarrollo. |
AgentHandoffError | ChatFlowError | El agente objetivo no existe en el registro del Runner o el turno supera max_handoffs_per_turn. | Verificar destinos de handoff y revisar condiciones de bucle de transferencias. |
ProviderError | ChatFlowError | El proveedor de modelos retorna un código de error HTTP (ej. 429, 500, 503). | Implementar retroceso exponencial o alternar a un motor de respaldo. |
ReentrantTurnError Prerelease (0.4.0rc1) | ChatFlowError, RuntimeError | Código dentro de un turno inicia otro turno para la misma sesión. | Utilizar colas de trabajos en segundo plano o despachadores de seguimiento. |
SessionDeletedError Prerelease (0.4.0rc1) | ChatFlowError | Se procesa un mensaje para una sesión eliminada durante la ejecución. | Recrear la sesión o notificar al usuario para reiniciar el flujo. |
Autocorrección Autónoma de Herramientas
Cuando una herramienta registrada lanza una excepción o recibe argumentos que no satisfacen la validación del esquema, el Runner captura la falla y devuelve un error estructurado al modelo en lugar de interrumpir abruptamente el turno:
import logging
from chatflow_agent import Agent, Runner, tool
logger = logging.getLogger("app.tools")
@tool
def process_refund(order_id: str, amount: float) -> str:
"""Issue a refund for an order.
Args:
order_id: Order identifier formatted as ORD-XXXX.
amount: Positive monetary value to refund.
"""
if not order_id.startswith("ORD-"):
raise ValueError("Invalid order format. Order ID must begin with 'ORD-'.")
if amount <= 0:
raise ValueError("Refund amount must be strictly greater than 0.")
return f"Refund of ${amount:.2f} processed for order {order_id}."
agent = Agent(
name="RefundBot",
model="gpt-4o",
tools=[process_refund],
instructions="Process refunds accurately. If an order ID format is invalid, clarify with the user.",
)
runner = Runner(starting_agent=agent)Qué Sucede Durante la Ejecución
- El modelo invoca
process_refund(order_id="12345", amount=50.0). process_refundlanzaValueError: Invalid order format. Order ID must begin with 'ORD-'..- El
Runnerasigna untrace_idúnico (UUID4) y añade unToolResult:{ "tool_call_id": "call_abc123", "name": "process_refund", "content": "Tool execution failed [trace_id: a8c2...]. Invalid order format. Order ID must begin with 'ORD-'.", "is_error": true } - El modelo recibe
is_error=Trueen la siguiente iteración y le informa al usuario: "El ID de pedido '12345' carece del prefijo 'ORD-'. ¿Podrías confirmar el número de pedido completo?"
Protección Contra Bucles de Reintento
Para evitar bucles de reintento infinitos en los que un agente falla reiteradamente la llamada a una herramienta, el Runner impone max_tool_iterations (predeterminado: 10). Si se alcanza este límite sin una respuesta final de texto, el runner retorna un mensaje de respaldo controlado sin bloquearse.
Reversión Transaccional de Turnos (Rollback)
Los turnos de enjambres multi-agente suelen modificar el historial de la conversación, transferir el diálogo a especialistas y actualizar metadatos de sesión. Si ocurre un fallo irrecuperable a mitad del turno (como una desconexión de red o límite de cuota del proveedor), dejar la sesión parcialmente ejecutada corrompería las interacciones posteriores.
El Runner garantiza la semántica de reversión a punto de control:
Inicio del Turno
├── Capturar Punto de Control: (history, active_agent, metadata)
├── Añadir Mensaje Entrante del Usuario
├── Ejecutar Turnos del LLM y Herramientas
│ ├── Éxito: Confirmar respuesta final del asistente en SessionStore
│ └── Fallo / CancelledError: Restaurar (history, active_agent, metadata)
└── Liberar Bloqueo de SesiónEjemplo de Reversión en Código
import asyncio
from chatflow_agent import Agent, Runner
from chatflow_agent.exceptions import ProviderError
def build_resilient_runner(agent: Agent) -> Runner:
"""Configure a runner with bounded handoffs and tool iterations."""
return Runner(
starting_agent=agent,
max_tool_iterations=6,
max_handoffs_per_turn=3,
)
async def execute_turn_with_recovery(
runner: Runner,
session_id: str,
user_message: str,
) -> str:
"""Execute a turn with explicit exception handling and graceful fallback."""
try:
response = await runner.run_async(
session_id=session_id,
user_message=user_message,
)
return response.content
except ProviderError as err:
# El estado fue revertido automáticamente al estado previo al turno
return "Our AI inference service is temporarily degraded. Please retry in a few moments."
except TimeoutError:
# Tiempo límite del turno excedido; punto de control restaurado
return "The request took too long to complete. Please try a simpler question."
except Exception as err:
return "An unexpected system error occurred. Our operations team has been notified."Tiempos Límite de Turno y Límites de Recursos
En el SDK v0.3.x, los tiempos de espera se gestionan a nivel del turno asíncrono utilizando la utilidad estándar asyncio.wait_for de Python. Ten en cuenta que un parámetro de palabra clave explícito turn_timeout en run_async se introduce en la versión de pre-lanzamiento v0.4.0rc1:
# [no-exec: illustrative turn timeout call]
import asyncio
# En v0.3.x, aplica tiempos límite de turno mediante asyncio.wait_for
response = await asyncio.wait_for(
runner.run_async(
session_id="customer-1029",
user_message="Analyze this quarterly financial audit report...",
),
timeout=45.0,
)Si el tiempo límite expira:
- Todas las subtareas asíncronas en ejecución se cancelan inmediatamente.
- Las ejecuciones síncronas de herramientas se esperan en hilos secundarios para prevenir interbloqueos en SQLite.
- El historial conversacional y los metadatos se revierten al punto de control previo al turno.
- Se lanza
asyncio.TimeoutErroral invocador.
Lista de Verificación de Buenas Prácticas
- Capturar
ChatFlowError: Intercepta excepciones del framework antes de propagarlas a los controladores HTTP. - Configurar Iteraciones Acotadas: Nunca definas
max_tool_iterationsomax_handoffs_per_turncon valores infinitos. - Retornar Errores Descriptivos en Herramientas: Lanza mensajes de
ValueErroroKeyErrordescriptivos dentro de las herramientas para que el agente pueda interpretarlos y autocorregirse. - Registrar IDs de Correlación: Captura el
trace_idgenerado en los registros delRunnerpara correlacionar reportes de usuarios con registros de trazas internas.
Webhooks y Canales Personalizados
Construye integraciones de webhook y adaptadores de canales personalizados utilizando BaseChannel, FastAPI y despacho asíncrono.
Configuración y Entorno
Gestiona variables de entorno, preajustes de proveedores, tiempos de espera y configuración de aplicaciones Twelve-Factor en despliegues de chatflow-agent.