Rezepte

Eine fehlgeschlagene Zahlung untersuchen

Ein Support-Tool nur zum Lesen: Zahlungs-ID hinein, Ursache des Fehlschlags heraus.

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.

  1. 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.
    Terminal
    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 server
  2. Playbook 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.

    playbook.md
    # 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.md gespeichert. 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.

  3. 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_methods auf ["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-api und 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 nur GET. Die instructions sagen 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/connections listet sie für Mitglieder mit Typ und erlaubten Methoden auf, ohne URL und ohne Zugangsdaten.

  4. 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 model gesetzt, 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.

  5. Ausführung aus Ihrem Backend starten

    Senden Sie den Workflow-Namen, die Zahlungs-ID, das Budget und einen Callback. Der Idempotency-Key macht eine Wiederholung sicher: Ein wiederholter Schlüssel liefert die bereits vorhandene Ausführung mit 200 zurü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 Accepted mit dem Ausführungsobjekt im Status queued. 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 mit 400 fehl, und nichts wird gestartet. Beim gehosteten Dienst bedeutet 402, dass Ihr Guthaben das Budget nicht deckt.

  6. Callback prüfen

    Erreicht die Ausführung einen Endstatus, sendet Ephemeral genau einen signierten POST mit 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 dem X-Ephemeral-Timestamp-Header, einem Punkt und dem Body, signiert mit HMAC-SHA256 und Ihrem Secret. Das vollständige Verfahren steht unter Callbacks.

    Node.js, ohne Abhängigkeiten
    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/ephemeral

    Jede Antwort, die nicht 2xx ist, wird mit wachsenden Abständen wiederholt, sodass dieselbe Ausführung zweimal eintreffen kann. Deshalb merkt sich der Handler die Ausführungs-IDs.

  7. Ergebnis lesen

    Der Body des Callbacks ist das Ausführungsobjekt. Für die Beispielzahlung sieht es so aus:

    JSON
    {
      "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
    }

    output ist die Antwort des Agenten als Text. cost_micros sind die gesamten Kosten in Millionstel Dollar, hier $0.002618. Eine Ausführung, die nicht erfolgreich war, hat den status failed, timed_out oder cancelled und statt einer Ausgabe einen error; zeigen Sie das Ihrem Agenten, statt nichts anzuzeigen. Ist billing_pending true, sind die Kosten noch vorläufig: lesen Sie die Ausführung etwas später erneut mit GET /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

RisikoWas 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.
Geben Sie dem Lese-Schlüssel nur Lesezugriff
Die Verbindung begrenzt, was der Agent aufrufen kann, doch ein Schlüssel, der nur lesen darf, ist die stärkere Garantie. Erstellen Sie bei Ihrem Zahlungsanbieter einen eingeschränkten Schlüssel allein für diese Verbindung, damit Sie ihn getrennt widerrufen können.
Das Playbook feinabstimmen
Lassen Sie es an ein paar bekannten Fehlschlägen laufen und lesen Sie die Ausgabe. Ist sie falsch, ändern Sie das Playbook und laden es erneut hoch; die nächste Ausführung verwendet die neue Datei. Unter Workflows steht, wie gespeicherte Felder und Überschreibungen pro Ausführung zusammenwirken.
© 2026 EphemeralProduziert von erni.works
esc

Keine Treffer für „“.