Verifique uma página ou API pública a cada 15 minutos, peça ao agente que informe o que encontrar em JSON e publique no Slack apenas quando o estado mudar. O Ephemeral executa a verificação em um agendamento; um pequeno script seu lê o resultado e decide se deve alertar.
Uma verificação que busca uma página leva cerca de 20 segundos. A maior parte do custo é a computação, cobrada a $0.0002 por segundo, mais $0.001 pela busca da página. A parte do modelo depende do modelo que você escolher; por isso, leia cost_micros nas primeiras execuções e ajuste o agendamento ou o modelo a partir daí.
Reúna o que você precisa
- Uma chave de API com a função de administrador, porque só proprietários e administradores podem criar agendamentos. Veja funções e chaves.
- A página ou API a observar, em um único domínio, aqui
https://status.example.com. - Uma URL de webhook de entrada do Slack, ou o endereço do seu próprio serviço de alertas.
- Um lugar para executar um script a cada poucos minutos: cron, uma tarefa de CI agendada ou um timer serverless.
Salve o fluxo de trabalho
O fluxo de trabalho busca a página e responde em um formato JSON fixo. O Ephemeral não impõe um esquema de saída: a saída da execução é texto livre. Por isso o prompt pede apenas JSON, e o seu script o interpreta com cautela no passo 4.
curl -X PUT $EPHEMERAL_URL/v1/workflows/check-status-page \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Fetch the page at input.url with web_fetch. Reply with one JSON object and nothing else: {\"ok\": boolean, \"http_status\": number, \"summary\": string}. Set ok to true only when the response status is 200 and the page reports no ongoing incident, outage or degraded service; resolved past incidents do not count. summary is one sentence of at most 200 characters.", "web": { "allow": ["status.example.com"], "search": false }, "shell": false, "timeout_seconds": 90 }'O acesso à web fica limitado a
status.example.come a pesquisa fica desligada, então a verificação pode ler esse site e mais nada. A URL a verificar chega como entrada, de modo que o mesmo fluxo de trabalho pode atender a mais de um agendamento nesse domínio.Crie o agendamento
Primeiro, pré-visualize a programação. Ela retorna os próximos cinco horários de início e não salva nada.
curl -X POST $EPHEMERAL_URL/v1/schedules/preview \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cron": "*/15 * * * *", "timezone": "UTC" }'Depois, crie-o. A entrada e o orçamento são os mesmos em todas as execuções.
curl -X POST $EPHEMERAL_URL/v1/schedules \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "workflow": "check-status-page", "name": "Status page, every 15 minutes", "cron": "*/15 * * * *", "input": { "url": "https://status.example.com" }, "max_cost_micros": 100000 }'Guarde o
iddo agendamento. O orçamento de 100.000 micros ($0.10) é reservado dos seus créditos a cada início e liberado quando a execução é liquidada; ele precisa cobrir a computação do tempo limite inteiro, que aqui é de 90 segundos, ou $0.018. Se uma verificação ainda estiver em andamento quando o próximo início estiver previsto, esse início é ignorado, porqueskip_if_runningétruepor padrão.Inicie uma agora e leia a resposta
Não espere pela programação.
POST /v1/schedules/{id}/runinicia o fluxo de trabalho agora com a entrada e o orçamento do agendamento e responde202com uma execução que carrega o ID do agendamento. Depois, liste as execuções do agendamento, da mais recente para a mais antiga:curl -X POST $EPHEMERAL_URL/v1/schedules/$SCHEDULE_ID/run \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" curl "$EPHEMERAL_URL/v1/runs?schedule=$SCHEDULE_ID&limit=1" \ -H "Authorization: Bearer $EPHEMERAL_API_KEY"outputé uma string que contém o JSON. Às vezes os modelos o envolvem em um bloco de código ou acrescentam uma frase apesar da instrução, então o script abaixo pega tudo desde o primeiro{até o último}e interpreta esse trecho.Alerte apenas quando algo mudar
As execuções agendadas não enviam callbacks, então o seu script consulta a execução mais recente do agendamento. Ele memoriza em um arquivo a última execução e o último estado, ignora as execuções que já viu ou que ainda estão em andamento e publica no Slack apenas quando o estado difere do anterior. Uma verificação que falha ou retorna algo ilegível conta como um estado próprio,
unknown, para que um monitor quebrado não pareça uma página saudável.import { readFile, writeFile } from "node:fs/promises"; const { EPHEMERAL_URL, EPHEMERAL_API_KEY, SCHEDULE_ID, SLACK_WEBHOOK_URL } = process.env; const ACTIVE = new Set(["reserving", "queued", "starting", "running"]); const stateFile = "monitor-state.json"; const state = JSON.parse(await readFile(stateFile, "utf8").catch(() => "{}")); const response = await fetch(`${EPHEMERAL_URL}/v1/runs?schedule=${SCHEDULE_ID}&limit=1`, { headers: { Authorization: `Bearer ${EPHEMERAL_API_KEY}` }, }); if (!response.ok) throw new Error(`Ephemeral returned ${response.status}`); const [run] = (await response.json()).items; if (!run || ACTIVE.has(run.status) || run.id === state.run) process.exit(0); // nothing new to judge let label = "unknown"; // the check itself did not produce an answer let summary = run.error ?? `The run ${run.status}.`; if (run.status === "succeeded") { try { const result = JSON.parse(run.output.match(/\{[\s\S]*\}/)[0]); // tolerate text or a code fence around the JSON label = result.ok === true ? "ok" : "down"; summary = result.summary; } catch { summary = "The check did not return valid JSON."; } } if (label !== (state.label ?? "ok")) { await fetch(SLACK_WEBHOOK_URL, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text: `Status page: ${label}. ${summary} (${run.id})` }), }); } await writeFile(stateFile, JSON.stringify({ run: run.id, label }));Execute-o a cada cinco minutos, por exemplo com
*/5 * * * *no cron, com as quatro variáveis definidas. A primeira verificação fica em silêncio quando a página está saudável; cada mudança posterior, incluindo a recuperação dedownparaok, publica uma vez.
Bom saber
| Tema | Comportamento |
|---|---|
| Verificações sobrepostas | Com skip_if_running ativado, um início é ignorado enquanto a execução anterior ainda está em andamento, e o agendamento registra isso em last_error. Defina como false apenas se a sobreposição for inofensiva. |
| Um agendamento que para | Após cinco inícios com falha seguidos, por exemplo porque os créditos acabaram, o agendamento se desativa sozinho e nenhuma nova execução aparece. Confira enabled e last_error com GET /v1/schedules/{id} de vez em quando, ou recarregue os créditos e defina enabled como true. |
| Alterando o intervalo | PATCH /v1/schedules/{id} com um novo cron; o próximo início é contado a partir de agora. |
| Pausando | ephemeral schedules pause ID e resume, ou enabled em um PATCH. |
POST /v1/runs, o mesmo fluxo de trabalho e um callback. O receptor é o de a receita de investigação de pagamento. Assim você abre mão da proteção contra sobreposição e da programação do Ephemeral, então reserve os agendamentos para o trabalho que você não precisa empurrar.