KI-Agenten und langlaufende API-Aufrufe: Polling vs. Webhooks

Agenten lesen 202 Accepted als erledigt und melden Erfolg bei Aufträgen, die nie abgeschlossen wurden. Erfahren Sie, welchem asynchronen Vertrag Agenten folgen, und wie Sie den Timeout-Pfad testen.

Ashley Innocent

Ashley Innocent

26 August 2026

KI-Agenten und langlaufende API-Aufrufe: Polling vs. Webhooks

Apidog für Unternehmen

On-Premises Bereitstellung

SSO & RBAC

SOC 2 konform

Apidog Enterprise entdecken

Der Agent ruft Ihren Video-Transkodierungs-Endpunkt auf. Der Endpunkt gibt 202 Accepted und eine Auftrags-ID zurück. Der Agent, der keine Ahnung hat, was 202 in Ihrem System bedeutet, meldet, dass die Transkodierung abgeschlossen ist, und geht zum nächsten Schritt über, der eine Datei liest, die noch nicht existiert.

Langlaufende Operationen stören Agenten auf eine bestimmte Weise. Ein synchroner Aufruf hat einen offensichtlichen Vertrag: Sie senden, Sie warten, Sie erhalten eine Antwort. Ein asynchroner Aufruf teilt dies in einen Start und ein Ende auf, und die Lücke dazwischen ist der Punkt, an dem Agenten verwirrt werden. Sie melden den Erfolg zu früh, sie fragen tausendmal in einer engen Schleife ab, oder sie sitzen sechs Minuten lang blockiert und halten einen Gesprächszug offen.

Dieser Leitfaden behandelt, wie man den asynchronen Vertrag so gestaltet, dass ein Agent ihm folgen kann, wann man abfragen und wann man übergeben sollte, wie man die Tools schreibt, damit sich das Modell richtig verhält, und wie man den gesamten Pfad einschließlich der langsamen und fehlgeschlagenen Fälle testet. Unser Beitrag zur Fehlerbehebung für KI-Agenten behandelt die Fehlerseite von API-Aufrufen; dieser hier behandelt diejenigen, die langsam erfolgreich sind.

Apidog passt genau dann, wenn Sie beweisen müssen, dass der Agent eine Aufgabe bewältigt, die vier Minuten dauert und dann fehlschlägt, was Sie in der Produktion nicht entdecken möchten.

Warum Agenten asynchrone Vorgänge falsch handhaben

Drei Gewohnheiten verursachen die meisten Probleme.

Modelle behandeln ein 2xx als erledigt. Ein 202 besagt, dass die Anfrage zur Verarbeitung angenommen wurde, und die HTTP-Semantik-Spezifikation legt explizit fest, dass die Verarbeitung möglicherweise noch nicht abgeschlossen ist. Modelle, die auf gewöhnlichem Anfrage-/Antwort-Verkehr trainiert wurden, neigen dazu, jedes 2xx als Abschluss zu interpretieren, es sei denn, die Antwort besagt ausdrücklich etwas anderes.

Schleifen sind teuer. Wenn ein Agent innerhalb seiner Denk-Schleife abfragt, kostet jede Prüfung einen Modell-Turn plus die Tokens des vorherigen Gesprächs. Alle zwei Sekunden eine Abfrage für einen vierminütigen Job bedeutet 120 Turns, und der Durchlauf erschöpft entweder den Kontext oder das Budget. Unser Beitrag zum Heraushalten von Tool-Antworten aus dem Kontextfenster erklärt, warum sich das schneller summiert, als man erwartet.

Agenten verlieren die Übersicht über Aufträge. Ein Tool, das eine Arbeit beginnt und eine Auftrags-ID zurückgibt, hat einen Zustand erzeugt, den der Agent weiterführen muss. Wenn die ID mitten in einem langen Gespräch landet, kann sie komprimiert werden, und der Agent vergisst, dass er einen laufenden Auftrag hat.

Gestalten Sie die Antwort so, dass das Modell sie nicht falsch interpretieren kann

Die effektivste Lösung ist die Formulierung, nicht die Architektur. Unabhängig von Ihrem Statuscode sollte der Body klar sagen, was passiert ist und was als Nächstes zu tun ist.

{
  "status": "processing",
  "job_id": "job_7f21c",
  "message": "The transcode has STARTED and is NOT complete. Do not report success. Check status with getJobStatus(job_id) after at least 30 seconds.",
  "poll_after_seconds": 30,
  "estimated_duration_seconds": 240,
  "status_url": "/v1/jobs/job_7f21c"
}

Das klingt für einen menschlichen API-Konsumenten übertrieben. Es richtet sich an ein Modell, und Modelle folgen expliziten Anweisungen in einem Antwort-Body weitaus zuverlässiger, als sie die Bedeutung aus einem Statuscode ableiten. Drei Details leisten die Arbeit: das Wort „nicht abgeschlossen“, das benannte nächste Tool und eine Mindestwartezeit.

Googles AIP-151 zu langlaufenden Operationen beschreibt eine saubere Ressourcenform dafür, mit einem einzigen Operation-Objekt, das die Felder done, error und response enthält. Das Kopieren dieser Struktur bietet Ihnen eine konsistente Oberfläche über jeden langsamen Endpunkt hinweg, was wichtig ist, da ein Agent, der ein Abfragemuster lernt, dann alle davon verarbeiten kann.

Halten Sie die Statusantwort ebenso direkt:

{
  "job_id": "job_7f21c",
  "status": "processing",
  "done": false,
  "progress_percent": 45,
  "elapsed_seconds": 108,
  "poll_after_seconds": 45,
  "message": "Still processing. Do not proceed to the next step."
}

Und bei Abschluss geben Sie das Ergebnis inline zurück, wenn es klein ist, damit der Agent keinen dritten Aufruf benötigt:

{
  "job_id": "job_7f21c",
  "status": "succeeded",
  "done": true,
  "result": { "output_url": "https://cdn.example.com/out/7f21c.mp4", "duration_seconds": 372 }
}

Abfragen außerhalb des Modells, nicht innerhalb

Die wichtigste Implementierungsentscheidung: Platzieren Sie das Warten in Ihrem Tool-Wrapper, nicht in der Denk-Schleife des Agenten.

import time

def start_and_await_transcode(client, source_url, max_wait=600):
    job = client.post("/v1/transcode", json={"source_url": source_url}).json()
    job_id = job["job_id"]
    delay = job.get("poll_after_seconds", 5)
    waited = 0

    while waited < max_wait:
        time.sleep(delay)
        waited += delay
        status = client.get(f"/v1/jobs/{job_id}").json()

        if status.get("done"):
            if status["status"] == "succeeded":
                return {"status": "succeeded", "result": status["result"]}
            return {"status": "failed", "error": status.get("error")}

        delay = min(int(delay * 1.5), 60)

    return {
        "status": "timed_out",
        "job_id": job_id,
        "message": f"Still running after {max_wait}s. Job {job_id} continues in the background.",
    }

Aus Sicht des Modells ist dies ein Tool-Aufruf, der eine Weile dauert und eine endgültige Antwort zurückgibt. Keine Abfrageschleife im Kontext, keine vergessenen Auftrags-IDs, keine 120 Züge. Der Backoff hält die Anzahl der Anfragen vernünftig, und die Obergrenze verhindert, dass ein festgefahrener Job den Durchlauf ewig blockiert. Amazons Artikel über Timeouts, Wiederholungsversuche und Backoff mit Jitter ist die Referenz, die man lesen sollte, bevor man diese Zahlen anpasst.

Zwei Regeln machen dies sicher. Begrenzen Sie die Wartezeit immer, und geben Sie bei einem Timeout immer die Auftrags-ID zurück, damit der Agent oder ein Mensch später nachsehen kann. Geben Sie niemals ein mehrdeutiges Ergebnis zurück: succeeded, failed und timed_out sind drei verschiedene Ergebnisse, und das Modell sollte drei verschiedene Wörter sehen.

Für Jobs, die in Stunden statt in Minuten gemessen werden, macht das In-Wrapper-Polling keinen Sinn mehr. Dann ist die richtige Form zwei Tools, eines zum Starten und eines zum Überprüfen, plus eine dauerhafte Aufzeichnung der laufenden Jobs außerhalb des Gesprächs, damit nichts durch Komprimierung verloren geht. Speichern Sie job_id, die Aufgabe, zu der sie gehört, und die Startzeit, und lassen Sie den Agenten diese Liste am Anfang jedes Durchlaufs lesen.

Wann Webhooks die bessere Antwort sind

Polling ist einfach und funktioniert überall. Callbacks sind effizienter und mit mehr Aufwand verbunden. Der Kompromiss wird in unserem Vergleich Webhooks vs. Polling gut behandelt, und die agentspezifische Version ist enger gefasst.

Nutzen Sie Polling, wenn der Job Sekunden bis Minuten dauert, wenn der Agent auf das Ergebnis wartet, um fortzufahren, oder wenn Sie keinen öffentlichen Endpunkt hosten können. Die meisten Agenten-Workloads fallen hierher.

Verwenden Sie Webhooks, wenn Jobs Stunden dauern, wenn der Agent Arbeit auslöst und weitermacht, oder wenn viele Jobs gleichzeitig laufen und das Abfragen jedes einzelnen verschwenderisch ist. Die Kosten sind real: Sie benötigen einen öffentlichen Empfänger, eine Signaturprüfung, eine Fehlerbehandlung bei Wiederholungsversuchen und eine Möglichkeit, den Agenten zu wecken, wenn der Callback eintrifft. Unsere Leitfäden zum Entwerfen zuverlässiger Webhooks und zur Webhook-Signaturprüfung decken diese Grundlagen ab.

Eine mittlere Option ist wissenswert. Das Streaming des Jobfortschritts über Server-Sent Events bietet Ihnen Push-Semantik ohne einen öffentlichen Endpunkt, da der Client die Verbindung hält. Es eignet sich für interaktive Agenten, bei denen ein Mensch zuschaut, und unser Leitfaden zum Streaming von API-Antworten mit SSE behandelt die Implementierung.

Für welche Option Sie sich auch entscheiden, der Abschluss-Pfad muss idempotent sein. Webhooks versuchen es erneut, Abfragen überschneiden sich, und ein Agent, der zweimal „erfolgreich“ sieht, sollte den nachgelagerten Schritt nicht zweimal starten. Unser Beitrag zu Idempotenz für KI-Agenten behandelt die Schlüssel, die dies sicherstellen.

Testen Sie den langsamen Pfad, nicht nur den schnellen

Asynchrone Fehler verstecken sich, weil Testumgebungen schnell sind. Ein Job, der in der Produktion vier Minuten dauert, ist gegen einen lokalen Stub in 200 Millisekunden abgeschlossen, sodass der Agent nie den Zustand erlebt, dem er tatsächlich begegnen wird.

Vier Szenarien sollten bewusst aufgebaut werden.

Speichern Sie alle vier als Szenarien, damit sie in CI ausgeführt werden. Sie kosten nichts bei der erneuten Ausführung und fangen Regressionen ab, bei denen jemand ein Timeout verkürzt oder einen Fehler verschluckt. Der umfassendere Ansatz findet sich in unserem Leitfaden zum API-Vertragstesting.

Drei Jobs, die das Problem aufzeigen

Teilergebnissen eine Form geben

Lange Jobs enden oft irgendwo zwischen Erfolg und Misserfolg, und ein Zwei-Zustands-Modell zwingt Sie, darüber zu lügen. Machen Sie den dritten Zustand explizit:

{
  "job_id": "job_a11f",
  "status": "completed_with_errors",
  "done": true,
  "summary": { "processed": 20000, "succeeded": 19860, "failed": 140 },
  "errors_url": "/v1/jobs/job_a11f/errors?limit=50",
  "message": "Import finished. 140 rows failed and were not written. Review errors before reporting success."
}

Zwei Dinge sind in dieser Payload wichtig. Die Zählungen sind inline, sodass der Agent ohne einen weiteren Aufruf entscheiden kann. Die fehlerhaften Zeilen sind hinter einer URL mit einem Limit, sodass 140 Fehlerobjekte nicht unaufgefordert im Kontext landen.

Jemand muss den Job sehen, der ins Stocken geraten ist

Der Timeout-Pfad endet mit einer Job-ID und einer Meldung, dass die Arbeit noch läuft. Das ist der korrekte Rückgabewert, und er ist nur nützlich, wenn er eine Person erreicht.

Wenn der Agent Ihr eigener Dienst ist, leiten Sie ihn in die Warteschlange, die Ihr Team bereits überwacht. Wenn der Agent eine Code-Laufzeitumgebung ist, die zugewiesene Aufgaben abarbeitet, hat die Plattform, auf der er läuft, normalerweise einen Ort, an dem dies landen kann. In Sharkly bleibt ein blockiert endender Lauf mit seinem Ausführungszustand und Ergebnis an seiner Aufgabe, und der Posteingang trennt Elemente, die eine menschliche Antwort oder Überprüfung benötigen, von normalen Updates. Es geht nicht um das spezifische Tool. Es geht darum, dass „noch läuft, später prüfen“ einen Verantwortlichen braucht, sonst wird es zu „niemand hat nachgesehen“.

Eine kurze Checkliste

Wenn die Antwortformulierung und der Wrapper stimmen, hören langlaufende Operationen auf, ein Sonderfall für den Agenten zu sein. Er ruft ein Tool auf, wartet und erhält eine Antwort, was der Vertrag ist, den er am besten handhabt. Laden Sie Apidog herunter, um die Mocks für langsame Jobs zusammen mit den Tests zu erstellen.

Häufig gestellte Fragen

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen