Estados de Ejecucion
Las ejecuciones de agentes siguen una maquina de estados definida. Entender estos estados es clave para diseñar flujos robustos.
Maquina de Estados
┌─────────┐
│ PENDING │
└────┬────┘
│ start
▼
┌─────────┐
┌─────────│ RUNNING │─────────┐
│ └────┬────┘ │
│ │ │
wait │ done │ fail │
▼ ▼ ▼
┌─────────┐ ┌───────────┐ ┌────────┐
│ WAITING │ │ COMPLETED │ │ FAILED │
└────┬────┘ └───────────┘ └────────┘
│ ▲ ▲
resume │ │ │
└──────────────┴──────────────┘
Estados Principales
| Estado | Descripcion | Siguiente |
|---|---|---|
| PENDING | Ejecucion creada, en cola | RUNNING |
| RUNNING | Ejecutando acciones | WAITING, COMPLETED, FAILED |
| WAITING | Esperando evento externo | RUNNING (resume) |
| COMPLETED | Finalizado exitosamente | (terminal) |
| FAILED | Finalizado con error | (terminal) |
| TIMEOUT | Tiempo de espera excedido | (terminal) |
| CANCELLED | Cancelado manualmente | (terminal) |
Estado PENDING
Cuando Ocurre
- Ejecucion recien creada
- En cola esperando recursos
- Esperando su turno (rate limiting)
Transiciones
PENDING → RUNNING : Cuando el sistema inicia la ejecucion
PENDING → CANCELLED : Si se cancela antes de iniciar
Duracion Tipica
- Normal: < 1 segundo
- Con cola: hasta 30 segundos
- Con rate limit: variable
Estado RUNNING
Cuando Ocurre
- Ejecutando acciones secuencialmente
- Procesando logica del flujo
- Comunicandose con servicios externos
Transiciones
RUNNING → WAITING : Accion requiere esperar
RUNNING → COMPLETED : Todas las acciones completadas
RUNNING → FAILED : Error en alguna accion
Logs Tipicos
[14:32:15] Ejecucion iniciada
[14:32:15] Accion 1: send_message - iniciando
[14:32:16] Accion 1: send_message - completada
[14:32:16] Accion 2: wait_for_response - iniciando
[14:32:16] Accion 2: wait_for_response - esperando...
Estado WAITING (Detallado)
El estado WAITING es el mas complejo. La ejecucion se pausa esperando un evento externo.
Tipos de Espera
| waitingFor | Descripcion | Evento de Resume |
|---|---|---|
| response | Espera mensaje del usuario | MESSAGE_RECEIVED |
| agent | Espera que hijo termine | AGENT_COMPLETED |
| document | Espera documentos | DOCUMENT_UPLOADED |
| signature | Espera firma | SIGNATURE_COMPLETED |
| test | Espera evaluacion | TEST_COMPLETED |
| event | Espera evento calendario | EVENT_COMPLETED |
| delay | Espera tiempo programado | SCHEDULE_REACHED |
Estructura de WAITING
Cuando una ejecucion entra en WAITING, se guardan estos campos:
{
"status": "waiting",
"waitingFor": "response", // Tipo de espera
"waitingUntil": "2024-01-15T10:00:00Z", // Timeout
"waitingData": { // Contexto de espera
"threadId": 123,
"expectedFrom": "postulant",
"timeout": "24h"
}
}
Wait for Response
La accion wait_for_response espera un mensaje del usuario.
Flujo:
1. Agente envia mensaje
2. Agente ejecuta wait_for_response
3. Ejecucion → WAITING (waitingFor: "response")
4. ... tiempo pasa ...
5. Usuario responde en chat
6. Sistema detecta MESSAGE_RECEIVED
7. Sistema resume ejecucion
8. Ejecucion → RUNNING
9. Variable {{lastResponse}} disponible
Configuracion:
{
"actionType": "wait_for_response",
"parameters": {
"timeout": "24h",
"onTimeout": "continue"
}
}
Wait for Agent (Parent-Child)
Cuando trigger_agent usa waitForCompletion=true y el hijo entra en WAITING.
Flujo:
1. Padre ejecuta trigger_agent
2. Hijo inicia (PENDING → RUNNING)
3. Hijo ejecuta wait_for_response
4. Hijo → WAITING
5. Padre → WAITING (waitingFor: "agent")
6. ... usuario responde ...
7. Hijo resume → completa
8. Hijo emite AGENT_COMPLETED
9. Padre resume automaticamente
10. Padre continua al siguiente nodo
Variables disponibles post-resume:
{
"triggeredExecutionId": 456,
"childExecutionStatus": "completed",
"childExecutionSuccess": true,
"lastResponse": "mensaje del usuario",
// ... variables del hijo
}
Wait for Document
Espera a que el usuario suba documentos solicitados.
Flujo:
1. Agente solicita documentos (request_document)
2. Se crea solicitud pendiente
3. Ejecucion → WAITING (waitingFor: "document")
4. ... usuario sube documentos ...
5. Sistema detecta todos los docs subidos
6. Ejecucion resume
7. Variable {{documentUrls}} disponible
Wait for Signature
Espera firma electronica.
Flujo:
1. Agente solicita firma (request_signature)
2. Se envia documento para firmar
3. Ejecucion → WAITING (waitingFor: "signature")
4. ... usuario firma ...
5. Sistema detecta firma completada
6. Ejecucion resume
7. Variables {{signedDocumentUrl}}, {{signedAt}} disponibles
Wait for Test
Espera que el usuario complete una evaluacion.
Flujo:
1. Agente asigna test (assign_test)
2. Usuario recibe notificacion
3. Ejecucion → WAITING (waitingFor: "test")
4. ... usuario completa test ...
5. Sistema detecta test completado
6. Ejecucion resume
7. Variables {{testScore}}, {{testResult}} disponibles
Transiciones y Eventos
Diagrama de Eventos
┌─────────────────────────────────────────────────────────────────┐
│ SISTEMA DE EVENTOS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ MESSAGE_RECEIVED ──────┬──────────▶ Resume (waitingFor=response)
│ │ │
│ AGENT_COMPLETED ───────┼──────────▶ Resume (waitingFor=agent) │
│ │ │
│ DOCUMENT_UPLOADED ─────┼──────────▶ Resume (waitingFor=document)
│ │ │
│ SIGNATURE_COMPLETED ───┼──────────▶ Resume (waitingFor=signature)
│ │ │
│ TEST_COMPLETED ────────┼──────────▶ Resume (waitingFor=test) │
│ │ │
│ SCHEDULE_REACHED ──────┴──────────▶ Resume (waitingFor=delay) │
│ │
└─────────────────────────────────────────────────────────────────┘
Resume Execution
Cuando llega el evento esperado:
// AgentGraph.resumeExecution()
1. Cargar checkpoint de LangGraph
2. Actualizar estado:
- shouldWait: false
- variables: { lastResponse, ... }
3. Reanudar grafo: graph.invoke(null, config)
4. Ejecucion continua desde donde quedo
Timeouts
Configuracion de Timeout
Cada tipo de espera tiene timeout configurable:
| Tipo | Default | Maximo |
|---|---|---|
| response | 24 horas | 7 dias |
| agent | 1 hora | 24 horas |
| document | 7 dias | 30 dias |
| signature | 7 dias | 30 dias |
| test | 7 dias | 30 dias |
| delay | variable | 30 dias |
Acciones al Timeout
{
"timeout": "24h",
"onTimeout": "continue", // o "fail" o "retry"
"timeoutActions": [
{
"actionType": "send_message",
"parameters": {
"message": "No recibimos tu respuesta. Te contactaremos pronto."
}
}
]
}
| onTimeout | Comportamiento |
|---|---|
| continue | Continua al siguiente nodo |
| fail | Marca ejecucion como TIMEOUT |
| retry | Reintenta la accion de espera |
Estados Terminales
COMPLETED
Ejecucion exitosa. Todas las acciones completaron.
{
"status": "completed",
"completedAt": "2024-01-10T14:35:00Z",
"resultType": "success",
"resultSummary": "Flujo completado exitosamente",
"variables": { ... } // Estado final
}
FAILED
Error que detuvo la ejecucion.
{
"status": "failed",
"completedAt": "2024-01-10T14:35:00Z",
"resultType": "failure",
"errorMessage": "Error al enviar email: recipient not found",
"failedActionId": 3
}
TIMEOUT
Tiempo de espera excedido.
{
"status": "timeout",
"completedAt": "2024-01-11T14:32:00Z",
"resultType": "timeout",
"resultSummary": "Timeout esperando respuesta del usuario"
}
CANCELLED
Cancelado por usuario o sistema.
{
"status": "cancelled",
"completedAt": "2024-01-10T15:00:00Z",
"resultType": "cancelled",
"cancelledBy": "user",
"cancelReason": "Usuario solicito cancelacion"
}
Checkpoints y Persistencia
LangGraph Checkpointing
El estado se persiste en Redis para sobrevivir reinicios:
{
"thread_id": "execution_123",
"checkpoint": {
"currentStep": 3,
"variables": { ... },
"conversationHistory": [ ... ],
"shouldWait": true,
"waitingFor": "response",
"nextActionId": 4
}
}
Recuperacion
Despues de un reinicio del servidor:
- Sistema detecta ejecuciones en WAITING
- Re-registra listeners de eventos
- Cuando llega evento, resume desde checkpoint
- Ejecucion continua normalmente
Monitoreo de Estados
Query de Estados Activos
SELECT
status,
COUNT(*) as count,
AVG(TIMESTAMPDIFF(SECOND, createdAt, NOW())) as avg_age_seconds
FROM agent_execution
WHERE status IN ('pending', 'running', 'waiting')
GROUP BY status;
Ejecuciones en WAITING
SELECT
id,
agentId,
waitingFor,
waitingUntil,
TIMESTAMPDIFF(HOUR, updatedAt, NOW()) as waiting_hours
FROM agent_execution
WHERE status = 'waiting'
ORDER BY waitingUntil;
Detectar Stuck
SELECT *
FROM agent_execution
WHERE status = 'waiting'
AND waitingUntil < NOW() -- Timeout pasado pero no procesado
AND updatedAt < NOW() - INTERVAL 1 HOUR;
Debugging
Logs por Estado
PENDING → RUNNING:
[AgentGraph] Starting execution 123
[AgentGraph] Loading agent configuration...
RUNNING → WAITING:
[AgentGraph] Action wait_for_response requires wait
[AgentGraph] Saving checkpoint for execution 123
[AgentGraph] Execution 123 entering WAITING state (waitingFor: response)
WAITING → RUNNING (resume):
[AgentGraph] Resuming execution 123
[AgentGraph] Updating state: shouldWait=false, lastResponse="..."
[AgentGraph] Continuing from checkpoint
RUNNING → COMPLETED:
[AgentGraph] Execution 123 completed with result: success
[AgentGraph] Emitting AGENT_COMPLETED event
[AgentGraph] Released locks on 1 thread(s)
Problemas Comunes
| Problema | Causa | Solucion |
|---|---|---|
| Stuck en WAITING | Evento nunca llega | Verificar listener, revisar timeout |
| Resume no funciona | Checkpoint corrupto | Reiniciar ejecucion |
| Timeout no dispara | Job scheduler detenido | Verificar BullMQ |
| Variables perdidas | Checkpoint incompleto | Verificar persistencia Redis |
Proximos Pasos
- Acumulacion de Variables - Flujo de datos
- Agentes Encadenados - Parent-child
- Logs de Ejecuciones - Debugging