KI-Agenten lesen jetzt deine API-Fehler

Teilen

Im März hat Mintlify einen Monat Verkehr auf den Doku-Websites zusammengezählt, die es hostet. Das waren rund 790 Millionen Requests, und 45,3 % davon kamen von KI-Coding-Agenten. Browser kamen auf 45,8 %. Claude Code allein schickte ein Viertel von allem (die Zahlen von Mintlify).

Das ist Verkehr auf Dokumentation, nicht auf APIs. Aber die Agenten, die die Doku lesen, sind dieselben, die danach den Request schreiben, ausführen und lesen, was zurückkommt. In der State-of-the-API-Umfrage 2025 von Postman sagten 24 % der Entwickler, dass sie APIs bereits mit Blick auf Agenten entwerfen. Als das erschien, klang es verfrüht. Jetzt nicht mehr.

Das meiste, was wir hier bauen, dreht sich ums Scheitern: Endpunkte, die 500er zurückgeben, hängen oder mitten in einer Antwort aufhören. Unsere Frage war also eng gefasst. Wenn ein Agent von deiner API einen Fehler bekommt, hat er genug, um als Nächstes das Richtige zu tun?

Ein Agent nimmt deine Fehlermeldung beim Wort

Wer als Entwickler {"error":"E4021"} zurückbekommt, sucht nach dem Code, findet nichts und fragt eine Kollegin. Ein Agent kann niemanden fragen. Er arbeitet mit dem Body, den du geschickt hast, und wenn der nichts Brauchbares sagt, rät er: Er wiederholt denselben Request oder ändert ein Feld, das in Ordnung war.

Das sagt unser Produkt-Endpunkt, wenn die ID nicht existiert:

Terminal
$ curl -i https://api.testingapis.com/api/Products/99999
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8

{"status":404,"error":"Not Found","message":"Product with ID 99999 does not exist."}

Ein langweiliger Satz, und das ist in Ordnung. Er nennt Ressource und ID, wer ihn liest, Mensch oder Programm, weiß also, dass die ID das Problem ist und erneutes Senden nicht hilft.

Wenn du eine Standardform für Fehler willst, definiert RFC 9457 (Problem Details for HTTP APIs) type, title, status, detail und instance, ausgeliefert als application/problem+json. Sie hat 2023 RFC 7807 abgelöst. Wir glauben nicht, dass das genaue Format viel ausmacht. Wichtig ist, dass irgendwo ein klarer Satz drinsteht.

Sag, wie lange gewartet werden soll

Agenten versuchen es erneut. Sagt dein 429 oder 503 nicht, wie lange man warten soll, muss der Client eine Zahl wählen, und ein Agent, der eine Aufgabe in einer Schleife abarbeitet, wählt immer wieder. Retry-After gehört seit Jahrzehnten zu HTTP und löst das mit einem Header:

Terminal
$ curl -i https://api.testingapis.com/api/status/429
HTTP/1.1 429 Too Many Requests
content-type: application/json; charset=utf-8
retry-after: 5

{"status":429,"statusText":"Too Many Requests","category":"client-error","message":"This is a 429 response. Use /api/status/{code} to request any status."}
GET/api/status/429

Die IETF arbeitet außerdem an den Headern RateLimit und RateLimit-Policy, mit denen ein Client sein Kontingent sieht, bevor es aufgebraucht ist, statt danach. Entwurf 11 erschien im Mai. Die Syntax sieht so aus:

Header
RateLimit-Policy: "default";q=100;w=60
RateLimit: "default";r=50;t=30

Das liest sich als "100 Requests pro 60 Sekunden, 50 übrig, das Fenster setzt sich in 30 zurück". Es ist noch ein Entwurf, also würden wir die X-RateLimit-*-Header, die deine Clients schon lesen, nicht streichen. Beide zu senden kostet sehr wenig.

Retries erzeugen Duplikate

Ein GET zu wiederholen ist harmlos. Ein POST zu wiederholen nicht, wenn der erste Versuch den Server erreicht hat und nur die Antwort verloren ging. Am Ende hast du zwei Bestellungen. Ein Mensch bemerkt die doppelte Abbuchung meist. Ein Agent sieht, dass sein zweiter Versuch geklappt hat, und macht weiter.

Die übliche Lösung ist ein Idempotenzschlüssel. Der Client sendet mit dem Schreibzugriff einen eindeutigen Header Idempotency-Key, und kommt derselbe Schlüssel noch einmal an, gibt der Server das erste Ergebnis zurück, statt die Arbeit doppelt zu machen. Stripe arbeitet seit Jahren so, und es gibt einen IETF-Entwurf für den Header, auch wenn er noch keine RFC ist. Nimmt deine API Zahlungen an oder legt etwas an, das sich nur mühsam aufräumen lässt, lohnt es sich, ihn einzubauen, bevor Agenten sie aufrufen.

MCP-Server werden zu gewöhnlichen HTTP-APIs

Viele Agenten werden deine REST-API nicht direkt aufrufen. Sie gehen über einen MCP-Server, der sie umhüllt. Die am 28. Juli veröffentlichte MCP-Spezifikation hat den Session-Handshake und den Header Mcp-Session-Id entfernt. Jeder Request trägt jetzt seine eigene Protokollversion und Client-Angaben, und Methoden- und Tool-Namen reisen in HTTP-Headern, ein Gateway kann Requests also routen und begrenzen, ohne den Body zu parsen.

Unterm Strich verhält sich ein MCP-Server jetzt weitgehend wie jeder andere zustandslose HTTP-Dienst. Er kann hinter einem einfachen Load Balancer stehen, und die Ratschläge oben gelten für ihn unverändert. Wenn ein Tool-Aufruf scheitert, braucht der Agent von deinem MCP-Server einen Grund und eine Wartezeit, genau wie von deiner API.

Ein schneller Check

Hier ist das Skript, das wir beim Schreiben laufen ließen. Es schickt vier Requests, die scheitern, und prüft bei jedem zwei Dinge: Gibt es einen Grund, den ein Programm lesen kann, und gibt es ein Retry-After?

check-errors.mjs
// For each failure: is there a reason a program can read, and a time to wait?
const BASE = "https://api.testingapis.com";

const cases = [
  ["missing product", "/api/Products/99999"],
  ["rate limited", "/api/status/429"],
  ["server down", "/api/Products/1?error=503"],
  ["bad request", "/api/status/400"],
];

for (const [name, path] of cases) {
  const res = await fetch(BASE + path);
  const body = await res.json().catch(() => ({}));
  const reason = body.message ?? body.detail ?? body.title;
  const wait = res.headers.get("retry-after");
  console.log(
    name.padEnd(16),
    res.status,
    reason ? "reason: yes" : "reason: NO ",
    wait ? `retry-after: ${wait}s` : "retry-after: -",
  );
}
Ausgabe (Node 24, 9. Oktober 2026)
missing product  404 reason: yes retry-after: -
rate limited     429 reason: yes retry-after: 5s
server down      503 reason: yes retry-after: -
bad request      400 reason: yes retry-after: -

Jede Antwort hat einen Grund, das ist gut. Aber sieh dir die dritte Zeile an. /api/status/503 sendet Retry-After: 5, und ?error=503 an einem echten Endpunkt sendet nichts. Ein dagegen getesteter Client würde nie lernen, wann er es erneut versuchen soll. Das steht auf unserer Liste.

Richte dasselbe Skript auf die Fehlerpfade deiner eigenen API. Wenn du deine API nicht auf Wunsch scheitern lassen kannst, zeigt der Leitfaden zu Fehlerantworten, wie du von unserer ein 500, ein 429, einen Timeout oder einen abgeschnittenen Body bekommst.

Nichts davon ist ein neuer Rat. Klare Fehlermeldungen und Retry-After waren gute Ideen, lange bevor jemand einen Agenten gebaut hat. Geändert hat sich, dass ein verwirrter Mensch dir irgendwann eine E-Mail schreibt und ein Agent es einfach noch einmal versucht.