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:
- Lembretes e alertas: Enviar mensagem em data/hora específica
- Relatórios periódicos: Gerar relatório toda segunda às 9h
- Follow-ups automáticos: Agendar contato 3 dias após compra
- Manutenção recorrente: Executar limpeza de dados diariamente
- Campanhas agendadas: Lançar promoção em horário específico
Como funciona internamente?
Quando o SCHEDULE é executado, o sistema:
- Identifica scheduleType: datetime (único) ou cron (recorrente)
- Valida datetime/cron: Verifica formato correto
- Registra agendamento: Persiste na fila de tarefas
- Aguarda momento: Sistema aguarda até datetime/cron trigger
- Executa action: Quando hora chega, executa node especificado
- 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
- Lembrete único: Enviar mensagem daqui a 2 horas
- Follow-up: Cobrar pagamento após 3 dias sem resposta
- Relatório diário: Gerar dashboard toda manhã às 8h
- Manutenção semanal: Limpar dados todo domingo à meia-noite
- 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