Pular para conteúdo

Cron Jobs no OpenClaw: por que param de rodar e como resolver

Você configurou três cron jobs (tarefas agendadas — você define o horário e elas rodam sozinhas) no OpenClaw. Relatório semanal, limpeza de cache, sync de dados. Testou, tudo rodou. Foi embora na sexta. Segunda de manhã: nada executou desde sexta-feira. Nenhum alerta, nenhum erro nos logs. O agente estava lá — mas parado.

Esse é o problema mais relatado pela comunidade em produção. Este post cobre os 7 problemas reais que fazem cron jobs pararem, a escada de diagnóstico para identificar cada um, e as configurações defensivas que evitam que aconteçam de novo.


ProblemaCausa raizFix rápido
Job para sem avisoDelivery falha silenciosa--best-effort-deliver
Funciona 2 semanas, depois morreSessão principal sobrecarregada--session isolated
Update quebrou meus jobsPatches em dist/ sobrescritosPin version + patch externo
Config errada afeta tudoJSON inválido no scheduleropenclaw cron list + validar
Job a cada 1 min travaExecução demora mais que o intervalomaxConcurrentRuns + intervalo >= 5m
Horário erradoTimezone implícito--tz "America/Sao_Paulo" explícito
Repo virou caixa pretaPRs/issues automáticos sem reviewFila de aprovação manual

Diagnóstico rápido

Antes de tentar qualquer fix, siga essa escada. Cada comando descarta uma categoria inteira de problema.

Job não roda?
    │
    ▼
openclaw cron status          ← o agendador está ativo?
    │
    ▼
openclaw cron list            ← job existe e está habilitado?
    │
    ▼
openclaw cron runs --last 10  ← execuções recentes e códigos de saída
    │
    ▼
openclaw logs --since 24h     ← erros de runtime no agente
    │
    ▼
openclaw channels status --probe  ← canal de entrega está respondendo?

Na maioria dos casos, cron list já revela o problema: job desabilitado, expressão cron inválida, ou ID que mudou após edição.


O que chegou nas mudanças de fevereiro/2026

Alguns dos fixes deste post dependem de funcionalidades que chegaram nas releases de fevereiro/2026 — hoje presentes em qualquer versão da trilha stable.

FuncionalidadeComando / configPor que importa
Webhook deliverydelivery.mode: "webhook"Desacopla execução de notificação — falha no canal não mata o job
Stagger window--exact para desabilitarExpressões no topo da hora aplicam até 5 min de atraso proposital para não sobrecarregar por padrão
6-field cron*/30 * * * * * (com segundos)Sub-minuto sem gambiarras
Restart catch-upcatchUp: trueJobs perdidos durante downtime rodam ao reiniciar

Verifique sua versão com openclaw --version. Mantenha-se na trilha stable (2026.9.x em setembro/2026) antes de aplicar as receitas deste post.


Os 7 problemas

1. Falhas silenciosas

O job roda, o agente processa, mas a entrega nunca chega. Você acha que o cron parou. Na verdade, a execução aconteceu — o que falhou foi a entrega para o canal configurado (Telegram, webhook, e-mail etc.).

O comportamento padrão do OpenClaw é tratar falha de entrega como sucesso do job. O agendador marca como completed, o log mostra exit: 0, e ninguém percebe que a mensagem não chegou.

O relato mais frequente na comunidade é de jobs que rodam por dias sem entregar nada, porque o token do bot do Telegram expirou ou o webhook (um aviso automático que um sistema manda para outro quando algo acontece) mudou de URL.

openclaw cron add \
  --name "Relatório semanal" \
  --cron "0 9 * * 1" \      # toda segunda às 9h
  --best-effort-deliver \
  --on-delivery-fail retry:3

O --best-effort-deliver faz o agendador tentar a entrega, mas registrar falhas separadamente do status do job. O --on-delivery-fail retry:3 adiciona até 3 tentativas com espera progressiva (1 segundo, depois 2, depois 4…) antes de desistir.

2. Degradação com o tempo

O job funciona por duas semanas. Depois começa a ficar lento, a pular execuções, até parar. Reiniciar o agente resolve — por mais duas semanas.

Isso acontece porque cron jobs rodam na sessão principal por padrão. Cada vez que o job roda, ele acumula informação da sessão anterior — logs, respostas, histórico de ferramentas. Depois de semanas fazendo isso, a sessão fica pesada demais e o agente trava.

openclaw cron add \
  --name "Sync de dados" \
  --cron "0 */6 * * *" \    # a cada 6 horas
  --session isolated \
  --message "Sincronizar base de clientes com CRM"

O --session isolated cria uma sessão (a conversa ativa entre você e o agente) descartável para cada execução. O job roda, entrega o resultado, e a sessão é destruída. Sem acúmulo, sem degradação. O custo é que o agente não tem memória entre execuções do mesmo job — se isso for necessário, use --session shared:nome-do-grupo para compartilhar contexto entre jobs relacionados.

3. Updates que quebram

Você rodou openclaw update, e os cron jobs pararam de funcionar. Ou pior: continuam rodando, mas com comportamento diferente.

Atualizações podem sobrescrever arquivos em dist/ e node_modules/. Se você fez patches manuais (modificou um arquivo de configuração interno, ajustou um handler), esses patches desaparecem no update.

A solução é nunca modificar arquivos internos. Em vez disso:

# Trava a versão do OpenClaw para não atualizar sozinho
"openclaw": "2026.7.1"

# Aplica patches fora de node_modules (usando patch-package)
npx patch-package openclaw

Antes de atualizar, rode openclaw cron list e salve o output. Depois do update, compare. Se um job mudou de ID ou sumiu, recrie-o a partir do backup.

Nas versões atuais, openclaw update é atômico: o gateway atual continua rodando enquanto a nova versão é preparada, com rollback automático se a atualização falhar. Isso evita ficar com um agente quebrado, mas não preserva patches manuais nem garante que um job se comporte igual depois de uma atualização bem-sucedida — o backup e a comparação acima continuam valendo.

4. Erros em cascata

Um typo no Goals.md — uma data mal formatada, um campo com configuração inválida — faz o agente gastar tokens tentando interpretar o erro a cada execução. O job roda, consome recursos, e produz lixo. Por dias, sem ninguém perceber.

# Mostra detalhes completos das últimas 5 execuções do job
openclaw cron runs --name "briefing-matinal" --last 5 --verbose

O --verbose mostra o prompt enviado, a resposta do modelo, e o custo em tokens de cada execução. Se o consumo está alto e a resposta é irrelevante, o problema está no input, não no cron.

Duas práticas defensivas: primeiro, configure alertas de custo por job com maxTokensPerRun. Segundo, revise o output dos jobs semanalmente — o equivalente a olhar os logs do servidor.

{
  name: "briefing-matinal",
  cron: "0 6 * * *",         // toda manhã às 6h
  maxTokensPerRun: 2000,     // aborta se ultrapassar 2000 tokens
  onTokenExceeded: "abort",
}

5. Jobs de alta frequência

Um job configurado para rodar a cada minuto parece inofensivo. Mas se a execução leva 90 segundos, o segundo disparo acontece antes do primeiro terminar. Em meia hora você tem 30 instâncias empilhadas, o agente trava, e o VPS (um computador na nuvem que fica ligado 24 horas) fica sem memória.

{
  name: "health-check",
  cron: "*/5 * * * *",       // a cada 5 minutos
  maxConcurrentRuns: 1,      // só uma execução por vez
  session: "isolated",
}

O maxConcurrentRuns: 1 garante que uma nova execução só começa quando a anterior terminar. Se a anterior ainda está rodando, o disparo é descartado — não enfileirado, descartado.

Regra prática: o intervalo do cron deve ser pelo menos 3x o tempo médio de execução. Se o job leva 2 minutos, configure para 6 ou mais. Para checagens que precisam de frequência sub-minuto, use a sintaxe de 6 campos: */30 * * * * * (a cada 30 segundos).

6. Timezone errado

O job está configurado para 7h. Mas roda às 4h da manhã. Ou às 10h. A causa é sempre a mesma: o timezone do cron não está explícito, e o padrão do servidor não é o que você espera.

Em ambientes de VPS (um computador na nuvem que fica ligado 24 horas), o timezone padrão costuma ser UTC. O OpenClaw herda esse padrão. Se você não configurou --tz, seu “0 7 * * *” roda às 7h UTC — que são 4h em Brasília.

openclaw cron add \
  --name "Briefing matinal" \
  --cron "0 7 * * *" \       # 7h no horário de Brasília
  --tz "America/Sao_Paulo" \
  --exact

O --exact desabilita o stagger window (atraso proposital para não sobrecarregar). Sem ele, expressões que caem no topo da hora (:00) recebem um atraso de até 5 minutos para evitar que todos os jobs disparem no mesmo segundo. Para briefings pessoais, o atraso geralmente não importa. Para integrações que dependem de timing preciso, --exact é necessário.

7. Caixa preta no repositório

O agente está configurado para abrir PRs, criar issues, e atualizar wikis automaticamente. O cron dispara, o agente age, e de repente o repositório tem 47 PRs abertos que ninguém revisou, issues duplicadas, e commits em branches que ninguém pediu.

O problema não é o cron — é o escopo. O agente tem permissão para fazer tudo, e o cron dispara sem supervisão.

{
  name: "code-review-semanal",
  cron: "0 10 * * 1",        // toda segunda às 10h
  permissions: {
    createPR: false,          // não abre PR sozinho
    createIssue: true,        // pode criar issues
    pushToMain: false,        // não envia para a branch principal
    requireApproval: true,    // aguarda sua confirmação antes de agir
  },
}

O requireApproval: true faz o agente preparar a ação mas aguardar confirmação antes de executar. Você recebe uma notificação com o resumo do que seria feito, e aprova ou rejeita. Isso transforma o cron de “dispara e esquece” em “prepara e confirma”.


Padroes de configuracao

Quatro receitas prontas que cobrem os cenários mais comuns.

Receita A — Sessao isolada para jobs pesados

Para tarefas que consomem muitos tokens ou rodam por mais de 30 segundos. A sessão isolada evita degradação e o modelo barato mantém o custo baixo.

openclaw cron add \
  --name "Análise semanal" \
  --cron "0 6 * * 1" \       # toda segunda às 6h
  --session isolated \
  --message "Análise profunda da semana" \
  --model haiku \
  --announce                 # avisa no canal quando começa e termina

O --announce envia uma confirmação curta no canal quando o job começa e quando termina. Sem ele, você só sabe que rodou se houver output explícito.

Receita B — Webhook para monitoramento externo

Para quem usa UptimeRobot, Betterstack, ou qualquer sistema de monitoramento externo. O webhook (aviso automático entre sistemas) desacopla a execução da notificação — se o seu Telegram cair, o job continua rodando e o monitoramento externo registra.

{
  delivery: {
    mode: "webhook",
    to: "https://seu-api.com/cron-webhook",  // URL que recebe o aviso
    bestEffort: true,
  },
}

Receita C — Hybrid heartbeat + cron

Heartbeat para checagens leves a cada 30 minutos com modelo gratuito. Cron para tarefas que precisam de timing preciso, com o modelo principal. Os dois coexistem sem conflito.

{
  heartbeat: {
    every: "30m",                                      // verifica a cada 30 minutos
    model: "openrouter/stepfun/step-3.5-flash:free",   // modelo gratuito
  },
  cron: [
    {
      name: "briefing-7h",
      cron: "0 7 * * *",           // todo dia às 7h
      tz: "America/Sao_Paulo",
      session: "isolated",
    },
  ],
}

Receita D — Timezone explícito com stagger controlado

Para jobs que precisam rodar no horário exato, sem atraso proposital.

openclaw cron add \
  --cron "0 7 * * *" \       # 7h exatas
  --tz "America/Sao_Paulo" \
  --exact                    # desabilita o atraso automático de até 5 min

Troubleshooting

job not found ao tentar editar

O ID do job muda após edição ou recriação. Use openclaw cron list para confirmar o ID atual antes de qualquer operação.

429 rate_limited em jobs com modelo gratuito

Modelos gratuitos via OpenRouter têm rate limit (limite de uso) de 50 req/min. Se você tem muitos agentes com heartbeat + cron no mesmo modelo, o limite estoura. Adicione um modelo pago como fallback (plano B).

Job roda mas não entrega

Verifique delivery.mode — se está none, o job executa mas não envia resultado para nenhum canal. Teste o canal separadamente com openclaw channels status --probe.

Stagger inesperado de 3-5 minutos

Expressões cron que caem no topo da hora (0 * * * *) recebem atraso automático por padrão. Use --exact para desabilitar.


Próximo passo

Esc