Pular para conteúdo

SCHEDULE - Agendar Execução

O que é este Node?

O SCHEDULE é o node responsável por agendar a execução de ações em momentos futuros específicos, suportando tanto data/hora exata quanto expressões cron para recorrência (equivalente a cronjobs ou scheduled tasks).

Por que este Node existe?

Automações frequentemente precisam executar em momentos específicos no futuro. O SCHEDULE existe para:

  1. Lembretes e alertas: Enviar mensagem em data/hora específica
  2. Relatórios periódicos: Gerar relatório toda segunda às 9h
  3. Follow-ups automáticos: Agendar contato 3 dias após compra
  4. Manutenção recorrente: Executar limpeza de dados diariamente
  5. Campanhas agendadas: Lançar promoção em horário específico

Como funciona internamente?

Quando o SCHEDULE é executado, o sistema:

  1. Identifica scheduleType: datetime (único) ou cron (recorrente)
  2. Valida datetime/cron: Verifica formato correto
  3. Registra agendamento: Persiste na fila de tarefas
  4. Aguarda momento: Sistema aguarda até datetime/cron trigger
  5. Executa action: Quando hora chega, executa node especificado
  6. Se cron: Re-agenda próxima execução automaticamente

Código interno (logic-control-executor.service.ts:264-278):

private async executeSchedule(parameters: any, context: any): Promise<any> {
  const { scheduleType, datetime, cron, action } = parameters;

  this.logger.log(`📅 SCHEDULE - Type: ${scheduleType}, Action: ${action}`);

  return {
    success: true,
    action: 'execution_scheduled',
    scheduleType: scheduleType || 'datetime',
    scheduledFor: datetime || null,
    cronExpression: cron || null,
    scheduledAction: action || null,
    timestamp: new Date().toISOString()
  };
}

Quando você DEVE usar este Node?

Use SCHEDULE quando precisar executar ações no futuro:

Casos de uso

  1. Lembrete único: Enviar mensagem daqui a 2 horas
  2. Follow-up: Cobrar pagamento após 3 dias sem resposta
  3. Relatório diário: Gerar dashboard toda manhã às 8h
  4. Manutenção semanal: Limpar dados todo domingo à meia-noite
  5. Campanha sazonal: Lançar Black Friday em 25/11 às 00:00

Parâmetros

Campo Tipo Obrigatório Descrição
scheduleType string Sim datetime (única vez) ou cron (recorrente)
datetime string Se datetime Data/hora no formato ISO 8601
cron string Se cron Expressão cron (minuto hora dia mês dia-semana)
action string Sim Node ID da ação a executar quando trigger ocorrer

Parâmetros Detalhados

scheduleType (string, obrigatório)

O que é: Define se execução é única (datetime) ou recorrente (cron).

Valores aceitos: - "datetime": Executa UMA VEZ em data/hora específica - "cron": Executa RECORRENTEMENTE baseado em expressão cron

Flow completo para testar (datetime):

{
  "name": "Teste SCHEDULE - ScheduleType DateTime",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Agendar Lembrete",
        "parameters": {
          "message": "⏰ Agendando lembrete para daqui 5 minutos..."
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Agendar Envio",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "2025-12-31T23:59:00Z",
          "action": "message_lembrete"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmação",
        "parameters": {
          "message": "✅ Lembrete agendado com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_lembrete",
      "type": "message",
      "position": { "x": 500, "y": 300 },
      "data": {
        "label": "Lembrete Agendado",
        "parameters": {
          "message": "🔔 Este é seu lembrete agendado!"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Teste: Define datetime futuro. Flow continua imediatamente, mas action executa apenas no datetime especificado!

datetime (string, condicional)

O que é: Data e hora exata para execução única (formato ISO 8601).

Obrigatório: Apenas se scheduleType="datetime"

Formato: YYYY-MM-DDTHH:mm:ss.sssZ (ISO 8601 com timezone)

Exemplos válidos: - "2025-12-31T23:59:00Z" (UTC) - "2025-06-15T14:30:00-03:00" (horário de Brasília) - "2025-01-01T00:00:00.000Z" (com milissegundos)

Flow completo para testar:

{
  "name": "Teste SCHEDULE - DateTime",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Definir Data",
        "parameters": {
          "name": "data_envio",
          "value": "2025-12-31T23:59:00Z",
          "operation": "set"
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Agendar Feliz Ano Novo",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "{{data_envio}}",
          "action": "message_ano_novo"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmação",
        "parameters": {
          "message": "📅 Mensagem de Ano Novo agendada para 31/12 às 23:59!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_ano_novo",
      "type": "message",
      "position": { "x": 500, "y": 300 },
      "data": {
        "label": "Feliz Ano Novo",
        "parameters": {
          "message": "🎉 FELIZ ANO NOVO! 🎆"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Flow executa imediatamente e agenda. No dia 31/12 às 23:59 UTC, message_ano_novo será executado!

cron (string, condicional)

O que é: Expressão cron para execuções recorrentes.

Obrigatório: Apenas se scheduleType="cron"

Formato: minuto hora dia mês dia-da-semana

Exemplos comuns: - "0 9 * * *" → Todo dia às 9:00 - "30 14 * * 1-5" → Segunda a sexta às 14:30 - "0 0 1 * *" → Primeiro dia de cada mês à meia-noite - "*/15 * * * *" → A cada 15 minutos - "0 8 * * 1" → Toda segunda-feira às 8:00

Flow completo para testar:

{
  "name": "Teste SCHEDULE - Cron",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Configurar Bom Dia",
        "parameters": {
          "message": "☀️ Configurando mensagem de bom dia diária..."
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Agendar Recorrente",
        "parameters": {
          "scheduleType": "cron",
          "cron": "0 9 * * *",
          "action": "message_bom_dia"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Ativo",
        "parameters": {
          "message": "✅ Bom dia será enviado todo dia às 9h!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_bom_dia",
      "type": "message",
      "position": { "x": 500, "y": 300 },
      "data": {
        "label": "Bom Dia",
        "parameters": {
          "message": "☕ Bom dia! Tenha um ótimo dia!"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Teste: Flow executa imediatamente e agenda. TODOS OS DIAS às 9h, message_bom_dia será executado automaticamente!

action (string, obrigatório)

O que é: ID do node que será executado quando o agendamento disparar.

Flow completo para testar:

{
  "name": "Teste SCHEDULE - Action",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Pedir Nome",
        "parameters": {
          "message": "Qual seu nome?",
          "variable": "nome"
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Agendar Follow-up",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "2025-12-15T10:00:00Z",
          "action": "message_followup"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmação",
        "parameters": {
          "message": "✅ {{nome}}, agendamos um follow-up com você!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_followup",
      "type": "message",
      "position": { "x": 500, "y": 300 },
      "data": {
        "label": "Follow-up",
        "parameters": {
          "message": "Olá {{nome}}! Como você está? Vamos continuar nossa conversa?"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Digite seu nome. Flow continua e confirma. Na data agendada, message_followup executa com variável {{nome}} preservada!

Exemplo 1: Lembrete Único

Objetivo: Agendar lembrete para data/hora específica

{
  "name": "SCHEDULE - Lembrete Consulta",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Agendar Consulta",
        "parameters": {
          "message": "Para quando deseja agendar sua consulta? (YYYY-MM-DD HH:mm)",
          "variable": "data_consulta"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar Data",
        "parameters": {
          "message": "📅 Agendando consulta para {{data_consulta}}"
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Agendar Lembrete 1 dia Antes",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "{{data_consulta}}",
          "action": "message_lembrete"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Sucesso",
        "parameters": {
          "message": "✅ Consulta agendada! Você receberá um lembrete."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_lembrete",
      "type": "message",
      "position": { "x": 700, "y": 300 },
      "data": {
        "label": "Lembrete",
        "parameters": {
          "message": "🔔 LEMBRETE: Você tem uma consulta amanhã às {{data_consulta}}!"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "message_1" },
    { "source": "message_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Para quando deseja agendar sua consulta? (YYYY-MM-DD HH:mm)
Usuário: 2025-12-20 14:30
Sistema: 📅 Agendando consulta para 2025-12-20 14:30
Sistema: ✅ Consulta agendada! Você receberá um lembrete.

[No dia 20/12 às 14:30]
Sistema: 🔔 LEMBRETE: Você tem uma consulta amanhã às 2025-12-20 14:30!

Exemplo 2: Relatório Semanal com Cron

Objetivo: Gerar relatório toda segunda-feira às 9h

{
  "name": "SCHEDULE - Relatório Semanal",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Configurar",
        "parameters": {
          "message": "📊 Ativando relatório semanal automático..."
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Agendar Toda Segunda 9h",
        "parameters": {
          "scheduleType": "cron",
          "cron": "0 9 * * 1",
          "action": "message_relatorio"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Ativo",
        "parameters": {
          "message": "✅ Relatório semanal ativado! Toda segunda às 9h."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_relatorio",
      "type": "message",
      "position": { "x": 500, "y": 300 },
      "data": {
        "label": "Relatório",
        "parameters": {
          "message": "📈 RELATÓRIO SEMANAL\n\nVendas: R$ 12.500\nNovos clientes: 45\nTicket médio: R$ 278"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 📊 Ativando relatório semanal automático...
Sistema: ✅ Relatório semanal ativado! Toda segunda às 9h.

[Toda segunda-feira às 9h]
Sistema: 📈 RELATÓRIO SEMANAL

Vendas: R$ 12.500
Novos clientes: 45
Ticket médio: R$ 278

Exemplo 3: Follow-up Múltiplo com Delays Progressivos

Objetivo: Sistema de follow-up com 3 tentativas em intervalos crescentes (1 dia, 3 dias, 7 dias)

{
  "name": "SCHEDULE - Follow-up Inteligente",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Pedir Nome",
        "parameters": {
          "message": "Qual seu nome?",
          "variable": "nome"
        }
      }
    },
    {
      "id": "input_2",
      "type": "input",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Pedir Email",
        "parameters": {
          "message": "Qual seu email?",
          "variable": "email"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmação Inicial",
        "parameters": {
          "message": "✅ Obrigado {{nome}}! Você receberá nosso conteúdo em {{email}}"
        }
      }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Agendar Follow-up 1 (1 dia)",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "2025-12-16T10:00:00Z",
          "action": "message_followup_1"
        }
      }
    },
    {
      "id": "schedule_2",
      "type": "schedule",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Agendar Follow-up 2 (3 dias)",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "2025-12-18T10:00:00Z",
          "action": "message_followup_2"
        }
      }
    },
    {
      "id": "schedule_3",
      "type": "schedule",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Agendar Follow-up 3 (7 dias)",
        "parameters": {
          "scheduleType": "datetime",
          "datetime": "2025-12-22T10:00:00Z",
          "action": "message_followup_3"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1500, "y": 100 },
      "data": {
        "label": "Concluído",
        "parameters": {
          "message": "🎯 Sistema de follow-up configurado com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1700, "y": 100 },
      "data": { "label": "Fim" }
    },
    {
      "id": "message_followup_1",
      "type": "message",
      "position": { "x": 900, "y": 300 },
      "data": {
        "label": "Follow-up Dia 1",
        "parameters": {
          "message": "Olá {{nome}}! 👋\n\nComo está sendo sua experiência? Precisa de ajuda?"
        }
      }
    },
    {
      "id": "message_followup_2",
      "type": "message",
      "position": { "x": 1100, "y": 300 },
      "data": {
        "label": "Follow-up Dia 3",
        "parameters": {
          "message": "{{nome}}, estamos aqui! 💙\n\nTem alguma dúvida sobre nossos serviços?"
        }
      }
    },
    {
      "id": "message_followup_3",
      "type": "message",
      "position": { "x": 1300, "y": 300 },
      "data": {
        "label": "Follow-up Dia 7",
        "parameters": {
          "message": "Última chance, {{nome}}! 🎁\n\nOferta especial de 20% OFF expira hoje!\n\nEmail: {{email}}"
        }
      }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "input_2" },
    { "source": "input_2", "target": "message_1" },
    { "source": "message_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "schedule_2" },
    { "source": "schedule_2", "target": "schedule_3" },
    { "source": "schedule_3", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Qual seu nome?
Usuário: Maria
Sistema: Qual seu email?
Usuário: maria@example.com
Sistema: ✅ Obrigado Maria! Você receberá nosso conteúdo em maria@example.com
Sistema: 🎯 Sistema de follow-up configurado com sucesso!

[Dia 1 - 16/12 às 10h]
Sistema: Olá Maria! 👋
Como está sendo sua experiência? Precisa de ajuda?

[Dia 3 - 18/12 às 10h]
Sistema: Maria, estamos aqui! 💙
Tem alguma dúvida sobre nossos serviços?

[Dia 7 - 22/12 às 10h]
Sistema: Última chance, Maria! 🎁
Oferta especial de 20% OFF expira hoje!
Email: maria@example.com

Resposta do Node

{
  "success": true,
  "action": "execution_scheduled",
  "scheduleType": "datetime",
  "scheduledFor": "2025-12-31T23:59:00Z",
  "cronExpression": null,
  "scheduledAction": "message_feliz_ano_novo",
  "timestamp": "2025-01-15T10:30:00.000Z"
}

Guia de Expressões Cron

┌───────────── minuto (0 - 59)
│ ┌───────────── hora (0 - 23)
│ │ ┌───────────── dia do mês (1 - 31)
│ │ │ ┌───────────── mês (1 - 12)
│ │ │ │ ┌───────────── dia da semana (0 - 6) (0=Domingo)
│ │ │ │ │
│ │ │ │ │
* * * * *

Exemplos práticos:

Cron Descrição
0 9 * * * Todo dia às 9:00
30 14 * * 1-5 Segunda a sexta às 14:30
0 0 1 * * Primeiro dia do mês à meia-noite
*/15 * * * * A cada 15 minutos
0 8,12,18 * * * Às 8h, 12h e 18h
0 0 * * 0 Todo domingo à meia-noite
0 22 * * 1-5 Segunda a sexta às 22h

Boas Práticas

SIM:

  • Use datetime para eventos únicos (lançamento, lembrete)
  • Use cron para recorrência (relatórios, limpeza, backups)
  • Sempre use timezone explícito em datetime (Z para UTC, -03:00 para BRT)
  • Teste cron expressions em https://crontab.guru
  • Preserve variáveis do context para action agendado

NÃO:

  • Não use datetime no passado (não executará)
  • Não esqueça timezone (pode executar em horário errado)
  • Não use cron muito frequente (< 5 min pode sobrecarregar)
  • Não confie em action que depende de variáveis temporárias
  • Não use para delays curtos (< 1 min, use DELAY ao invés)

Dicas

💡 Datetime vs Delay: Use SCHEDULE para > 1 hora, DELAY para < 1 hora 💡 Timezone: Sempre especifique timezone para evitar confusão (UTC, BRT, etc) 💡 Cron testing: Use https://crontab.guru para validar expressões cron 💡 Context preservation: Variáveis do context são preservadas até action executar 💡 Cancelamento: Implemente lógica de cancelamento se necessário (salvar schedule_id)

Próximo Node

RETRY - Tentar novamente em caso de erro → DELAY - Aguardar tempo (para delays curtos) → VARIABLE - Preservar dados para action agendado