Bauen Sie ein Support-Tool, das eine Zahlungs-ID entgegennimmt und die Frage "Warum ist diese Zahlung fehlgeschlagen?" anhand Ihrer Zahlungs-API und Ihrer Statusseite beantwortet. Der Agent kann nur lesen: Er kann nichts erstatten, wiederholen oder ändern. Die Einrichtung dauert etwa fünfzehn Minuten.
Eine solche Ausführung dauert meist 10 bis 15 Sekunden. Den größten Teil der Kosten macht die Rechenzeit aus, die mit $0.0002 pro Sekunde berechnet wird, und jede vom Agenten abgerufene Seite kostet $0.001. Der Anteil des Modells hängt vom gewählten Modell ab. Lesen Sie daher bei den ersten Ausführungen cost_micros aus. Das Budget von $0.50 ist eine Obergrenze, kein Preis.
Was Sie brauchen
- Ein Ephemeral-Konto mit Guthaben und zwei API-Schlüssel unter API-Schlüssel: ein Mitglieder-Schlüssel für Ihr Backend, das Ausführungen startet, und ein Admin-Schlüssel für die einmalige Einrichtung der Verbindung. Siehe Rollen und Schlüssel.
- Die Basis-URL Ihrer Zahlungs-API (HTTPS, aus dem Internet erreichbar) und ein Schlüssel nur zum Lesen dafür, etwa ein eingeschränkter Schlüssel, der nur Zahlungen lesen darf.
- Eine öffentliche Statusseite auf einer Domain, hier
status.example.com. - Ein HTTPS-Endpunkt auf Ihrem Server, der das Ergebnis empfängt.
export EPHEMERAL_URL=https://app.ephemer.al export EPHEMERAL_API_KEY=eak_… # member key, for your backend export EPHEMERAL_ADMIN_KEY=eak_… # admin key, for setup only export EPHEMERAL_CALLBACK_SECRET=$(openssl rand -hex 16) # 32 characters; keep it on your serverPlaybook schreiben und hochladen
Im Playbook steckt das Wissen Ihres Teams: welche Aufrufe zu machen sind und wie die Antwort zu lesen ist. Halten Sie es kurz und konkret. Der Agent erhält es als schreibgeschützte Datei neben der Aufgabe.
# Failed payment playbook You can only read. The payments connection allows GET, and web access is limited to status.example.com. 1. GET /payments/{payment_id}. Note status, amount, currency, failure_code and failure_message. 2. GET /payments/{payment_id}/attempts. Check whether earlier attempts failed for the same reason. 3. If failure_code is processor_error or timeout, read https://status.example.com for incidents around that time. 4. Decide the cause: - card_declined, insufficient_funds, expired_card: the customer's bank or card. Suggest a retry or another card. - processor_error, timeout: ours or the processor's. Say whether the status page shows an incident. - fraud_review: a risk rule held it. Do not suggest bypassing it. 5. Never guess. If a call fails or a field is missing, say so. Answer in at most six lines: the cause, the evidence (field and value) and the next step for the support agent. Do not include card numbers or customer email addresses.curl $EPHEMERAL_URL/v1/files \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" \ -F [email protected]Die Datei wird unter dem Namen
playbook.mdgespeichert. Laden Sie sie erneut hoch, entsteht eine neue Version, und Workflows, die die Datei nennen, übernehmen beim Start einer Ausführung die neueste. Siehe Dateien.Verbindung payments-api erstellen
Eine Verbindung hält die Adresse und den Schlüssel der API innerhalb von Ephemeral. Der Agent ruft sie über den Namen auf und sieht den Schlüssel nie. Setzen Sie
allowed_methodsauf["GET"], damit jede andere Methode abgelehnt wird.curl -X PUT $EPHEMERAL_URL/v1/connections/payments-api \ -H "Authorization: Bearer $EPHEMERAL_ADMIN_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "http", "url": "https://api.example.com/v1", "auth": { "type": "bearer", "token": "rk_live_…" }, "allowed_methods": ["GET"], "instructions": "Look up a payment with GET /payments/{id} and its attempts with GET /payments/{id}/attempts. Amounts are in cents." }'Lieber im Dashboard? Öffnen Sie Verbindungen, wählen Sie Verbindung hinzufügen und HTTP-API, geben Sie den Namen
payments-apiund die Basis-URL ein, wählen Sie Bearer-Token und fügen Sie den Schlüssel ein. Wählen Sie dann unter Erlaubte HTTP-Methoden nurGET. Dieinstructionssagen dem Agenten, welche Endpunkte es gibt; er bekommt sie angezeigt, halten Sie also Geheimnisse heraus.Beim erneuten Lesen der Verbindung wird kein Token angezeigt, und
GET /v1/catalog/connectionslistet sie für Mitglieder mit Typ und erlaubten Methoden auf, ohne URL und ohne Zugangsdaten.Workflow speichern
Ein Workflow hält die Aufgabe, das Playbook, die Verbindung und die Limits unter einem Namen zusammen, sodass Ihr Backend nur die Zahlungs-ID sendet. Der Agent sieht die Verbindung als
payments. Der Webzugriff ist auf die Statusseite beschränkt, und die Shell ist aus, weil die Aufgabe keine Befehle braucht.curl -X PUT $EPHEMERAL_URL/v1/workflows/investigate-payment \ -H "Authorization: Bearer $EPHEMERAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Find out why this payment failed.", "files": [{ "file": "playbook.md" }], "connections": { "payments": { "ref": "payments-api", "allowed_methods": ["GET"] } }, "web": { "allow": ["status.example.com"] }, "shell": false, "timeout_seconds": 120 }'Es ist kein
modelgesetzt, daher verwendet jede Ausführung das Standardmodell zum Zeitpunkt ihres Starts. Wählen Sie bei Bedarf ein anderes aus dem Modellkatalog. Die Zahlungs-ID, das Budget und der Callback gehören zur jeweiligen Ausführung, nicht zum Workflow.Ausführung aus Ihrem Backend starten
Senden Sie den Workflow-Namen, die Zahlungs-ID, das Budget und einen Callback. Der
Idempotency-Keymacht eine Wiederholung sicher: Ein wiederholter Schlüssel liefert die bereits vorhandene Ausführung mit200zurück, statt eine zweite zu starten. Verwenden Sie einen Schlüssel, den Sie neu bilden können, etwa die Zahlungs-ID oder Ihre Ticket-ID.const paymentId = "pay_123"; const response = await fetch(`${process.env.EPHEMERAL_URL}/v1/runs`, { method: "POST", headers: { Authorization: `Bearer ${process.env.EPHEMERAL_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": `investigate-${paymentId}`, }, body: JSON.stringify({ workflow: "investigate-payment", input: { payment_id: paymentId }, max_cost_micros: 500000, callback: { url: "https://example.com/hooks/ephemeral", secret: process.env.EPHEMERAL_CALLBACK_SECRET, }, }), }); const run = await response.json(); // { id: "run_…", status: "queued", … }Die Antwort ist
202 Acceptedmit dem Ausführungsobjekt im Statusqueued. Die Ausführung startet, sobald ein Worker frei ist. Die Callback-URL muss HTTPS verwenden und auf eine öffentliche Adresse auflösen, und ein Secret muss 24 bis 1.024 Zeichen lang sein; andernfalls schlägt die Anfrage mit400fehl, und nichts wird gestartet. Beim gehosteten Dienst bedeutet402, dass Ihr Guthaben das Budget nicht deckt.Callback prüfen
Erreicht die Ausführung einen Endstatus, sendet Ephemeral genau einen signierten
POSTmit dem Ausführungsobjekt. Prüfen Sie die Signatur anhand der Rohbytes des Bodys, bevor Sie etwas darin für wahr halten. Der signierte Text besteht aus demX-Ephemeral-Timestamp-Header, einem Punkt und dem Body, signiert mit HMAC-SHA256 und Ihrem Secret. Das vollständige Verfahren steht unter Callbacks.import crypto from "node:crypto"; import http from "node:http"; const handled = new Set(); // use your database in production http .createServer((req, res) => { const chunks = []; req.on("data", (chunk) => chunks.push(chunk)); req.on("end", () => { const body = Buffer.concat(chunks); const timestamp = req.headers["x-ephemeral-timestamp"] ?? ""; const signature = req.headers["x-ephemeral-signature"] ?? ""; const expected = "sha256=" + crypto .createHmac("sha256", process.env.EPHEMERAL_CALLBACK_SECRET) .update(timestamp + ".") .update(body) .digest("hex"); const valid = signature.length === expected.length && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300; if (!valid || !fresh) return res.writeHead(401).end(); const run = JSON.parse(body); if (!handled.has(run.id)) { handled.add(run.id); // Attach run.output to the support ticket for run.id here. } res.writeHead(204).end(); // any 2xx counts as delivered }); }) .listen(3000); // serve this behind HTTPS at /hooks/ephemeralJede Antwort, die nicht
2xxist, wird mit wachsenden Abständen wiederholt, sodass dieselbe Ausführung zweimal eintreffen kann. Deshalb merkt sich der Handler die Ausführungs-IDs.Ergebnis lesen
Der Body des Callbacks ist das Ausführungsobjekt. Für die Beispielzahlung sieht es so aus:
{ "id": "run_118622d16f00105f7bba6d2281774705", "status": "succeeded", "output": "- **Cause:** The customer’s bank declined the payment for insufficient funds.\n- **Evidence:** `failure_code: insufficient_funds`; `failure_message: The card issuer declined the charge: insufficient funds.`\n- **Attempts:** Both attempts failed for the same reason.\n- **Next step:** Suggest the customer retry after resolving the balance issue or use another card.", "created_at": "2026-10-03T09:14:05.118Z", "started_at": "2026-10-03T09:14:05.402Z", "finished_at": "2026-10-03T09:14:16.447Z", "max_cost_micros": 500000, "cost_micros": 2618, "billing_pending": false, "zero_data_retention": false }outputist die Antwort des Agenten als Text.cost_microssind die gesamten Kosten in Millionstel Dollar, hier $0.002618. Eine Ausführung, die nicht erfolgreich war, hat denstatusfailed,timed_outodercancelledund statt einer Ausgabe einenerror; zeigen Sie das Ihrem Agenten, statt nichts anzuzeigen. Istbilling_pendingtrue, sind die Kosten noch vorläufig: lesen Sie die Ausführung etwas später erneut mitGET /v1/runs/{id}. Um jeden Aufruf des Agenten zu sehen, öffnen Sie die Ausführung im Dashboard oder streamen Sie ihre Ereignisse.
Warum es sicher ist
| Risiko | Was es verhindert |
|---|---|
| Der Agent ändert oder erstattet eine Zahlung. | Die Verbindung und der Workflow erlauben beide nur GET; jede andere Methode wird mit HTTP method not permitted abgelehnt. |
| Der Zahlungsschlüssel gelangt nach außen. | Der Schlüssel bleibt in Ephemeral. Die microVM hat weder Netzwerk noch Schlüssel; der Broker fügt den Schlüssel jeder Anfrage hinzu und entfernt Zugangsdaten aus Antworten. |
| Daten gehen an eine unbekannte Seite. | Der Webzugriff erlaubt nur status.example.com, und Weiterleitungen werden gegen dieselbe Liste geprüft. Siehe Webzugriff. |
| Der Agent führt Befehle aus. | shell ist false. |
| Eine Ausführung kostet mehr als erwartet. | Das Budget von 500.000 Mikro ($0.50) wird beim Start reserviert und kann nicht überschritten werden; timeout_seconds beendet die Ausführung nach 120 Sekunden. |
| Jemand fälscht das Ergebnis. | Ihr Endpunkt akzeptiert nur Anfragen, deren Signatur stimmt. |