Motor de Automações
O motor de automações é o coração do x17. Permite criar fluxos visuais no estilo n8n que executam ações automaticamente quando triggers são disparados.
Arquitetura
Seção intitulada “Arquitetura”Fonte do Trigger | vdispatchTrigger() / dispatchEventToAutomations() [trigger-dispatcher.ts] | +-> Buscar automações ativas com trigger_type/trigger_metric +-> Para cada automação: +-> Match conditions (trigger-registry.ts) +-> Re-entry check (once/always/cooldown) +-> Loop detection (chain depth <= 5) +-> Concurrency check (execution-limiter.ts, max 10) +-> executeAutomation() [executor.ts] | +-> Criar execution record +-> Encontrar primeiro step (sem incoming edges) +-> Loop: +-> Flow filters check [filter-evaluator.ts] +-> Step filters check [filter-evaluator.ts] +-> Resolver variaveis [variable-resolver.ts] +-> executeStep() [step-handlers.ts] +-> Se wait > 30s: suspend +-> Se condition: branch true/false +-> Se switch: branch por rule +-> Proximo step (next_step_id) +-> Atualizar execution status (completed/failed/suspended)Arquivos do Motor
Seção intitulada “Arquivos do Motor”| Arquivo | Descrição |
|---|---|
src/lib/automations/trigger-registry.ts | Registro de todos os triggers com match conditions |
src/lib/automations/trigger-dispatcher.ts | Despacha triggers para automações correspondentes |
src/lib/automations/executor.ts | Executa uma automação (loop de steps) |
src/lib/automations/step-handlers.ts | Handlers para cada tipo de step |
src/lib/automations/expression-resolver.ts | Resolve expressoes {{variable}} |
src/lib/automations/variable-resolver.ts | Resolve variaveis de template + inline expressions |
src/lib/automations/filter-evaluator.ts | Avalia filtros em 3 níveis |
src/lib/automations/flow-serializer.ts | Serializa/deserializa flows entre editor e banco |
src/lib/automations/execution-limiter.ts | Limita execuções concorrentes (Upstash Redis) |
src/lib/automations/smart-sending.ts | Frequency cap + quiet hours |
src/lib/automations/whatsapp-sender.ts | Envia mensagens/templates via Meta API |
src/lib/automations/platform-events.ts | Eventos de cada plataforma e-commerce |
src/lib/automations/toolbox-categories.ts | Categorias do toolbox no editor visual |
src/lib/automations/trigger-schema.ts | Schema helpers para triggers |
src/lib/automations/blueprints.ts | Templates pre-configurados de automações |
src/lib/automations/template-presets.ts | Presets de templates |
src/lib/automations/insert-variable.ts | Helper para inserir variaveis no editor |
Trigger Registry (trigger-registry.ts)
Seção intitulada “Trigger Registry (trigger-registry.ts)”O Trigger Registry é a Single Source of Truth para todos os tipos de trigger. Define:
type: identificador único do triggerlabel: nome exibido na UI (pt-BR)match(config, triggerData): função que determina se o trigger ativa a automaçãoschema: campos disponíveis como variaveis no flowsampleData: dados de exemplo para preview no editor
Todos os Triggers Registrados
Seção intitulada “Todos os Triggers Registrados”| Trigger | Label | Match Condition |
|---|---|---|
message_received | Mensagem Recebida | Se config.keyword definido, verifica se message.text.body contém keyword (case-insensitive). Senao, sempre match. |
Contatos
Seção intitulada “Contatos”| Trigger | Label | Match Condition |
|---|---|---|
new_contact | Novo Contato | Se config.source definido, verifica triggerData.source === source. Senao, sempre match. |
tag_added | Tag Adicionada | Se config.tag_name definido, compara com triggerData.tag_name (case-insensitive). |
tag_removed | Tag Removida | Mesma lógica de tag_added. |
contact_updated | Contato atualizado | Se config.field definido, verifica triggerData.field === field. |
conversation_assigned | Conversa atribuida | Se config.assigned_to definido, verifica match. |
segment_entered | Entrou no Segmento | Se config.segment_id definido, verifica match. |
segment_exited | Saiu do Segmento | Se config.segment_id definido, verifica match. |
E-Commerce
Seção intitulada “E-Commerce”| Trigger | Label | Match Condition |
|---|---|---|
order_created | Pedido Criado | Se config.platform definido, verifica match. |
order_paid | Pedido Pago | Filtra por platform e min_amount. |
order_cancelled | Pedido Cancelado | Se config.platform definido, verifica match. |
order_fulfilled | Pedido Enviado | Se config.platform definido, verifica match. |
customer_created | Cliente Criado | Se config.platform definido, verifica match. |
checkout_created | Checkout Criado | Sempre match. |
cart_abandoned | Carrinho Abandonado | Filtra por platform e min_amount. |
Rastreamento
Seção intitulada “Rastreamento”| Trigger | Label | Match Condition |
|---|---|---|
tracking_updated | Rastreamento Atualizado | Filtra por config.status e config.carrier_name. |
Sistema
Seção intitulada “Sistema”| Trigger | Label | Match Condition |
|---|---|---|
webhook | Webhook Externo | Sempre match. |
schedule | Agendamento | Sempre match. |
template_status_changed | Status de template alterado | Se config.status definido, verifica match. |
date_property | Data do Contato | Sempre match (verificação feita pelo cron). |
Variaveis Disponíveis por Trigger
Seção intitulada “Variaveis Disponíveis por Trigger”Cada trigger define um schema com campos acessiveis via {{trigger.campo}}. Exemplos:
message_received:{{trigger.message_text}},{{trigger.from}},{{trigger.timestamp}},{{trigger.message_type}}order_created:{{trigger.customer_name}},{{trigger.total_amount}},{{trigger.order_id}},{{trigger.order_number}},{{trigger.platform}},{{trigger.item_names}},{{trigger.pix_qr_code}}cart_abandoned:{{trigger.customer_name}},{{trigger.total_amount}},{{trigger.recovery_url}},{{trigger.item_names}}tracking_updated:{{trigger.tracking_number}},{{trigger.tracking_status}},{{trigger.carrier_name}},{{trigger.tracking_url}}
Trigger Dispatcher (trigger-dispatcher.ts)
Seção intitulada “Trigger Dispatcher (trigger-dispatcher.ts)”O dispatcher é chamado quando um evento ocorre (webhook, ação do usuário, cron) e precisa encontrar e executar automações correspondentes.
dispatchTrigger(accountId, triggerType, triggerData)
Seção intitulada “dispatchTrigger(accountId, triggerType, triggerData)”Fluxo:
- Busca automações ativas com
trigger_type = triggerTypeeis_active = trueedeleted_at IS NULL - Para cada automação encontrada:
a. Obtem
TriggerDefinitiondo registry b. Chamadef.match(config, triggerData)- se false, skip c. Re-entry check: verificareentry_modeda automação d. Loop detection: verifica se automação já está na_executionChain(max depth: 5) e. Concurrency check:canExecute(accountId)via Upstash Redis (max 10 por account) f.incrementCount(accountId)+executeAutomation()(fire-and-forget) g.decrementCount(accountId)no finally
dispatchEventToAutomations(accountId, metricName, eventData)
Seção intitulada “dispatchEventToAutomations(accountId, metricName, eventData)”Similar ao dispatchTrigger, mas para automações baseadas em trigger_metric:
- Busca automações com
trigger_metric = metricName - Usa
matchesEventConfig()em vez do registry (filtra porplatformemin_amount) - Ignora eventos com
_fromAutomation = true(previne loops) - Limite: max 10 automações por evento (
MAX_EVENT_AUTOMATIONS)
Re-entry Control
Seção intitulada “Re-entry Control”Configuravel por automação (reentry_mode):
| Mode | Comportamento |
|---|---|
always | Executa toda vez (padrão) |
once | Executa apenas uma vez por contato (nunca re-entra) |
cooldown | Re-entra após X horas (reentry_cooldown_hours, padrão 24h) |
Verificação: busca em automation_executions a última execução completed para o par (automation_id, contact_id).
Chain Depth Protection
Seção intitulada “Chain Depth Protection”Previne loops infinitos onde automação A dispara automação B que dispara automação A:
_executionChain: array de automation IDs já executados na chainMAX_CHAIN_DEPTH = 5: máximo de automações encadeadas
Executor (executor.ts)
Seção intitulada “Executor (executor.ts)”executeAutomation(automationId, accountId, triggerData)
Seção intitulada “executeAutomation(automationId, accountId, triggerData)”Responsável por executar todos os steps de uma automação em sequência.
Fluxo detalhado:
- Busca todos os
automation_stepsda automação (ordenados porcreated_at) - Busca
flow_filtersda automação - Encontra o primeiro step (step sem incoming edges)
- Cria registro em
automation_executionscomstatus: "running" - Cria registros em
automation_execution_stepspara cada step (todospending) - Loop de execução (max 100 iterações -
MAX_STEPS): a. Busca step atual no map b. Avaliaflow_filters(se falha, para a execução) c. Avaliastep_filters(se falha, pula paranext_step_id) d. Atualiza step pararunninge. ChamaexecuteStep(stepConfig, context)f. Se sucesso:- Se
suspended(wait longo): cria suspension record, para execução - Senao: atualiza step para
completed, avanca para proximo step - Para
condition: branch true ->next_step_id, branch false ->condition_false_step_id - Para
switch: branch matched ->switch_routes[].next_step_idg. Se falha: atualiza step parafailed, para execução
- Se
- Atualiza
automation_executionscom status final +duration_ms
Encontrar primeiro step (findFirstStep):
- Coleta todos os IDs que são target de algum edge (next_step_id, condition_false_step_id, switch_routes)
- O primeiro step e aquele cujo ID NAO aparece como target
- Fallback: primeiro step pela ordem de criação
resumeAutomation(suspensionId)
Seção intitulada “resumeAutomation(suspensionId)”Resume uma automação suspensa (apos wait longo):
- Busca suspension com
status: "processing" - Le
current_step_id,trigger_data,previous_output - Continua o loop de execução a partir do step salvo
- Acumula
duration_ms(soma com duração anterior) - Pode gerar OUTRA suspension se encontrar outro wait longo
Modelo de Dados da Execução
Seção intitulada “Modelo de Dados da Execução”automation_executions id UUID PK automation_id UUID FK account_id UUID FK contact_id UUID FK (nullable) status: running | completed | failed | suspended trigger_data JSONB steps_total INTEGER steps_completed INTEGER error_message TEXT duration_ms INTEGER started_at TIMESTAMPTZ completed_at TIMESTAMPTZ
automation_execution_steps id UUID PK execution_id UUID FK step_id UUID FK step_type TEXT step_name TEXT status: pending | running | completed | failed | skipped | suspended input_data JSONB output_data JSONB error_message TEXT started_at TIMESTAMPTZ completed_at TIMESTAMPTZ
automation_execution_suspensions id UUID PK execution_id UUID FK step_id UUID FK account_id UUID FK automation_id UUID FK trigger_data JSONB previous_output JSONB current_step_id UUID resume_at TIMESTAMPTZ status: pending | processing | completed | failed error_message TEXT resumed_at TIMESTAMPTZStep Handlers (step-handlers.ts)
Seção intitulada “Step Handlers (step-handlers.ts)”Cada tipo de step tem um handler dedicado. O executeStep() roteia para o handler correto via lookup no STEP_HANDLERS map.
Todos os Step Types
Seção intitulada “Todos os Step Types”send_message
Seção intitulada “send_message”- Descrição: Envia mensagem de texto livre via WhatsApp
- Config:
{ message: string, is_transactional?: boolean } - Fluxo:
- Busca contato por
contact_id - Smart Sending check (se não transacional)
- Resolve variaveis inline
{{trigger.name}}no texto - Substitui URLs por tracked links (UTM params)
- Envia via
sendWhatsAppText() - Cria registro em
messages+ atualizaconversations.last_message_at - Emite evento
Message Sent - Registra em
smart_sending_timers
- Busca contato por
- Output:
{ sent, wa_message_id, conversation_id, message }
send_template
Seção intitulada “send_template”- Descrição: Envia template WhatsApp aprovado pela Meta
- Config:
{ template_id: string, variable_mapping: Record<string, string>, var_custom_*: string, is_transactional?: boolean } - Fluxo:
- Busca template por ID, verifica
meta_status === "approved" - Busca contato, resolve phone
- Smart Sending check
- Resolve variaveis do template (
resolveVariables()) - Resolve botoes (copy_code, url com variaveis)
- Cria tracked links para URLs no body
- Envia via
sendWhatsAppTemplate() - Cria registro em
messages+ emite eventoTemplate Sent
- Busca template por ID, verifica
- Output:
{ template_id, template_name, sent, wa_message_id, resolved_variables }
- Descrição: Pausa o fluxo por um tempo definido
- Config:
{ duration: number, unit: "seconds" | "minutes" | "hours" } - Fluxo:
- Se delay <= 30 segundos:
setTimeout()sincrono - Se delay > 30 segundos: retorna
{ suspended: true, resume_at }-> cron resume
- Se delay <= 30 segundos:
- Output:
{ duration, unit, waited_ms }ou{ duration, unit, delay_ms, resume_at, reason }
condition
Seção intitulada “condition”- Descrição: Divide o fluxo em dois caminhos (true/false)
- Config:
{ field: string, operator: string, value: string } - Operadores:
equals,not_equals,contains,not_contains,starts_with,ends_with,is_empty,is_not_empty,greater_than,less_than - Fluxo: Avalia
triggerData[field] <operator> value, suporta expressoes{{}}no value - Output:
{ field, operator, value, fieldValue, result },branch: "true" | "false"
- Descrição: Roteia para múltiplos caminhos com regras
- Config:
{ rules: [{ conditions: [{ field, operator, value }], output_name }] } - Fluxo: Avalia regras em ordem, primeira que match determina o branch
- Output:
{ matched_rule, output_name },branch: "rule_0" | "rule_1" | ... | "default" - Routing: Usa
switch_routesarray no config para mapearhandle_id->next_step_id
add_tag / remove_tag
Seção intitulada “add_tag / remove_tag”- Descrição: Adiciona ou remove uma tag do contato
- Config:
{ tag_name: string } - Fluxo: Busca tag por nome, upsert/delete em
contact_tags - Output:
{ action, tag_name, contact_id } - Eventos: Emite
Tag AddedouTag Removed
ai_respond
Seção intitulada “ai_respond”- Descrição: Gera resposta inteligente com Claude via VPS proxy
- Config:
{ prompt?: string }(prompt adicional opcional) - Fluxo:
- Busca
ai_settingsebrand_contextda conta - Busca últimas 20 mensagens da conversa
- Constroi system prompt + histórico de chat
- Chama
chatWithClaude()via VPS proxy - Trunca resposta em 500 chars
- Envia via
sendWhatsAppText() - Salva mensagem com
ai_generated: true
- Busca
- Output:
{ reply, model, sent, wa_message_id }
http_request
Seção intitulada “http_request”- Descrição: Faz requisição HTTP para API externa
- Config:
{ url: string, method: string, headers: Record<string, string>, body?: string } - Segurança:
- Bloqueio de IPs internos (10.x, 172.16-31.x, 192.168.x, 127.x, 0.x)
- Apenas protocolos HTTP/HTTPS
- Timeout de 10 segundos
- Fluxo: Resolve variaveis
{{}}na URL e body, executa fetch - Output:
{ status, body }
- Descrição: Atribui a conversa a um agente da equipe
- Config:
{ assign_to: string }(user_id do agente) - Fluxo: Verifica membro na conta, busca conversa aberta, atualiza
assigned_to - Output:
{ assign_to, conversation_id, contact_id }
close_conversation
Seção intitulada “close_conversation”- Descrição: Encerra a conversa ativa do contato
- Config:
{ closing_message?: string } - Fluxo: Busca conversa aberta, opcionalmente envia mensagem de encerramento, atualiza
status: "closed" - Eventos: Emite
Conversation Closed - Output:
{ conversation_id, status, closing_message_sent }
Expression Resolver (expression-resolver.ts)
Seção intitulada “Expression Resolver (expression-resolver.ts)”Resolve expressoes no formato {{namespace.field}} dentro de textos.
Sintaxe
Seção intitulada “Sintaxe”{{trigger.customer_name}} -> Dados do trigger{{contact.name}} -> Nome do contato{{contact.phone}} -> Telefone do contato{{contact.email}} -> Email do contato{{previous.wa_message_id}} -> Output do step anterior{{field_name}} -> Acesso legado direto ao triggerSegurança
Seção intitulada “Segurança”- Blacklist:
__proto__,constructor,prototype,toString,valueOf - Max depth: 10 níveis de aninhamento
- Max substitutions: 50 substituicoes por texto
- Se não encontrar valor: mantem a expressão original
{{trigger.campo}}
Namespaces
Seção intitulada “Namespaces”| Namespace | Fonte de Dados |
|---|---|
trigger.* | triggerData (dados do trigger que disparou a automação) |
contact.* | Contato associado (name, phone, email) |
previous.* | Output do step anterior na chain |
| (sem namespace) | Acesso legado direto ao triggerData |
Variable Resolver (variable-resolver.ts)
Seção intitulada “Variable Resolver (variable-resolver.ts)”Resolve variaveis de template WhatsApp. Diferente do expression resolver, este e específico para template parameters.
resolveVariables(variableMapping, triggerData, contact, customValues, resolveContext)
Seção intitulada “resolveVariables(variableMapping, triggerData, contact, customValues, resolveContext)”Recebe um mapeamento { "1": "customer_name", "2": "total_amount" } e retorna string[] com valores resolvidos.
Variaveis Suportadas
Seção intitulada “Variaveis Suportadas”| Variavel | Resolução |
|---|---|
customer_name | triggerData.customer_name ou contact.name |
contact_name | contact.name ou triggerData.customer_name |
contact_phone | contact.phone ou triggerData.customer_phone |
contact_email | contact.email ou triggerData.customer_email |
total_amount | Formata como moeda BRL (R$ 297,90) |
recovery_url | Adiciona UTM params automaticamente |
order_id | triggerData.external_order_id ou triggerData.order_id |
order_number | triggerData.order_number |
item_names | triggerData.item_names |
item_count | triggerData.item_count |
financial_status | Traduz para portugues (Pago, Pendente, etc.) |
fulfillment_status | Traduz para portugues (Entregue, Parcial, etc.) |
payment_method | Traduz para portugues (PIX, Cartão, etc.) |
is_pix | "true" ou "false" |
pix_qr_code | Código PIX copia e cola |
pix_expiration_date | Formatado pt-BR |
tracking_number | Código de rastreio |
tracking_status | Label traduzido |
carrier_name | Nome da transportadora |
tracking_url | URL de rastreio |
tracking_location | Localização |
estimated_delivery | Data formatada pt-BR |
custom | Valor customizado definido no editor |
resolveInlineExpressions(text, triggerData, contact, previousOutput, resolveContext)
Seção intitulada “resolveInlineExpressions(text, triggerData, contact, previousOutput, resolveContext)”Resolve expressoes {{trigger.*}}, {{contact.*}}, {{previous.*}} dentro de textos livres (mensagens, URLs, etc.). Combina o expression resolver com o variable resolver para acesso a variaveis formatadas.
Filter Evaluator (filter-evaluator.ts)
Seção intitulada “Filter Evaluator (filter-evaluator.ts)”Avalia filtros de contato em 3 níveis do flow.
3 Niveis de Filtros
Seção intitulada “3 Niveis de Filtros”Automação | +-> Flow Filters (automations.flow_filters) | Aplicados ANTES de cada step. | Se falha: PARA a execução inteira. | +-> Step 1 | +-> Step Filters (automation_steps.step_filters) | Se falha: PULA este step, vai para next_step_id. | +-> Step 2 | +-> Step Filters | ...FilterCondition
Seção intitulada “FilterCondition”interface FilterCondition { id: string field: string // "name" | "phone" | "email" | "tag" | "created_at" operator: string // depends on field type value: string}Campos de Filtro
Seção intitulada “Campos de Filtro”| Campo | Tipo | Operadores |
|---|---|---|
name | text | equals, not_equals, contains, not_contains, starts_with, ends_with, is_empty, is_not_empty |
phone | text | (mesmos de text) |
email | text | (mesmos de text) |
tag | tag | has_tag, not_has_tag |
created_at | date | greater_than (depois de), less_than (antes de), is_empty, is_not_empty |
evaluateContactFilters(contactId, accountId, filters)
Seção intitulada “evaluateContactFilters(contactId, accountId, filters)”- Busca contato completo (id, name, phone, email, created_at)
- Busca tags do contato via
contact_tagsJOINtags - Avalia TODOS os filtros (AND logico - todos devem passar)
- Se contato não encontrado: retorna
true(permite execução)
Execution Limiter (execution-limiter.ts)
Seção intitulada “Execution Limiter (execution-limiter.ts)”Controla o número máximo de automações executando simultaneamente por account, usando Upstash Redis.
Configuração
Seção intitulada “Configuração”MAX_CONCURRENT = 10execuções por accountTTL_SECONDS = 300(5 minutos) para auto-cleanup- Redis key:
x17:exec:active:{accountId}
Funcoes
Seção intitulada “Funcoes”canExecute(accountId) // Verifica se count < MAX_CONCURRENTincrementCount(accountId) // INCR + EXPIRE 300sdecrementCount(accountId) // DECR, se <= 0: DELFallback
Seção intitulada “Fallback”Se Redis não estiver configurado (sem env vars), todas as funções retornam permissivo (não bloqueia).
Smart Sending (smart-sending.ts)
Seção intitulada “Smart Sending (smart-sending.ts)”Previne fadiga do contato com dois mecanismos:
1. Quiet Hours
Seção intitulada “1. Quiet Hours”- Configurado por conta:
quiet_hours_enabled,quiet_hours_start,quiet_hours_end,timezone - Verifica hora atual no timezone da conta
- Suporta overnight (ex: 21:00 -> 08:00)
- Se em quiet hours:
{ allowed: false, reason: "quiet_hours", nextAllowedAt: "08:00 America/Sao_Paulo" }
2. Smart Sending (Frequency Cap)
Seção intitulada “2. Smart Sending (Frequency Cap)”- Configurado por conta:
smart_sending_enabled,smart_sending_window_hours(padrão: 16h) - Tabela
smart_sending_timers: armazenalast_sent_atpor (account_id, contact_id, channel) - Se última mensagem enviada dentro da janela:
{ allowed: false, reason: "smart_sending", nextAllowedAt: ISO } recordMessageSent(): upsert no timer após envio bem-sucedido
Steps com is_transactional: true ignoram Smart Sending (ex: confirmação de pedido, PIX).
WhatsApp Sender (whatsapp-sender.ts)
Seção intitulada “WhatsApp Sender (whatsapp-sender.ts)”Abstrai o envio de mensagens via Meta WhatsApp Cloud API.
getWhatsAppProfile(accountId)
Seção intitulada “getWhatsAppProfile(accountId)”- Busca
whatsapp_profilesconectado para a conta - Descriptografa
access_token_encryptedcomdecrypt() - Cria instância
MetaWhatsAppApi
sendWhatsAppText(accountId, to, text)
Seção intitulada “sendWhatsAppText(accountId, to, text)”Envia mensagem de texto livre. Retorna SendResult { sent, waMessageId, reason }.
sendWhatsAppTemplate(accountId, to, templateName, language, parameters, buttonComponents?)
Seção intitulada “sendWhatsAppTemplate(accountId, to, templateName, language, parameters, buttonComponents?)”Envia template com variaveis resolvidas. Constroi payload com components[] (body parameters + button components).
Tratamento de Erros
Seção intitulada “Tratamento de Erros”MetaApiError: extraierror.codeeerror.messagedo response da Meta- Retorna
{ sent: false, reason, errorCode, errorDetail }em vez de lancar exceção
Flow Serializer (flow-serializer.ts)
Seção intitulada “Flow Serializer (flow-serializer.ts)”Converte entre a representação do editor visual (@xyflow/react Nodes/Edges) é o modelo de dados do banco (AutomationStep[]).
serializeFlow(nodes, edges, automationId) -> AutomationStep[]
Seção intitulada “serializeFlow(nodes, edges, automationId) -> AutomationStep[]”Converte nodes/edges do ReactFlow para registros do banco:
- Filtra node do tipo
trigger(não é salvo como step) - Mapeia
node.type->AutomationStepTypeviagetStepType() - Resolve
next_step_idvia edges - Para
condition: extraiyesedge ->next_step_id,noedge ->condition_false_step_id - Para
switch: cria arrayswitch_routescom{ handle_id, next_step_id } - Preserva
step_filtersdo node data
deserializeFlow(steps, triggerType, triggerConfig?, triggerMetric?) -> { nodes, edges }
Seção intitulada “deserializeFlow(steps, triggerType, triggerConfig?, triggerMetric?) -> { nodes, edges }”Converte registros do banco para nodes/edges do ReactFlow:
- Cria node
trigger-0com dados do trigger - Mapeia
AutomationStepType-> ReactFlow type viaREACT_FLOW_TYPE_MAP - Cria edges entre steps (incluindo condition yes/no e switch routes)
- Edge style padrão:
stroke: "#4D4D4D", strokeWidth: 2, type: "custom" - Conecta trigger ao primeiro step automaticamente
Type Mappings
Seção intitulada “Type Mappings”| AutomationStepType | ReactFlow Node Type |
|---|---|
| send_message | action |
| send_template | send_template |
| wait | wait |
| condition | condition |
| switch | switch |
| add_tag | tag |
| remove_tag | tag |
| webhook | action |
| ai_respond | ai |
| http_request | http_request |
| assign | assign |
| close_conversation | close_conversation |
Cron Jobs
Seção intitulada “Cron Jobs”/api/cron/automations (GET)
Seção intitulada “/api/cron/automations (GET)”- Autenticado via
CRON_SECRETno header Authorization - Busca automações com
trigger_type: "schedule"eis_active: true - Verifica
schedule_interval(minutos) contralast_run_at - Se nenhuma execução
runningativa: executa - Atualiza
trigger_config.last_run_at
/api/automations/resume (POST)
Seção intitulada “/api/automations/resume (POST)”- Autenticado via
CRON_SECRET - Recebe
{ suspension_id }no body - Chama
resumeAutomation(suspensionId) - Usado pelo pg_cron para retomar automações suspensas (apos wait longo)
pg_cron (Supabase)
Seção intitulada “pg_cron (Supabase)”recalculate_all_segments: a cada 5 minutos, recalcula membros de segmentos dinâmicosexecute-scheduled-campaigns: a cada 1 minuto, executa campanhas agendadas
Platform Events (platform-events.ts)
Seção intitulada “Platform Events (platform-events.ts)”Define os eventos disponíveis para cada plataforma de e-commerce integrada.
Eventos por Plataforma
Seção intitulada “Eventos por Plataforma”| Plataforma | Eventos |
|---|---|
| Shopify | Order Placed, Order Paid, Order Cancelled, Order Refunded, Order Fulfilled, Checkout Started, Checkout Recovered, Shipment Created, Customer Created |
| Yampi | Order Placed, Order Paid, Order Cancelled, Order Fulfilled, Checkout Abandoned, Shipment Delivered, Contact Created |
| Nuvemshop | Order Placed, Order Paid, Order Cancelled, Order Fulfilled, Checkout Started, Shipment Created |
| Hotmart | Order Placed, Order Cancelled, Order Refunded, Checkout Abandoned |
| Kiwify | Order Placed, Order Refunded, Checkout Abandoned |
| WooCommerce | Order Placed, Order Paid, Order Cancelled |
Esses eventos aparecem no toolbox do editor quando a integração correspondente está ativa.
Toolbox Categories (toolbox-categories.ts)
Seção intitulada “Toolbox Categories (toolbox-categories.ts)”Define as categorias e itens do toolbox no editor visual de automações.
Categorias Estaticas
Seção intitulada “Categorias Estaticas”| ID | Label | Triggers | Actions |
|---|---|---|---|
whatsapp | message_received, Template Delivered, Template Read | send_message, send_template | |
contacts | Contatos | new_contact, Contact Created, tag_added, Tag Removed, Conversation Opened/Closed, contact_updated, conversation_assigned, segment_entered/exited | add_tag, remove_tag, assign, close_conversation |
system | Sistema | webhook, schedule, Link Clicked, template_status_changed, date_property | http_request |
logic | Lógica | (nenhum) | condition, switch, wait |
ai | IA | (nenhum) | ai_respond |
Categorias Dinamicas (Integrações)
Seção intitulada “Categorias Dinamicas (Integrações)”Geradas dinâmicamente via getToolboxCategories(integrations). Para cada integração ativa, cria uma categoria com os eventos da plataforma como triggers.
Arquivos Relevantes
Seção intitulada “Arquivos Relevantes”| Arquivo | Linha | Descrição |
|---|---|---|
src/lib/automations/trigger-registry.ts | 1-561 | 19 triggers registrados |
src/lib/automations/trigger-dispatcher.ts | 1-234 | Dispatch + re-entry + loop detection |
src/lib/automations/executor.ts | 1-598 | Execute + resume automation |
src/lib/automations/step-handlers.ts | 1-946 | 11 step handlers |
src/lib/automations/expression-resolver.ts | 1-54 | Expression {{}} resolver |
src/lib/automations/variable-resolver.ts | 1-250 | Template variable resolver |
src/lib/automations/filter-evaluator.ts | 1-149 | 3-level filter evaluation |
src/lib/automations/flow-serializer.ts | 1-228 | Editor <-> DB serialization |
src/lib/automations/execution-limiter.ts | 1-56 | Redis concurrency limiter |
src/lib/automations/smart-sending.ts | 1-105 | Frequency cap + quiet hours |
src/lib/automations/whatsapp-sender.ts | 1-117 | Meta API send abstraction |
src/lib/automations/platform-events.ts | 1-111 | E-commerce event definitions |
src/lib/automations/toolbox-categories.ts | 1-455 | Editor toolbox categories |
src/app/api/cron/automations/route.ts | 1-81 | Schedule cron job |
src/app/api/automations/resume/route.ts | 1-48 | Resume suspended automations |