# 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:

```json
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:

```json
{
  "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:

```json
{
  "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

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 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:

```json
{
  "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

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:

```json
{
  "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.
