Subworkflows
Subworkflows são workflows menores e especializados que podem ser executados por outros workflows, permitindo modularização, reutilização e organização de automações complexas. Esta abordagem facilita a manutenção, teste e escalabilidade de projetos n8n.
Conceitos Fundamentais
O que são Subworkflows?
Subworkflows são workflows independentes que:
- Executam uma função específica e bem definida
- Podem ser chamados por outros workflows
- Recebem dados de entrada e retornam resultados
- Podem ser reutilizados em múltiplos contextos
- Facilitam a organização e manutenção de código
Benefícios dos Subworkflows
- Modularização: Dividir lógica complexa em partes menores
- Reutilização: Usar o mesmo código em múltiplos workflows
- Manutenção: Atualizar lógica em um só lugar
- Teste: Testar componentes isoladamente
- Organização: Estruturar projetos de forma clara
- Colaboração: Equipes podem trabalhar em módulos diferentes
Implementação
1. Criando um Subworkflow
Estrutura básica:
Configuração do Workflow Trigger:
{
"name": "validacao_cliente",
"description": "Valida dados de cliente e retorna status"
}
2. Workflow Trigger Node
O Workflow Trigger é o ponto de entrada de um subworkflow.
Configuração:
{
"workflowId": "workflow_123456",
"name": "Validar Cliente",
"description": "Valida dados de cliente"
}
Dados de entrada esperados:
{
"cliente": {
"nome": "João Silva",
"email": "joao@exemplo.com",
"cpf": "123.456.789-00"
}
}
3. Executando Subworkflows
Use o Workflow Trigger Node para executar subworkflows.
Configuração básica:
{
"workflowId": "validacao_cliente",
"waitForWorkflow": true,
"options": {
"pinData": {
"cliente": "{{ $json.cliente }}"
}
}
}
Configuração avançada:
{
"workflowId": "{{ $json.workflow_id }}",
"waitForWorkflow": true,
"options": {
"pinData": {
"dados": "{{ $json }}",
"contexto": {
"origem": "{{ $workflow.name }}",
"timestamp": "{{ $now }}"
}
},
"startNodes": ["node_1", "node_2"]
}
}
Padrões de Design
1. Subworkflow de Validação
Cenário: Validar dados de entrada antes do processamento.
Implementação:
// Code Node - Validação de email
const email = $json.cliente.email;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return {
status: 'erro',
campo: 'email',
mensagem: 'Email inválido'
};
}
return {
...$json,
validacoes: {
...$json.validacoes,
email: 'valido'
}
};
2. Subworkflow de Notificação
Cenário: Enviar notificações através de múltiplos canais.
Implementação:
// Code Node - Determinar canais de notificação
const prioridade = $json.prioridade;
const canais = ['email', 'slack'];
if (prioridade === 'alta') {
canais.push('sms');
}
return {
...$json,
canais_notificacao: canais
};
3. Subworkflow de Processamento de Dados
Cenário: Transformar e enriquecer dados.
Implementação:
// Code Node - Processamento de dados
const dados = $json;
// Limpar dados
const dadosLimpos = {
nome: dados.nome.trim(),
email: dados.email.toLowerCase(),
telefone: dados.telefone.replace(/\D/g, '')
};
// Enriquecer
const dadosEnriquecidos = {
...dadosLimpos,
timestamp_processamento: $now,
origem: 'subworkflow_processamento'
};
return dadosEnriquecidos;
Casos de Uso Práticos
1. Sistema de Aprovações
Cenário: Workflow principal que usa subworkflows para diferentes tipos de aprovação.
Workflow Principal:
// 1. Subworkflow - Validação
{
"workflowId": "validacao_pedido",
"waitForWorkflow": true,
"options": {
"pinData": {
"pedido": $json
}
}
}
// 2. Subworkflow - Aprovação Financeira
{
"workflowId": "aprovacao_financeira",
"waitForWorkflow": true,
"options": {
"pinData": {
"pedido": $json.pedido,
"validacao": $json.validacao
}
}
}
2. Pipeline de Dados
Cenário: Processamento de dados em etapas modulares.
Implementação:
// Subworkflow - Limpeza
const dados = $json;
const dadosLimpos = dados.map(item => ({
...item,
nome: item.nome.trim(),
email: item.email.toLowerCase(),
telefone: item.telefone.replace(/\D/g, '')
}));
return {
dados: dadosLimpos,
estatisticas: {
total: dados.length,
limpos: dadosLimpos.length
}
};
3. Sistema de Monitoramento
Cenário: Monitoramento modular de diferentes sistemas.
Implementação:
// Subworkflow - Monitorar API
const apis = ['api1', 'api2', 'api3'];
const resultados = [];
for (const api of apis) {
try {
const response = await fetch(`https://${api}.exemplo.com/health`);
resultados.push({
api,
status: response.ok ? 'ok' : 'erro',
tempo_resposta: response.time
});
} catch (error) {
resultados.push({
api,
status: 'erro',
erro: error.message
});
}
}
return {
timestamp: $now,
resultados
};
Passagem de Dados
Dados de Entrada
// Dados passados para o subworkflow
{
"cliente": {
"nome": "João Silva",
"email": "joao@exemplo.com",
"cpf": "123.456.789-00"
},
"contexto": {
"origem": "workflow_principal",
"timestamp": "2024-01-15T10:30:00.000Z"
}
}
Dados de Retorno
// Dados retornados pelo subworkflow
{
"status": "sucesso",
"validacoes": {
"nome": "valido",
"email": "valido",
"cpf": "valido"
},
"metadata": {
"workflow": "validacao_cliente",
"timestamp": "2024-01-15T10:30:05.000Z"
}
}
Expressões Avançadas
// Passagem dinâmica de dados
{
"workflowId": "{{ $json.tipo_validacao }}",
"waitForWorkflow": true,
"options": {
"pinData": {
"dados": "{{ $json }}",
"configuracao": "{{ $('Config Node').json }}",
"contexto": {
"origem": "{{ $workflow.name }}",
"usuario": "{{ $user.name }}",
"timestamp": "{{ $now }}"
}
}
}
}
Tratamento de Erros
Error Handling em Subworkflows
// Subworkflow com tratamento de erro
try {
const resultado = await processarDados($json);
return {
status: 'sucesso',
dados: resultado
};
} catch (error) {
return {
status: 'erro',
erro: error.message,
timestamp: $now
};
}
Workflow Principal com Tratamento
// Workflow principal tratando erros do subworkflow
const resultado = await executarSubworkflow($json);
if (resultado.status === 'erro') {
// Log do erro
console.error('Erro no subworkflow:', resultado.erro);
// Notificar administrador
await enviarNotificacao({
tipo: 'erro_subworkflow',
erro: resultado.erro,
workflow: $workflow.name
});
// Continuar com dados padrão
return {
...$json,
status: 'processado_com_erro',
dados: resultado.dados || {}
};
}
return resultado;
Performance e Otimização
Boas Práticas
-
Mantenha Subworkflows Focados
- Uma responsabilidade por subworkflow
- Evite subworkflows muito grandes
- Use nomes descritivos
-
Otimize Passagem de Dados
- Passe apenas dados necessários
- Use compressão para dados grandes
- Evite dados duplicados
-
Monitore Performance
- Acompanhe tempo de execução
- Identifique gargalos
- Use cache quando apropriado
Exemplo de Monitoramento
// Subworkflow com monitoramento
const startTime = $now;
const dados = $json;
// Processar dados
const resultado = await processarDados(dados);
const endTime = $now;
const tempoExecucao = endTime - startTime;
return {
...resultado,
metadata: {
tempo_execucao: tempoExecucao,
workflow: $workflow.name,
timestamp: endTime
}
};
Troubleshooting
Problemas Comuns
Erro: "Workflow not found"
- Verifique se o Workflow ID está correto
- Confirme se o workflow existe e está ativo
- Verifique permissões de acesso
Erro: "Timeout"
- Aumente o timeout do subworkflow
- Otimize a performance do subworkflow
- Considere usar
waitForWorkflow: false
Erro: "Circular dependency"
- Verifique se não há chamadas circulares
- Use contadores para limitar recursão
- Reestruture a lógica se necessário
Debugging
// Subworkflow com debugging
const debug = {
"dados_entrada": $json,
"workflow": $workflow.name,
"timestamp": $now,
"usuario": $user.name
};
console.log('Subworkflow Debug:', JSON.stringify(debug, null, 2));
// Processar dados
const resultado = await processarDados($json);
return {
...resultado,
debug
};
Integração com Outros Nós
Fluxo Típico
Exemplo Completo
// 1. HTTP Request - Receber dados
{
"url": "/webhook/dados",
"method": "POST"
}
// 2. Subworkflow - Validar dados
{
"workflowId": "validacao_dados",
"waitForWorkflow": true,
"options": {
"pinData": {
"dados": $json
}
}
}
// 3. Code Node - Processar dados válidos
const dados = $json;
const validacao = $('Subworkflow').json.validacao;
if (validacao.status === 'sucesso') {
return {
dados_processados: processarDados(dados),
validacao
};
} else {
throw new Error(`Dados inválidos: ${validacao.erro}`);
}
// 4. Subworkflow - Notificar sucesso
{
"workflowId": "notificacao_sucesso",
"waitForWorkflow": false,
"options": {
"pinData": {
"dados": $json
}
}
}
// 5. Database - Salvar dados
{
"operation": "insert",
"table": "dados_processados",
"data": $json.dados_processados
}
Referências
- Workflow Trigger - Nó para executar subworkflows
- Error Handling - Tratamento de erros em workflows
- Execution Order - Ordem de execução de nós
- Data Mapping - Mapeamento avançado de dados
Dica: Use subworkflows para criar bibliotecas de componentes reutilizáveis. Isso facilita a manutenção e permite que equipes diferentes trabalhem em módulos específicos sem interferir no workflow principal.
Esta documentação está em processo de validação. Os exemplos práticos e configurações de nós apresentados precisam ser testados e validados em ambientes reais. A intenção é sempre fornecer práticas e exemplos que funcionem corretamente em produção. Se encontrar inconsistências ou problemas, por favor, reporte para que possamos melhorar a qualidade da documentação.