Skip to content
chatflow-agent logochatflow-agent
Patrones de Producción

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ónHereda deGenerada CuandoEstrategia de Recuperación
ChatFlowErrorExceptionClase base para todas las excepciones del SDK.Capturar en las fronteras superiores de petición.
DependencyErrorChatFlowErrorUn extra opcional de canal (ej. [telegram], [whatsapp]) no está instalado.Instalar el extra requerido mediante pip install "chatflow-agent[extra]".
ToolExecutionErrorChatFlowErrorUna 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)ChatFlowErrorLos 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.
AgentHandoffErrorChatFlowErrorEl 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.
ProviderErrorChatFlowErrorEl 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, RuntimeErrorCó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)ChatFlowErrorSe 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

  1. El modelo invoca process_refund(order_id="12345", amount=50.0).
  2. process_refund lanza ValueError: Invalid order format. Order ID must begin with 'ORD-'..
  3. El Runner asigna un trace_id único (UUID4) y añade un ToolResult:
    {
      "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
    }
  4. El modelo recibe is_error=True en 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ón

Ejemplo 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:

  1. Todas las subtareas asíncronas en ejecución se cancelan inmediatamente.
  2. Las ejecuciones síncronas de herramientas se esperan en hilos secundarios para prevenir interbloqueos en SQLite.
  3. El historial conversacional y los metadatos se revierten al punto de control previo al turno.
  4. Se lanza asyncio.TimeoutError al 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_iterations o max_handoffs_per_turn con valores infinitos.
  • Retornar Errores Descriptivos en Herramientas: Lanza mensajes de ValueError o KeyError descriptivos dentro de las herramientas para que el agente pueda interpretarlos y autocorregirse.
  • Registrar IDs de Correlación: Captura el trace_id generado en los registros del Runner para correlacionar reportes de usuarios con registros de trazas internas.

On this page