Boa parte do Studio roda em um agendamento, e não em resposta a uma requisição de usuário: workflows agendados, todos os triggers de polling, syncs de conectores, o outbox, a drenagem de dados e a retenção. Tudo isso é movido por endpoints HTTP que algo externo precisa chamar em intervalos regulares.
Os dois modelos de implantação já incluem um agendador e o habilitam por padrão: o Kubernetes como CronJobs, o Docker Compose como um serviço cron. Os dois autenticam com o CRON_SECRET e usam os mesmos agendamentos.
Autenticação
Todos os endpoints são protegidos pelo CRON_SECRET e o esperam como bearer token:
curl -f -s -S --max-time 60 \
-H "Authorization: Bearer $CRON_SECRET" \
https://studio.yourdomain.com/api/schedules/executeGere-o como os outros secrets:
openssl rand -hex 32O CRON_SECRET é obrigatório sempre que os jobs em segundo plano estiverem habilitados — o que é o padrão do Helm chart. O chart se recusa a renderizar sem ele. Se não estiver definido, os endpoints rejeitam todas as chamadas e todo o trabalho agendado para silenciosamente.
Aponte o cron para um endereço interno quando possível (o Service dentro do cluster, ou localhost em um nó único). Esses endpoints não deveriam ser acessíveis pela internet; se forem, o CRON_SECRET é a única coisa que os protege.
Os jobs
| Job | Endpoint | Agendamento | Movimenta |
|---|---|---|---|
| Execução de agendamentos | /api/schedules/execute | */1 * * * * | Workflows agendados |
| Polling do Gmail | /api/webhooks/poll/gmail | */1 * * * * | Trigger do Gmail |
| Polling do Outlook | /api/webhooks/poll/outlook | */1 * * * * | Trigger do Outlook |
| Polling de IMAP | /api/webhooks/poll/imap | */1 * * * * | Trigger de IMAP |
| Polling de RSS | /api/webhooks/poll/rss | */1 * * * * | Trigger de RSS |
| Polling do Google Sheets | /api/webhooks/poll/google-sheets | */1 * * * * | Trigger do Sheets |
| Polling do Google Drive | /api/webhooks/poll/google-drive | */1 * * * * | Trigger do Drive |
| Polling do Google Calendar | /api/webhooks/poll/google-calendar | */1 * * * * | Trigger do Calendar |
| Polling do HubSpot | /api/webhooks/poll/hubspot | */1 * * * * | Trigger do HubSpot |
| Pausa/retomada por tempo | /api/resume/poll | */1 * * * * | Workflows pausados por tempo |
| Processamento do outbox | /api/webhooks/outbox/process | */1 * * * * | Retentativas do outbox transacional para cobrança, participação, emissão enterprise e efeitos colaterais do deploy de workflows |
| Sync de conectores | /api/knowledge/connectors/sync | */5 * * * * | Syncs dos conectores da base de conhecimento |
| Polling de eventos de workspace | /api/workspace-events/poll | */15 * * * * | Triggers de eventos de workspace |
| Drenagem de dados | /api/cron/run-data-drains | 0 * * * * | Drenagem de dados enterprise |
| Renovação de assinaturas | /api/cron/renew-subscriptions | 0 */12 * * * | Renova as assinaturas de chat do Microsoft Teams (o Graph as limita a cerca de 3 dias) |
| Reconciliação de assentos de cobrança | /api/cron/reconcile-billing-seats | 0 * * * * | Só cobrança — pode ser desativado com segurança na auto-hospedagem |
| Reconciliação de acesso ao inbox | /api/cron/reconcile-inbox-entitlement | 0 3 * * * | Reconciliação de acesso ao inbox |
| Limpeza de imagens de sandbox | /api/cron/cleanup-sandbox-images | 30 4 * * * | Recupera espaço das imagens de sandbox |
A renovação de assinaturas cobre os triggers de chat do Microsoft Teams, cujas assinaturas no Microsoft Graph têm limite fixo de cerca de três dias. Sem ela, os triggers do Teams funcionam por alguns dias e depois param sem aviso. Os triggers de Gmail, Outlook, Drive, Calendar e Sheets funcionam por polling — eles dependem dos jobs de polling por minuto acima, não deste.
Kubernetes
Habilitado por padrão. Não há nada a fazer além de definir o CRON_SECRET.
cronjobs:
enabled: trueCada job roda um pequeno pod curlimages/curl que chama o Service do app dentro do cluster (não o ingress), com concurrencyPolicy: Forbid para que uma execução lenta nunca se sobreponha a si mesma, e até três retentativas.
Desative individualmente os jobs de que você não precisa — a reconciliação de cobrança é o caso mais óbvio em uma instalação auto-hospedada:
cronjobs:
jobs:
reconcileBillingSeats:
enabled: falseVerifique se estão rodando:
kubectl get cronjobs -n studio
kubectl get jobs -n studio --sort-by=.metadata.creationTimestamp | tail
kubectl logs -n studio job/<job-name>Um CronJob cujo LAST SCHEDULE está desatualizado, ou cujos jobs estão falhando, significa que o recurso correspondente está morto. Crie um alerta para isso — veja Observabilidade.
Docker Compose
O serviço cron roda os mesmos jobs nos mesmos agendamentos, então não há nada a configurar além do CRON_SECRET:
CRON_SECRET=$(openssl rand -hex 32)Sem ele, o serviço cron registra no log exatamente o que definir — inclusive um valor recém-gerado — e encerra, deixando o resto da stack em pé. Os agendamentos ficam em docker/crontab e espelham um a um o cronjobs.jobs de helm/studio/values.yaml.
Está atualizando uma implantação criada antes de o agendador existir? Seu .env não tem CRON_SECRET, então a stack sobe como antes e o cron encerra com instruções. Adicione o valor e rode up -d de novo para ligar os jobs em segundo plano.
O serviço roda o supercronic em vez da imagem do app: ele registra a saída de cada job no log do contêiner, repassa o SIGTERM para que docker compose stop seja gracioso, e não inicia uma iteração enquanto a anterior ainda está em execução.
docker compose -f docker-compose.prod.yml logs -f cronUma linha de log saudável se parece com isto:
level=info msg=starting iteration=0 job.schedule="*/1 * * * *"
level=info msg="job succeeded" iteration=0Para descartar um job de que você não precisa, comente a linha dele em docker/crontab e reinicie o serviço.
Verificando
Crie um workflow com um trigger Schedule definido para cada minuto, faça o deploy e acompanhe a visão Logs. Uma execução deve aparecer em cerca de 2 minutos. Se nada aparecer:
- Verifique os logs do próprio agendador —
docker compose logs cron, oukubectl get cronjobs -n studiopara conferir umLAST SCHEDULErecente. - Confirme que o app e o agendador compartilham o mesmo
CRON_SECRET. Uma divergência aparece como401no log do agendador. - Um
202significa que o endpoint aceitou a chamada; não confirma que havia um agendamento a executar, então confira a visão Logs.
Concorrência
O volume de execuções agendadas é limitado por instância do app por:
| Variável | Padrão | Aplica-se a |
|---|---|---|
SCHEDULE_EXECUTION_CONCURRENCY_LIMIT | 30 | Workflows agendados em andamento, em qualquer instalação |
WORKFLOW_EXECUTION_CONCURRENCY_LIMIT, WEBHOOK_EXECUTION_CONCURRENCY_LIMIT e RESUME_EXECUTION_CONCURRENCY_LIMIT são configurações de concurrencyLimit em definições de tarefa do Trigger.dev. Elas não têm efeito a menos que TRIGGER_DEV_ENABLED esteja definido, e nem o Helm chart nem o Docker Compose configuram o Trigger.dev — então, em uma auto-hospedagem padrão, elas são inertes.
Só aumente o limite de agendamentos junto com folga de memória: as execuções concorrentes rodam no processo do app, então a vazão é limitada pela memória do pod antes de ser limitada por esse número.