Prüfen Sie alle 15 Minuten eine öffentliche Seite oder API, lassen Sie den Agenten das Gefundene als JSON melden und posten Sie nur dann in Slack, wenn sich der Zustand ändert. Ephemeral führt die Prüfung nach Zeitplan aus; ein kleines Skript von Ihnen liest das Ergebnis und entscheidet, ob alarmiert wird.
Eine Prüfung, die eine Seite abruft, dauert etwa 20 Sekunden. Den größten Teil der Kosten macht die Rechenzeit aus, die mit $0.0002 pro Sekunde berechnet wird, dazu kommen $0.001 für den Seitenabruf. Der Anteil des Modells hängt vom gewählten Modell ab. Lesen Sie daher bei den ersten Ausführungen cost_micros aus und passen Sie danach den Zeitplan oder das Modell an.
Was Sie brauchen
- Ein API-Schlüssel mit der Rolle Admin, denn nur Inhaber und Admins können Zeitpläne erstellen. Siehe Rollen und Schlüssel.
- Die zu überwachende Seite oder API auf einer Domain, hier
https://status.example.com. - Eine eingehende Slack-Webhook-URL oder die Adresse Ihres eigenen Alarmdienstes.
- Ein Ort, an dem alle paar Minuten ein Skript laufen kann: cron, ein geplanter CI-Job oder ein Serverless-Timer.
Workflow speichern
Der Workflow ruft die Seite ab und antwortet in einer festen JSON-Form. Ephemeral erzwingt kein Ausgabeschema: Die Ausgabe der Ausführung ist freier Text. Daher verlangt der Prompt ausschließlich JSON, und Ihr Skript wertet es in Schritt 4 defensiv aus.
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 }'Der Webzugriff ist auf
status.example.combeschränkt und die Suche ist aus, die Prüfung kann also diese Seite lesen und sonst nichts. Die zu prüfende URL kommt als Eingabe, sodass derselbe Workflow mehr als einen Zeitplan auf dieser Domain bedienen kann.Zeitplan erstellen
Sehen Sie sich zuerst den Fahrplan in der Vorschau an. Er liefert die nächsten fünf Startzeiten und speichert nichts.
curl -X POST $EPHEMERAL_URL/v1/schedules/preview \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cron": "*/15 * * * *", "timezone": "UTC" }'Erstellen Sie ihn dann. Die Eingabe und das Budget sind für jede Ausführung gleich.
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 }'Notieren Sie sich die
iddes Zeitplans. Das Budget von 100.000 Mikro ($0.10) wird bei jedem Start aus Ihrem Guthaben reserviert und freigegeben, wenn die Ausführung abgerechnet ist; es muss die Rechenzeit für das gesamte Timeout decken, hier 90 Sekunden, also $0.018. Läuft eine Prüfung noch, wenn der nächste Start fällig ist, wird dieser Start übersprungen, dennskip_if_runningist standardmäßigtrue.Eine Ausführung sofort starten und die Antwort lesen
Warten Sie nicht auf den Fahrplan.
POST /v1/schedules/{id}/runstartet den Workflow sofort mit der Eingabe und dem Budget des Zeitplans und antwortet mit202und einer Ausführung, die die ID des Zeitplans trägt. Listen Sie dann die Ausführungen des Zeitplans auf, die neueste zuerst: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"outputist ein String, der das JSON enthält. Modelle verpacken es trotz der Anweisung manchmal in einen Codeblock oder fügen einen Satz hinzu. Das Skript unten nimmt daher alles vom ersten{bis zum letzten}und wertet das aus.Nur alarmieren, wenn sich etwas geändert hat
Geplante Ausführungen senden keine Callbacks, Ihr Skript fragt daher stattdessen nach der neuesten Ausführung des Zeitplans. Es merkt sich die letzte Ausführung und den letzten Zustand in einer Datei, ignoriert Ausführungen, die es schon gesehen hat oder die noch laufen, und postet nur dann in Slack, wenn sich der Zustand vom vorherigen unterscheidet. Eine Prüfung, die fehlschlägt oder etwas Unlesbares liefert, zählt als eigener Zustand,
unknown, damit ein defekter Monitor nicht wie eine gesunde Seite aussieht.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 }));Führen Sie es alle fünf Minuten aus, etwa mit
*/5 * * * *in cron, mit den vier gesetzten Variablen. Die erste Prüfung bleibt still, wenn die Seite gesund ist; jede spätere Änderung, auch die Erholung vondownzuok, postet einmal.
Gut zu wissen
| Thema | Verhalten |
|---|---|
| Überlappende Prüfungen | Ist skip_if_running an, wird ein Start übersprungen, solange die vorherige Ausführung noch läuft, und der Zeitplan vermerkt dies in last_error. Setzen Sie es nur dann auf false, wenn Überschneidung harmlos ist. |
| Ein Zeitplan, der stoppt | Nach fünf fehlgeschlagenen Starts in Folge, etwa weil das Guthaben aufgebraucht ist, schaltet sich der Zeitplan selbst ab, und es erscheinen keine neuen Ausführungen. Prüfen Sie enabled und last_error hin und wieder mit GET /v1/schedules/{id}, oder laden Sie Guthaben auf und setzen Sie enabled auf true. |
| Intervall ändern | PATCH /v1/schedules/{id} mit einem neuen cron; der nächste Start wird ab jetzt gezählt. |
| Pausieren | ephemeral schedules pause ID und resume, oder enabled in einem PATCH. |
POST /v1/runs, demselben Workflow und einem callback. Den Empfänger finden Sie im Rezept zur Zahlungsuntersuchung. Dann verzichten Sie auf den Überlappungsschutz und den Fahrplan von Ephemeral; behalten Sie Zeitpläne also für Arbeit, die Sie nicht pushen müssen.