Saltar para o conteúdo principal
Automações são as partes de um app que rodam por conta própria — em um cronograma, ou quando um serviço externo envia um evento. Você as declara em um componente process em kazzle.config.ts. Um componente pode ter quantos triggers você precisar.

A estrutura

{
  name: 'events',
  type: 'process',
  path: './components/events/index.ts',
  processMode: 'persistent', // ou 'triggered'
  triggers: [
    { name: 'daily-digest', kind: 'schedule', schedule: '0 9 * * *', path: '/cron/daily-digest' },
    { name: 'stripe',       kind: 'webhook',                          path: '/webhook/stripe' },
  ],
}
Duas coisas estão acontecendo aqui:
  • processMode escolhe o ciclo de vida — servidor de longa duração, ou uma execução única por trigger.
  • triggers[] lista os eventos que devem disparar este componente.
Os dois são independentes. Um servidor persistente pode ter um cron. Um processo efêmero pode ter um webhook. Escolha o ciclo de vida que se adequa à carga de trabalho e anexe quantos triggers quiser.

processMode

ModoO que rodaQuando usar
persistent (padrão)Um servidor HTTP de longa duração. Triggers são POSTados para ele.O componente já serve HTTP, ou mantém estado em memória (filas, websockets, caches).
triggeredO script de entrada é executado por trigger e sai.Tarefas de background puro — limpeza noturna, handler único de webhook Stripe, etc. Sem servidores ociosos.

Triggers

Cada trigger tem um name (único dentro do componente), um kind, e — dependendo do modo — um schedule e/ou path.
CampoQuando obrigatórioNotas
namesempreUsado no segmento da URL do webhook e em logs. Kebab-case.
kindsempre'schedule' ou 'webhook'.
schedulequando kind: 'schedule'Expressão cron de 5 campos. Resolução de minuto é o mínimo.
pathquando processMode: 'persistent'Rota HTTP no seu servidor onde o trigger chega.

Modo persistente — HTTP para o servidor

Quando um trigger dispara para um componente persistente, Kazzle faz POST no seu servidor no path declarado. A requisição carrega:
HeaderO que informa
Authorization: Bearer ${KAZZLE_TRIGGER_SECRET}Valide isto. Rejeite chamadas que não correspondem.
x-kazzle-trigger-nameO name do trigger do manifesto.
x-kazzle-trigger-run-idID opaco para correlação de logs.
x-kazzle-triggered-bycron | webhook | manual.
Para triggers de webhook, o corpo da requisição original é encaminhado como corpo do POST. Para triggers de cronograma o corpo está vazio.
// components/events/index.ts (modo persistente)
const TRIGGER_SECRET = process.env.KAZZLE_TRIGGER_SECRET ?? '';

Bun.serve({
  port: Number(process.env.PORT),
  hostname: process.env.HOST,
  async fetch(req) {
    const url = new URL(req.url);

    if (req.method === 'POST' && url.pathname === '/cron/daily-digest') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      await sendDigest();
      return Response.json({ ok: true });
    }

    if (req.method === 'POST' && url.pathname === '/webhook/stripe') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      const event = await req.json();
      await handleStripe(event);
      return Response.json({ ok: true });
    }

    return new Response('not found', { status: 404 });
  },
});

Modo triggered — uma execução por trigger

Quando um trigger dispara para um componente triggered, Kazzle executa o script de entrada do zero e aguarda sua saída. Não há path; o script aprende qual trigger disparou através de variáveis de ambiente.
Variável de ambienteValor
TRIGGER_NAMEO name do trigger do manifesto.
TRIGGERED_BYcron | webhook | manual.
RUN_IDID opaco para correlação de logs.
WEBHOOK_PAYLOADCorpo JSON (apenas triggers de webhook).
// components/events/index.ts (modo triggered)
const trigger = process.env.TRIGGER_NAME;
const runId = process.env.RUN_ID;

if (trigger === 'daily-digest') {
  await sendDigest();
} else if (trigger === 'stripe') {
  const event = JSON.parse(process.env.WEBHOOK_PAYLOAD ?? '{}');
  await handleStripe(event);
}

console.log(`run ${runId} done`);
Componentes triggered não têm máquinas ociosas em produção — eles iniciam por chamada e desligam na saída.

URLs de webhook

POST https://api.kazzle.app/webhooks/{spaceId}/{appId}/{componentName}/{triggerName}
O segmento triggerName deve corresponder a uma entrada kind: 'webhook' em triggers[] daquele componente. Nomes de trigger desconhecidos retornam 404.

Resolução de cronograma

Expressões cron são de 5 campos (minuto, hora, dia do mês, mês, dia da semana) e resolução de minuto é o mínimo. Cronogramas sub-minuto são rejeitados na validação do manifesto.

Como as execuções são registradas

Cada disparo de trigger escreve uma linha process_runs com trigger_name, triggered_by, run_id e o status de saída da execução. Você pode consultá-las do seu próprio código ou inspecioná-las na visualização de execuções do app.

Ficando sem créditos

Uma execução com falha é registrada e registrada em log, mas o cronograma continua rodando em seu ritmo normal — uma execução instável nunca desativa o trigger. A única coisa que para uma execução é créditos: cada disparo de trigger é verificado contra o saldo do espaço, e enquanto o espaço está sem créditos (ou não tem cobrança configurada) as execuções são puladas com um 402. Isto é auto-recuperável — o cronograma permanece armado e o próximo disparo após você recarregar roda normalmente, sem retomada manual.

Adicionando automações depois

Um app simples pode começar sem triggers e ganhá-los depois — adicione um resumo diário, conecte Stripe, execute limpeza. O ciclo de vida do componente (processMode) e triggers (triggers[]) são independentes, então você pode alterá-los sem reescrever o resto do app.