Integrações
Funciona em qualquer ambiente
O CronObserver aceita um check-in HTTPS simples. Se a sua plataforma faz uma requisição HTTP, dá para monitorar.
Plataformas de agentes com agendador embutido
Quando o agendador mora dentro do agente, ele não pode ser o próprio vigia. Passo a passo testado em cada plataforma:
Agentes de IA e pipelines de LLM
Sinalize início, sucesso e falha. Uma execução com falha gera alerta na hora, com o motivo; uma execução que trava além do tempo máximo, ou que nunca começa, também gera alerta.
Agente em Python (LangGraph, CrewAI ou qualquer SDK de LLM)
O mesmo runId liga o início ao fim, então o CronObserver registra a duração. Saída vazia conta como falha.
import json, os, urllib.request, uuid
BASE = os.environ["CRONOBSERVER_CHECKIN_URL"] # https://cronobserver.com/checkin/<token>
RUN_ID = str(uuid.uuid4())
def ping(suffix: str = "", **payload) -> None:
req = urllib.request.Request(
BASE + suffix,
data=json.dumps({"runId": RUN_ID, **payload}).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
urllib.request.urlopen(req, timeout=10)
except Exception:
pass # monitoring must never break the job
ping("/start")
try:
result = run_agent()
if result.items == 0:
raise RuntimeError("agent produced nothing")
ping(model=result.model, tokens_in=result.tokens_in, tokens_out=result.tokens_out,
cost_usd=result.cost_usd, items_processed=result.items)
except Exception as exc:
ping("/fail", exitCode=1, message=str(exc)[:500])
raiseRotina do Claude Code / Codex
O cron chama um script (cada entrada do crontab precisa caber em uma linha). O test -s falha com saída vazia, então um agente que "dá certo" sem entregar nada ainda gera alerta.
# crontab -e (every day at 21:00, host time)
CO_URL=https://cronobserver.com/checkin/<token>
0 21 * * * /opt/agents/summary/run.sh
# /opt/agents/summary/run.sh (chmod +x)
#!/bin/sh
cd /opt/agents/summary || exit 1
curl -fsS --retry 3 -X POST "$CO_URL/start"
if claude -p "$(cat prompt.md)" > out.md && test -s out.md; then
curl -fsS --retry 3 -X POST "$CO_URL"
else
curl -fsS --retry 3 -X POST "$CO_URL/fail" -H 'Content-Type: application/json' \
-d '{"exitCode":1,"message":"empty or failed run"}'
fin8n
Coloque o HTTP Request como último nó do caminho de sucesso: se um nó antes dele der erro, nenhum ping é enviado. Adicione um workflow com Error Trigger que faz POST em …/checkin/<token>/fail com o erro, para o alerta já chegar com o motivo.
Schedule Trigger → … your AI nodes … → HTTP Request
Method: POST
URL: https://cronobserver.com/checkin/<token>
Body: JSON (optional) {"status": "success", "items_processed": {{ $json.count }}}
Error Trigger → HTTP Request
Method: POST
URL: https://cronobserver.com/checkin/<token>/fail
Body: JSON {"message": "{{ $json.execution.error.message }}"}Make
Adicione como último módulo: o Make interrompe o cenário quando há erro, então uma execução com falha nunca faz check-in. Na rota do error handler, faça POST em …/checkin/<token>/fail para ter o motivo no alerta.
Scenario: … → HTTP › Make a request URL: https://cronobserver.com/checkin/<token> Method: POST Error handler route → HTTP › Make a request URL: https://cronobserver.com/checkin/<token>/fail Method: POST
GitHub Actions rodando um agente
Faça check-in quando der certo; reporte a falha (com uma mensagem) quando qualquer etapa falhar.
on:
schedule:
- cron: "0 6 * * *"
jobs:
agent:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python agents/triage.py
- name: Check in
if: success()
run: |
curl -fsS --retry 3 -X POST "${{ secrets.CRONOBSERVER_CHECKIN_URL }}"
- name: Report failure
if: failure()
run: |
curl -fsS --retry 3 -X POST "${{ secrets.CRONOBSERVER_CHECKIN_URL }}/fail" \
-H 'Content-Type: application/json' -d '{"exitCode":1,"message":"workflow failed"}'Cron, containers e CI
Linux / Unix Cron
Adicione uma chamada curl depois que o script terminar e configure a tolerância para evitar alertas falsos.
# crontab entries are one line each 0 * * * * /app/scripts/report.sh && curl -fsS --retry 3 -X POST https://cronobserver.com/checkin/<token>
Kubernetes CronJob
Envolva o container do job e chame o endpoint de check-in quando o trabalho terminar. Sua imagem precisa ter curl (alpine: apk add --no-cache curl).
apiVersion: batch/v1
kind: CronJob
metadata:
name: report-job
spec:
schedule: "*/30 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: curlimages/curl:8.11.1
command: ["sh", "-c", "run-task && curl -fsS --retry 3 -X POST https://cronobserver.com/checkin/<token>"]Laravel Scheduler
Use hooks onSuccess para enviar o heartbeat só quando o comando artisan terminar com sucesso.
Schedule::command('reports:daily')
->daily()
->onSuccess(fn () =>
Http::post('https://cronobserver.com/checkin/<token>')
);Node.js / Fetch
Aguarde a promise do job e depois dispare um POST para confirmar a execução.
await runJob();
await fetch('https://cronobserver.com/checkin/<token>', {
method: 'POST'
});Pipelines de CI
Use curl ou bibliotecas HTTP no GitHub Actions, no GitLab CI ou em qualquer pipeline, depois da última etapa.
- name: heartbeat
run: |
curl -fsS -X POST https://cronobserver.com/checkin/<token>Precisa de uma stack específica?
Se faz uma requisição HTTP quando o job termina, funciona com o CronObserver. Conte qual é a sua stack e indicamos o exemplo mais próximo.