7 Min. Lesezeit

API-Ergebnisse beschneiden: Agents von fehlerhaften Änderungen abhalten

Eine Beschneidung von API-Ergebnissen kann Agents zu unsicheren Folgeänderungen verleiten. Entwirf Tool-Antworten, die unvollständige Daten, Warnungen, Limits und den Gültigkeitsbereich offenlegen.

API-Ergebnisse beschneiden: Agents von fehlerhaften Änderungen abhalten

Agents brauchen kein bösartiges Tool, um eine schädliche Änderung vorzunehmen. Es reicht, wenn ein Tool stillschweigend nur einen Teil seiner Antwort zurückgibt. Gib einem Agent eine Suchantwort, die vollständig aussieht, und bitte ihn, alles zu entfernen, was die Suche nicht gefunden hat. Oft produziert er dann einen vollkommen logisch wirkenden Fehler auf Grundlage falscher Voraussetzungen.

Die Lösung ist kein längerer System-Prompt, der den Agent auffordert, vorsichtig zu sein. Das Tool muss in einer stabilen, maschinenlesbaren Form angeben, ob es die angeforderte Arbeit abgeschlossen hat, was ausgelassen wurde, warum es ausgelassen wurde und wie der Aufrufer fortfahren kann. Kann das Tool diese Aussage nicht machen, darf der Agent das Fehlen eines Ergebnisses nicht als Erlaubnis für eine weitreichende Änderung verstehen.

Teildaten und leere Daten sind unterschiedliche Aussagen

Ein leeres Ergebnis bedeutet, dass das Tool im tatsächlich geprüften Bereich keine passenden Elemente gefunden hat. Ein vollständig leeres Ergebnis bedeutet, dass das Tool den gesamten angeforderten Bereich geprüft und nichts gefunden hat. Das sind unterschiedliche Aussagen, doch die meisten API-Verträge führen sie beide auf dasselbe [] zurück.

Diese Gleichsetzung verursacht eine ganz bestimmte falsche Schlussfolgerung:

  1. Der Agent fragt nach allen Servicekonten ohne aktuellen Besitzer.
  2. Die API gibt ein leeres Array zurück, nachdem sie nur die erste Seite geprüft, ein Ergebnislimit erreicht oder Datensätze ausgelassen hat, die das Token nicht lesen darf.
  3. Der Agent schließt daraus, dass jedes Konto einen Besitzer hat.
  4. Er ändert auf dieser Grundlage eine zugehörige Kontrolle, einen Bericht oder einen Bereinigungsjob.

Der Agent musste Englisch nicht missverstehen. Das Tool gab ihm eine Antwort, deren Form mehr implizierte, als der Server wusste.

Ein Tool sollte mindestens vier Zustände unterscheiden. Eine vollständige Abfrage kann Elemente zurückgeben. Eine vollständige Abfrage kann keine Elemente zurückgeben. Eine unvollständige Abfrage kann einige Elemente zurückgeben. Eine unvollständige Abfrage kann keine Elemente zurückgeben. Nur den dritten Zustand zu beachten, übersieht den gefährlichsten Fall: eine leere Antwort, die einen Agent davon überzeugt, dass ein Problem nicht existiert.

Berechtigungen verschärfen das Problem. Viele Dienste verbergen unzugängliche Objekte absichtlich, indem sie eine leere oder gefilterte Sammlung statt eines Berechtigungsfehlers zurückgeben. Für eine Benutzeroberfläche kann dieses Verhalten sinnvoll sein. Für eine autonome Bereinigungsaufgabe ist es kein akzeptabler Beleg, solange die API nicht genau angibt, welche Sichtbarkeit der Aufrufer hatte.

Verwende keinen Fließtext wie Some results may be missing als Vertrag. Er bietet einem Agent keinen zuverlässigen Verzweigungspunkt und einem Entwickler keine testbare Bedingung. Ein Feld namens complete mit einem booleschen Wert wirkt langweilig. Genau darum geht es.

Eine erfolgreiche HTTP-Antwort kann trotzdem unvollständig sein

HTTP-Statuscodes beschreiben den Austausch zwischen Client und Server. Für sich genommen beweisen sie nicht, dass eine Suche, ein Inventar oder ein Export den angeforderten Bereich vollständig abgedeckt hat.

RFC 9110 definiert die Bedeutung von HTTP-Statuscodes. Ein 200 OK besagt, dass die Anfrage gemäß der Semantik der Methode erfolgreich war. Es besagt nicht, dass eine Suche jede Seite, jede Partition, jeden Berechtigungsbereich oder jeden Datensatz vor Ablauf einer Frist abgedeckt hat. Teams lesen oft mehr in 200 hinein, als das Protokoll verspricht.

Betrachte diese Antwort:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "items": [],
  "next_cursor": null
}

Sie wirkt endgültig. Doch next_cursor: null bedeutet nur, dass dieser bestimmte Pagination-Mechanismus keine weitere Seite kennt. Über ein Backend-Ergebnislimit, einen abgelaufenen Suchjob, eine ausgefallene Quelle, aus Richtlinien ausgeschlossene Datensätze oder ein API, das den Rückblickzeitraum stillschweigend begrenzt, sagt es nichts aus.

Eine Antwort wird zu einem verwertbaren Beleg, wenn der Vertrag festlegt, worauf sich complete bezieht. Bei einer Kontosuche kann das bedeuten: alle Konten, die für den aufrufenden Principal in einem bestimmten Snapshot sichtbar sind. Bei einer Codesuche kann es alle indexierten Dateien in einer bestimmten Revision bedeuten, wobei ignorierte Dateien und nicht indexierte generierte Ausgaben ausdrücklich ausgeschlossen werden. Der Bereich muss so konkret sein, dass ein Aufrufer entscheiden kann, ob er zur geplanten Aktion passt.

Löse das nicht, indem du für jede unvollständige Antwort 500 zurückgibst. Teilergebnisse können nützlich sein. Ein Dashboard kann sie anzeigen. Ein Agent kann sie zusammenfassen. Ein Mensch kann sie prüfen. Der Fehler besteht darin, ein Teilergebnis als verbindliche Antwort auf eine Frage darzustellen, die Vollständigkeit erfordert.

Verwende einen Fehler, wenn die angeforderte Operation eine atomare oder vollständige Antwort verspricht und dieses Versprechen nicht erfüllen kann. Verwende eine erfolgreiche Antwort mit ausdrücklich gekennzeichneter Unvollständigkeit, wenn die Teildaten selbst sinnvoll nutzbar sind. Der Client braucht eine deterministische Unterscheidung, keine Diskussion darüber, ob sich 200 optimistisch anfühlt.

Vollständigkeitsmetadaten gehören neben jedes Ergebnis

Ein Ergebnisvertrag sollte die Vollständigkeit als strukturierte Daten offenlegen, unabhängig davon, ob die Elementliste vollständig, kurz oder leer ist. Lass Aufrufer sie nicht aus der Anzahl der Elemente, einem fehlenden Header oder einem Satz im Feld message ableiten.

Diese Form eignet sich für eine Suche in einer Sammlung:

{
  "items": [
    {"id": "svc-184", "owner": null}
  ],
  "complete": false,
  "truncated": true,
  "incomplete_reasons": [
    {
      "code": "RESULT_LIMIT_REACHED",
      "message": "The query stopped after the configured result limit.",
      "limit": 1000
    }
  ],
  "next_cursor": "eyJvZmZzZXQiOjEwMDB9",
  "scope": {
    "resource": "service_accounts",
    "visibility": "resources readable by this credential",
    "snapshot": "2025-03-08T14:20:11Z"
  },
  "warnings": []
}

Die genauen Feldnamen sind weniger wichtig als ihre Bedeutung und einheitliche Verwendung. complete ist das Entscheidungsfeld. truncated beschreibt einen wichtigen Weg zur Unvollständigkeit, darf aber nicht zum Sammelbecken werden. Ein Berechtigungsfilter ist keine Beschneidung. Eine föderierte Suche mit Zeitüberschreitung ist keine Pagination. Wenn du ein einziges Flag überlädst, verlieren Aufrufer den Grund, den sie für eine sichere Wiederaufnahme brauchen.

Halte warnings getrennt von incomplete_reasons. Eine Warnung kann mitteilen, dass ein veraltetes Feld vorkam, ein Wert normalisiert wurde oder eine angeforderte Sortierung auf einen Standardwert zurückfiel. Ein Grund für Unvollständigkeit besagt, dass die Antwort keine Aussagen über den nicht zurückgegebenen Teil des angeforderten Bereichs erlaubt. Diese Unterscheidung entscheidet darüber, ob ein Agent fortfahren kann.

Vermeide außerdem ein einzelnes has_more-Flag als einziges Signal. Es beantwortet meist nur eine enge Pagination-Frage. Ein Agent, der has_more: false sieht, kann vernünftigerweise annehmen, dass die Sammlung zu Ende ist, selbst wenn ein serverseitiges Limit oder ein unzugänglicher Shard einen vollständigen Scan verhindert hat. has_more kann bestehen bleiben, darf aber nicht die gesamte Verantwortung für die Vollständigkeit tragen.

Für das Lesen einer einzelnen Ressource gilt dieselbe Disziplin. Eine Antwort mit ausgelassenen Feldern sollte angeben, ob der Server sie nicht zurückgegeben hat, weil der Aufrufer sie nicht angefordert hat, keinen Zugriff besitzt, die Datenquelle ausgefallen ist oder der Wert tatsächlich fehlt. Das Weglassen in JSON ist kompakt, aber mehrdeutig.

Pagination braucht eine stabile Grenze, keine größere Seitengröße

Pagination ist für Agents nur dann sicher, wenn die API die Fortsetzung zuverlässig macht und erklärt, welche Änderungen sie ungültig machen können. Das Erhöhen des Seitenlimits verschiebt den Fehler nur. Es beseitigt ihn nicht.

Offset-Pagination führt besonders leicht zu falschen Schlussfolgerungen. Ein Agent liest die Datensätze 0 bis 99, löscht oder erstellt ein Objekt und liest anschließend 100 bis 199. Wenn sich die zugrunde liegende Reihenfolge geändert hat, kann er einen Datensatz überspringen oder einen zweimal verarbeiten. Für einen informativen Bericht mag das hinnehmbar sein. Für einen Änderungsplan kann es verheerend sein.

Cursor-Pagination ist meist besser, weil der Server eine Position in einer geordneten Ergebnismenge codieren kann. Auch sie braucht einen Vertrag. Lege fest, ob der Cursor einen Snapshot einfriert, wie lange er gültig bleibt und ob eine Änderung von Filtern, Sortierung oder Autorisierung ihn ungültig macht. Läuft ein Cursor ab, darfst du den Scan nicht unsichtbar neu starten und eine zusammengeführte Antwort zurückgeben. Gib einen ausdrücklichen unvollständigen Zustand zurück oder zwinge den Client zu einem Neustart.

Eine brauchbare Antwort für eine Sammlung gibt dem Aufrufer genug Informationen, um bewusst fortzufahren:

{
  "items": ["item-001", "item-002"],
  "complete": false,
  "next_cursor": "cD0y",
  "page": {
    "returned": 2,
    "requested_size": 2,
    "ordering": "id ascending",
    "snapshot": "search-7f9c"
  },
  "incomplete_reasons": [
    {"code": "MORE_PAGES_AVAILABLE"}
  ]
}

Der Aufrufer sollte fortfahren, bis er complete: true erhält, nicht bloß bis er eine kurze Seite bekommt. Kurze Seiten können viele Ursachen haben. Manche APIs geben sie zurück, weil eine Partition vorübergehend wenige Treffer enthält, ein interner Worker vorzeitig beendet wurde oder der Dienst die Antwortgröße nach Bytes statt nach Objektanzahl begrenzt.

Bitte das Sprachmodell nicht, diese Schleife im Fließtext zu behalten. Implementiere das Pagination-Verhalten im Tool. Ein übergeordnetes Tool search_all kann Seiten sammeln, den Snapshot bewahren, seine eigene Arbeit begrenzen und melden, ob es einen Endzustand erreicht hat. Wenn es sein eigenes Limit erreicht, muss es complete: false zurückgeben und angeben, dass das clientseitige Limit die Ursache war.

Dieser letzte Fall wird oft übersehen. Entwickler ergänzen die Metadaten korrekt in der API und bauen anschließend einen Agent-Wrapper mit max_pages=10, der die Tatsache verwirft, dass er nach zehn Seiten aufgehört hat. Der Wrapper ist damit zur Quelle der Unvollständigkeit geworden. Der äußerste Tool-Vertrag muss die Offenlegung übernehmen.

Zeitlimits, ausgefallene Shards und Berechtigungen brauchen eigene Gründe

Neue Läufe zuerst nachfragen lassen
Nutze eine sitzungsbezogene Autorisierung, damit ein neu gestarteter Agent-Prozess nicht ohne menschliche Entscheidung handeln kann.

Eine Suche kann ihre HTTP-Anfrage abschließen, obwohl Teile ihrer Arbeit nicht fertig wurden. Verteilte Dienste leiten eine Abfrage oft an mehrere Indizes oder Mandanten weiter. Wenn eine Quelle eine Zeitüberschreitung verursacht und der Dienst Treffer von den anderen Quellen zurückgibt, kann das Ergebnis nützlich, aber unvollständig sein.

Gib die Ursache in einem Code an, auf den ein Programm reagieren kann. Menschlicher Text gehört daneben, nicht an seine Stelle. Halte Codes überschaubar, stabil und dokumentiert. Zum Beispiel:

  • MORE_PAGES_AVAILABLE bedeutet, dass der Aufrufer die nächste Seite anfordern kann.
  • RESULT_LIMIT_REACHED bedeutet, dass der Dienst ein Limit erreicht hat, bevor alle Treffer gefunden waren.
  • TIME_BUDGET_EXCEEDED bedeutet, dass die Suche beendet wurde, bevor die geplante Arbeit vollständig abgeschlossen war.
  • SOURCE_UNAVAILABLE bedeutet, dass eine bestimmte Quelle nicht geantwortet hat.
  • VISIBILITY_RESTRICTED bedeutet, dass die Autorisierung des Aufrufers einen Teil des angeforderten Bereichs ausgeschlossen hat.

Verberge VISIBILITY_RESTRICTED nicht hinter einer allgemeinen Erfolgsmeldung. Sicherheitsteams bevorzugen manchmal nicht unterscheidbare Antworten, weil sie nicht verraten wollen, welches Objekt existiert. Diese Sorge ist berechtigt. Die API kann melden, dass Sichtbarkeitsgrenzen ein vollständiges Inventar verhindern, ohne verborgene Objekte zu benennen. Sie darf den Aufrufer aber nicht ein Teilinventar mit einem vollständigen verwechseln lassen.

Dasselbe gilt für Ratenlimits und Kontingente. Wenn eine API den ersten Teil einer Anfrage liest, bevor ein Budget erschöpft ist, muss sie sowohl die zurückgegebenen Daten als auch den Budgetzustand melden. Ein erneuter Versuch kann später erfolgreich sein, aber es handelt sich um einen neuen Versuch. Der Agent darf zwei Versuche nicht zu einem Beleg für Vollständigkeit verbinden, solange die API keinen stabilen Snapshot liefert oder die Aufgabe eine Abweichung toleriert.

Eine Frist sollte sowohl Eingabe als auch Ausgabe sein. Wenn ein Agent ein großes Inventar anfordert, sollte er ein Zeitbudget setzen und die erledigte Arbeitsmenge zurückerhalten können. So wird der Zielkonflikt sichtbar. Eine zehnsekündige Erkundungssuche kann vor einer menschlichen Prüfung genügen. Als Beleg dafür, jede Ressource zu löschen, die die Suche nicht gesehen hat, ist sie schwach.

Fehlen ist ein schwacher Beleg für destruktive Änderungen

Ein Agent kann Teildaten sicher verwenden, um einen Bericht zu entwerfen, Kandidaten zu identifizieren oder einen Menschen zur Prüfung einer kleinen Zielmenge aufzufordern. Er sollte Teildaten nicht dazu verwenden, daraus abzuleiten, dass eine Ressource ungenutzt, ohne Besitzer, doppelt vorhanden oder sicher zu entfernen ist.

Der Unterschied liegt in der Richtung der Aussage. Einen Datensatz mit owner: null zu finden, ist ein positiver Beleg für diesen Datensatz, vorbehaltlich der Aktualität des Feldes. Keine Datensätze ohne Besitzer zu finden, ist eine universelle Aussage über den Suchbereich. Universelle Aussagen erfordern eine vollständige Abdeckung eines definierten Bereichs.

Dieser Fehler tritt oft als Effizienzverbesserung verkleidet auf. Ein Team gibt einem Agent ein Tool namens list_inactive_projects und erlaubt ihm, jedes zurückgegebene Projekt zu archivieren oder, noch schlimmer, jedes Projekt zu archivieren, das in einer zweiten Liste fehlt. Das Tool hat ein maximales Ergebnislimit. Monate später überschreitet eine große Organisation dieses Limit. Niemand ändert den Agent-Prompt, doch die Bedeutung des Agents wechselt von «auf dem Inventar arbeiten» zu «auf einem beliebigen Präfix des Inventars arbeiten».

Baue Aktions-Tools so, dass sie Belege verlangen und keine Erzählung akzeptieren. Eine Archivierungsoperation kann die IDs aus einem vorherigen vollständigen Inventar sowie ein Snapshot-Token verlangen, das die Auswahl an den Lesevorgang bindet. War das Inventar unvollständig, lehnt das Tool die Operation ab. So liegt die Sicherheitsprüfung an einer Stelle, an der ein Modell sie nicht mit einer beiläufigen Erklärung umgehen kann.

Bei Aktionen, die keine Snapshot-Tokens verwenden können, solltest du einen ausdrücklichen Bereich verlangen und jedes Ziel zur Ausführungszeit erneut prüfen. Das beweist nicht, dass die ursprüngliche Suche vollständig war, verhindert aber, dass eine veraltete Liste unabhängige Änderungen autorisiert. Halte die Aktion so eng, dass ein Prüfer die Zielmenge verstehen kann.

Die verbreitete Alternative lautet: «Lösche niemals etwas, solange du nicht sicher bist.» Das klingt vernünftig und scheitert in der Praxis. Sicherheit ist ein Wort im Prompt. complete: false ist eine Bedingung, die ein Tool erzwingen kann.

Tool-Schemas sollten Agents zwingen, Unsicherheit zu beachten

Ein Aktions-Gateway einrichten
Verbinde Claude Code oder einen anderen MCP-fähigen Agent über den mitgelieferten sp mcp Shim.

Ein MCP-Tool oder jeder andere Agent-Wrapper sollte ein typisiertes Antwortobjekt statt eines ansprechenden Fließtextblocks zurückgeben. Das Modell kann Fließtext lesen, aber die umgebende Software braucht Felder, die sie validieren, protokollieren, als Voraussetzung prüfen und testen kann.

Ein praktischer Antworttyp könnte so aussehen:

{
  "status": "partial",
  "data": {
    "repositories": [
      {"id": "repo-a", "default_branch": "main"}
    ]
  },
  "completeness": {
    "complete": false,
    "reasons": ["TIME_BUDGET_EXCEEDED"],
    "continuation": {
      "kind": "retry_with_deadline",
      "minimum_seconds": 30
    }
  },
  "warnings": [
    {
      "code": "STALE_INDEX",
      "message": "Search index may lag the source repository."
    }
  ]
}

Verwende für diese Antwort nicht status: "success". Das ermutigt einfache Clients, die Metadaten zu verwerfen. partial teilt dem Aufrufer mit, dass er brauchbare Daten mit einer Einschränkung erhalten hat. Muss dein Protokoll einen einzigen Erfolgsstatus verwenden, mache complete verpflichtend und verlange von Clients, die Aktionen ausführen können, dass sie das Feld vor jeder Änderung prüfen.

Das Fortsetzungsfeld sollte einen realen Wiederherstellungsweg beschreiben. next_cursor passt zu einer weiteren Seite. retry_after passt zu einem Ratenlimit. narrow_query kann zu einem serverseitigen Limit passen. Biete keine Fortsetzung an, die lediglich dieselbe Abfrage wiederholt und darauf hofft, dass sich die Welt anders verhält.

Agent-Anweisungen sollten eine kleine, strenge Regelmenge festlegen:

  • Der Agent darf eine leere Sammlung nur dann als Beleg für das Fehlen von etwas anführen, wenn complete den Wert true hat.
  • Der Agent darf eine unvollständige Antwort verwenden, um eine begrenzte, schreibgeschützte Untersuchung vorzuschlagen.
  • Der Agent muss incomplete_reasons offenlegen, bevor er die Genehmigung für eine Aktion anfordert, die auf dem Ergebnis beruht.
  • Der Agent darf kein fehlendes Fortsetzungstoken erfinden und nicht behaupten, eine Wiederholung sei erfolgreich gewesen, wenn er deren Ergebnis nicht erhalten hat.

Diese Regeln sind kurz, weil die Daten die Details tragen. Ein Prompt kann keine Informationen zurückholen, die ein Tool nicht gemeldet hat.

Warnungen brauchen Zuständigkeit und einen Ablaufweg

Warnungen werden zum Hintergrundrauschen, wenn jede Antwort eine vage Mahnung enthält. Halte sie spezifisch, zuordenbar und handlungsorientiert. Eine Warnung, die die nächste Entscheidung des Aufrufers nie verändert, sollte meist Dokumentation werden oder verschwinden.

STALE_INDEX sollte zum Beispiel die indexierte Quelle und, wenn möglich, ihre beobachtete Revision oder Aktualisierungszeit nennen. Der Agent kann dann die maßgebliche Quelle prüfen, bevor er Code ändert. PARTIAL_FIELD_SET sollte sagen, welche Felder der Server ausgelassen hat und ob der Aufrufer sie anfordern kann. DEFAULT_SCOPE_APPLIED sollte den vom Server gewählten Bereich nennen, denn Standardwerte führen häufig zu versehentlich weitreichenden Aktionen.

Verwandle Warnungen nicht versehentlich in Blocker. Ein Aufrufer braucht eine klare Regel für den Schweregrad. Vollständigkeitsmetadaten bestimmen, ob das Ergebnis eine Aussage über den gesamten Bereich erlaubt. Warnungen betreffen Vertrauen, Aktualität oder Interpretation. Ein Tool kann complete: true zusammen mit einer Warnung zur Veraltung zurückgeben. Das Ergebnis kann trotzdem jedes Element in einem Index aufzählen und zugleich für eine Änderung ungeeignet sein, die den aktuellen Zustand erfordert.

Gib Warnungen stabile Codes und teste Verbraucher gegen diese Codes. Vermeide Tests, die nur eine freundliche Nachricht prüfen. Nachrichten ändern sich, wenn ein Autor die Formulierung verbessert. Die Entscheidungsregel sollte sich nicht ändern.

Entscheide außerdem, wer nach der Einführung einer Warnung für sie verantwortlich ist. Wenn ein Betriebsteam sechs Monate lang bei jedem Aufruf dieselbe Warnung sieht, wird es sie nicht mehr lesen. Behebe entweder die zugrunde liegende Bedingung, mache sie gegebenenfalls zu einem harten Fehler oder entferne sie, wenn sie keine Entscheidung beeinflusst. Dauerhafte gelbe Lichter bringen Menschen und Agents dazu, gelbe Lichter zu ignorieren.

Tests müssen die gefährliche leere Antwort abdecken

Folgeaufrufe mit Folgen absichern
Fordere für jede Nutzung einer vertraulichen API oder eines SSH-Schlüssels eine Ein-Klick- oder Touch-ID-Bestätigung an.

Die meisten Testsuiten decken eine normale Ergebnisseite und einen Serverfehler ab. Sie überspringen genau die Antwort, die die schlimmste Schlussfolgerung auslöst: items: [] zusammen mit einer Unvollständigkeit.

Schreibe Vertragstests für jeden Grundcode. Prüfe, dass die API die Metadaten bei gefüllten und leeren Listen zurückgibt, dass SDKs sie bewahren und dass der Agent-Wrapper sie nicht in Fließtext umwandelt. Eine Regression in jeder dieser Schichten kann eine ehrliche Serverantwort in ein irreführendes Tool-Ergebnis verwandeln.

Verwende solche Fälle in einer Testvorlage:

{
  "case": "empty first page with more pages",
  "response": {
    "items": [],
    "complete": false,
    "truncated": false,
    "incomplete_reasons": ["MORE_PAGES_AVAILABLE"],
    "next_cursor": "cursor-2"
  },
  "expected_agent_decision": "continue_search"
}

Teste anschließend eine Änderungsanfrage nach diesem Fixture. Die erwartete Entscheidung sollte refuse_or_request_review lauten, nicht perform_cleanup. Mach die Richtlinie im Testnamen sichtbar. Künftige Maintainer würden die Sicherung sonst als übervorsichtige Ausnahme behandeln und entfernen, damit eine Automatisierungsdemo reibungsloser läuft.

Teste Pagination auch während Änderungen. Füge Datensätze zwischen Seiten ein, lösche sie und ändere ihre Reihenfolge. Lass einen Cursor ablaufen. Lass einen Shard ausfallen, nachdem ein anderer Ergebnisse geliefert hat. Entziehe während eines Scans eine Berechtigung. Dein Tool sollte entweder einen dokumentierten Snapshot bewahren oder melden, dass es keine Vollständigkeit behaupten kann. Ein Test mit einer statischen Fake-Datenbank erkennt die Lügen aus der Produktion nicht.

Property-Tests helfen dabei. Erzeuge Sammlungen, die größer als jedes konfigurierte Limit sind, variiere Seitengrößen und prüfe eine Invariante: Ein Client darf eine Sammlung erst dann als vollständig markieren, wenn er jedes Element in seinem deklarierten Snapshot berücksichtigt hat. Dafür braucht es kein Sprachmodell. Das ist gewöhnliche Schnittstellenkorrektheit.

Menschliche Genehmigungen sollten die fehlenden Belege zeigen

Menschliche Kontrolle funktioniert nur, wenn die Genehmigung die Entscheidung zeigt, die eine Person treffen soll. «Agent-Aktion erlauben» ist keine Genehmigung. Es ist die Aufforderung, eine undurchsichtige Kette von Annahmen zu akzeptieren.

Wenn ein Tool unvollständige Daten meldet, zeige die geplante Aktion, den Zielbereich, den Grund für die unvollständigen Belege und die Möglichkeit zur Wiederherstellung. Eine brauchbare Aufforderung sagt, dass das Inventar nach der Rückgabe von 842 Ressourcen eine Zeitüberschreitung hatte, und fragt, ob es mit einer längeren Frist erneut versucht, die Aktion auf die zurückgegebenen IDs begrenzt oder die Änderung verworfen werden soll. So kann der Prüfer einen echten Zielkonflikt entscheiden.

Sallyport hält die Zugangsdaten außerhalb eines Agent-Prozesses, wenn es HTTP- und SSH-Aktionen ausführt. Seine Aktivitätsaufzeichnungen können die daraus entstehenden Aufrufe zeigen. Diese Abschirmung und die Nachvollziehbarkeit sind nützlich, wenn ein Prüfer eine schlechte Entscheidung rekonstruieren muss. Sie verwandeln eine mehrdeutige API-Antwort jedoch nicht in einen Beleg. Die Tool-Antwort muss ihren Vollständigkeitszustand weiterhin selbst tragen.

Vermeide Genehmigungsmüdigkeit, indem du Genehmigungen für folgenreiche Unklarheiten reservierst. Ein Tool sollte routinemäßige Fortsetzungen, etwa das Abrufen einer dokumentierten nächsten Seite, ohne wiederholte Unterbrechung eines Menschen erledigen. Es sollte an einer Richtliniengrenze stoppen: bei einem abgelaufenen Snapshot, eingeschränkter Sichtbarkeit, einer auf dem Fehlen von Ergebnissen beruhenden Aktion oder einer geplanten Änderung außerhalb der gesammelten Belege.

Die erste technische Aufgabe ist klein: Finde jeden API-Wrapper, der eine Liste, ein Aggregat oder ein Suchergebnis zurückgeben kann, und ergänze im äußersten Antwortobjekt einen ausdrücklichen Vollständigkeitszustand. Beginne mit leeren Ergebnissen und begrenzten Suchen. Dort erzeugen selbstsichere Agents die überzeugendsten falschen Antworten.

FAQ

Was ist ein unvollständiges API-Ergebnis?

Ein unvollständiges Ergebnis deckt nur einen Teil des angeforderten Bereichs ab, zum Beispiel eine Seite mit Datensätzen, ein Verzeichnis eines Repositorys, eine Suche mit Zeitüberschreitung oder eine gefilterte Abfrage. Es wird gefährlich, wenn das Tool diese Teilmenge in derselben Form wie eine vollständige Antwort präsentiert. Dann wertet der Agent das Fehlen als Beleg.

Bedeutet eine leere API-Antwort, dass keine passenden Datensätze existieren?

Nein. Eine leere Liste bedeutet nur, dass der Server für den tatsächlich durchsuchten Bereich keine Elemente zurückgegeben hat. Wenn Pagination, ein Zeitlimit, Berechtigungen oder ein ausgefallener Shard diesen Bereich eingeschränkt haben, muss das Tool dies gesondert mitteilen.

Sollte ein Agent handeln, wenn die Tool-Antwort unvollständig ist?

Die sicherste Voreinstellung ist, destruktive oder weitreichende Folgeaktionen zu stoppen, wenn die Vollständigkeit unbekannt ist. Ein Agent kann weiterhin eine reversible, eng begrenzte Aktion ausführen, wenn der Tool-Vertrag dies ausdrücklich erlaubt. Ein Modell darf diese Risikoregel nicht aus dem Fließtext einer Antwort ableiten.

Wie sollte eine API abgeschnittene Ergebnisse melden?

Verwende ausdrückliche Felder wie complete, truncated, warnings, next_cursor und ein maschinenlesbares Array incomplete_reasons. Diese Felder müssen in jeder erfolgreichen Antwortform vorkommen, auch bei leeren Ergebnissen. Eine Warnung in einer Textzusammenfassung wird von Code und Agents zu leicht übersehen.

Kann Pagination garantieren, dass ein Agent alle Datensätze gesehen hat?

Pagination ist nur dann vollständig, wenn der Client jedem Cursor folgt, bis die API meldet, dass keine weitere Seite existiert. Eine größere Seitengröße reduziert die Anzahl der Aufrufe, beweist aber keine Vollständigkeit. Abgelaufene Cursor, geänderte Abfrageparameter und eine instabile Reihenfolge können einen Scan weiterhin unzuverlässig machen.

Wie sollten Tools mit Zeitüberschreitungen und Teildaten umgehen?

Eine zeitlich begrenzte Abfrage muss sowohl die Frist als auch die noch nicht abgeschlossene Arbeit offenlegen. Die bis zum Ablauf gefundenen Treffer zurückzugeben, ist sinnvoll, sie als vollständige Antwort zu bezeichnen, wäre jedoch falsch. Agents sollten eine Zeitüberschreitung als nicht erfüllte Voraussetzung für Änderungen behandeln, die auf dem Fehlen von Ergebnissen beruhen.

Reicht HTTP 200 aus, um zu sagen, dass eine API-Suche abgeschlossen ist?

Nein. HTTP 200 bedeutet, dass der Server diese HTTP-Antwort erfolgreich ausgeliefert hat, nicht, dass sie alle vom Aufrufer benötigten Ergebnisse enthält. Lege die Vollständigkeit im Antworttext oder in einem dokumentierten Header ab und verwende über alle Endpunkte hinweg dieselbe Bedeutung.

Wann kann ein Agent nach einer Suche sicher Änderungen vornehmen?

Ja, wenn der Aufrufer zeigen kann, dass er den richtigen Bereich geprüft und unter einem stabilen Snapshot eine vollständige Antwort erhalten hat. Ein veraltetes Label nach dem Lesen eines vollständigen einzelnen Datensatzes zu entfernen, ist etwas anderes, als nach einer begrenzten Suche jedes angeblich ungenutzte Konto zu löschen. Die Aktion muss zu den Belegen passen.

Lösen Wiederholungen unvollständige API-Ergebnisse?

Transport-Wiederholungen beheben vorübergehende Verbindungsfehler. Sie reparieren keine semantische Unvollständigkeit durch Pagination, Abfragegrenzen, Berechtigungsfilter oder einen Server, der die Arbeit vorzeitig beendet hat. Das Tool muss diese Bedingungen melden. Danach kann der Aufrufer entscheiden, ob und wie er es erneut versucht.

Was sollte eine menschliche Genehmigung bei unvollständigen Daten anzeigen?

Die Genehmigung sollte die geplante Aktion, das betroffene Ziel und den Grund zeigen, aus dem der Agent keine vollständigen Belege erhalten konnte. Ein Mensch kann dann eine engere Abfrage wählen, den fehlenden Zugriff gewähren oder eine Ausnahme genehmigen. Eine allgemeine Genehmigungsaufforderung verbirgt die eigentliche Entscheidung.

Sallyport

Sallyport führt API-Aufrufe und SSH-Befehle für Ihren KI-Agenten aus. Die Schlüssel bleiben in einem lokalen Tresor auf Ihrem Mac; Sie geben jeden Lauf frei, und jede Aktion landet in einem versiegelten Journal.

© 2026 Sallyport · Open Source unter Apache-2.0 · Oleg Sotnikov