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])
    raise

Rotina 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"}'
fi

n8n

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.