Geheimnisfreie Agenten-Tools: belastbare Aktionsverträge
Geheimnisfreie Agenten-Tools halten Zugangsdaten außerhalb von KI-Prozessen. Sie nutzen Aktionsverträge, eingeschränkte Parameter, menschliche Genehmigungen und prüfbare Ausführung.

Agenten sollten Aktionen anfordern, nicht die Mittel erhalten, sich als eine Person oder ein Dienstkonto auszugeben. Das klingt selbstverständlich, bis man ein typisches Agenten-Tool betrachtet: Eine Funktion wie http_request akzeptiert URL, Header, Methode und Inhalt, während der Agent ein Bearer-Token aus einer Umgebungsvariable erhält. Der Tool-Aufruf sieht ordentlich aus. Die Berechtigung verteilt sich jedoch über Prompt-Text, Prozessspeicher, Protokolle, Shell-Verlauf und den nächsten Unterprozess, den der Agent startet.
Ein geheimnisfreies Design zieht eine klare Grenze zwischen Absicht und Ausführung. Der Agent sagt: «Erstelle für diesen Dienst in dieser Umgebung ein Deployment.» Eine Schicht, die die Zugangsdaten besitzt, entscheidet, ob die Aktion ausgeführt werden darf, wählt die passende Identität, führt den authentifizierten Aufruf aus und gibt das Ergebnis zurück. Dadurch verändert sich, was du prüfen, genehmigen und widerrufen kannst. Zugleich zwingt dich dieser Ansatz, Schnittstellen zu schreiben, denen man Autonomie anvertrauen kann.
Ein Vertrag muss die Absicht beschreiben, nicht den Transport
Ein Aktionsvertrag benennt die Operation, die ein Nutzer erkennt, und beschränkt die Eingaben auf die für diese Operation nötigen Informationen. Transportdetails gehören hinter die Grenze. Der Unterschied wird leicht übersehen, weil HTTP jede Aktion wie eine Kombination aus Methode, URL, Headern und JSON-Inhalt aussehen lässt.
Betrachte zwei Tool-Schnittstellen zum Eröffnen eines Änderungsantrags. Die erste ist verbreitet und für einen autonomen Prozess unsicher:
{
"name": "http_request",
"input": {
"method": "POST",
"url": "https://code.example/api/projects/alpha/changes",
"headers": {
"Authorization": "Bearer ${TOKEN}",
"Content-Type": "application/json"
},
"body": {
"title": "Fix timeout",
"branch": "agent/fix-timeout"
}
}
}
Diese Schnittstelle gibt dem Agenten die Kontrolle über Ziel, Authentifizierungsmethode und Anfrageformat. Das Entfernen des Klartext-Tokens löst das Problem nicht, wenn der Agent einen Header-Alias, eine Zugangsdatenkennung, eine Proxy-URL oder einen Shell-Befehl auswählen kann, der an anderer Stelle ein Token liest. Du hast das Geheimnis verschoben, aber die Berechtigung nicht verringert.
Eine vertragsorientierte Schnittstelle sieht eher so aus:
{
"name": "create_change_request",
"input": {
"project": "alpha",
"source_branch": "agent/fix-timeout",
"title": "Fix timeout in retry path",
"description": "Adds a bounded retry and a regression test."
}
}
Die Ausführungsschicht ordnet project einem bekannten Endpunkt und einem genehmigten Konto zu. Den Authentifizierungs-Header fügt sie selbst ein. Sie kann den Branch-Namen ablehnen, das Ziel-Repository prüfen, eine Genehmigung anfordern oder einen Fehler des entfernten Dienstes zurückgeben. Der Agent hat keinen Parameter mit der Bedeutung «verwende die Zugangsdaten mit den größten Rechten».
Das ist ein Unterschied, den viele regelmäßig verwischen: Geheimnisfreiheit ist nicht dasselbe wie Token-Schwärzung. Beim Schwärzen versucht man zu kontrollieren, was der Agent sieht, nachdem er die Berechtigung erhalten hat. Ein Aktionsvertrag verhindert, dass der Agent diese Berechtigung überhaupt besitzt. Wenn ein Modell-Prompt durchsickert, ein Tool-Transkript kopiert wird oder ein Unterprozess seine Umgebung liest, ist beim ersten Design bereits eine Zugangsdatenquelle verloren. Das zweite Design kann Betriebsdaten offenlegen, die eigene Schutzmaßnahmen benötigen, aber es übergibt nicht das Material zum Signieren.
Ein Vertrag sollte außerdem nicht so tun, als verdiene jeder Endpunkt ein eigenes Tool. Benutzerdefinierte Aktionen sind sinnvoll, wenn eine Person das gewünschte Ergebnis in einem Satz formulieren kann. «Starte diese Staging-Workload neu» beschreibt ein Ergebnis. «Sende einen PATCH an eine beliebige URL» ist ein Transport-Grundbaustein. Wenn du diesen Grundbaustein für einen Wartungsjob brauchst, gib ihn einer separaten, streng begrenzten Integration, nicht einem universellen Coding-Agenten.
Der Besitzer der Zugangsdaten muss die Anfrage ausführen
Ein Vertrag schützt nichts, wenn der Agent den endgültigen Netzwerkaufruf weiterhin mit einem in seinem Prozess eingebundenen Geheimnis ausführt. Die Komponente, die die Zugangsdaten speichert, muss selbst die HTTP-Anfrage oder SSH-Verbindung herstellen.
Die Ausführungsgrenze hat damit fünf Aufgaben:
- Sie ordnet den Aktionsnamen einem festen Ziel und einem festgelegten Protokollverhalten zu.
- Sie wählt eine gespeicherte Identität aus einer kleinen genehmigten Menge.
- Sie fügt die Zugangsdaten nur in die ausgehende Anfrage oder den SSH-Authentifizierungsaustausch ein.
- Sie protokolliert Anfrage, Entscheidung und Ergebnis, ohne geheime Informationen in den Eintrag zu schreiben.
- Sie gibt eine für die Aktion geformte Antwort zurück, nicht einen Dump ihres internen Zustands.
Der Modellprozess sollte weder ein Token noch einen privaten Schlüssel erhalten, auch keinen vorübergehend gültigen. Vermeide Shell-Muster wie TOKEN=$(vault read ...), Zugangsdaten in Arbeitsverzeichnissen, Authorization-Werte in generierten curl-Befehlen und SSH-Agenten, die mit einer vom Agenten gestarteten Shell geteilt werden. Alles wirkt praktisch, weil bestehende Skripte weiterverwendet werden können. Doch dadurch wird der Agentenprozess zum Besitzer der Zugangsdaten.
Die OAuth 2.0 Security Best Current Practice der IETF macht in einem anderen Zusammenhang denselben praktischen Punkt: Bearer-Tokens müssen bei der Speicherung und Übertragung geschützt werden, weil jeder, der eines besitzt, es verwenden kann. Ein Bearer-Token wird nicht dadurch sicher, dass man einem Modell sagt, es solle ihn nicht ausgeben. Der Besitz ist die Autorisierungsprüfung. Bei einem Agenten-Tool ist es besser, dem Prozess den Besitz gar nicht erst zu geben.
Bei SSH muss die Grenze mehr als den privaten Schlüssel verwalten. Eine rohe Schnittstelle wie ssh host command gibt dem Agenten weitreichenden Zugriff, selbst wenn der Schlüssel einen Helfer nie verlässt. Der Helfer sollte eine gespeicherte Hostdefinition und Identität auswählen und anschließend eine für diesen Host passende Befehlsform erzwingen. Ein Deployment-Host könnte status, restart-service und tail-release-log mit einem Dienstnamen erlauben. Er sollte nicht stillschweigend bash -c akzeptieren, nur weil jemand eine Abkürzung wollte.
Verwechsle das nicht mit einem Man-in-the-Middle-Proxy. Ein Proxy leitet beliebigen Client-Datenverkehr weiter und sieht dabei häufig Zugangsdaten. Eine Aktionsschicht, die Zugangsdaten besitzt, erhält eine Anfrage für eine benannte Operation, erstellt den ausgehenden Aufruf und hält die Zugangsdaten in ihrem eigenen Tresor. Dieser Unterschied entscheidet darüber, ob der Agent eine genehmigte Aktion in eine andere umwandeln kann.
Das Parameterdesign entscheidet, wie viel Berechtigung durchsickert
Jedes Feld in einem Vertrag schafft einen Freiheitsgrad. Gute Felder identifizieren das Arbeitsobjekt oder liefern Inhalte, die die Aktion tatsächlich benötigt. Schlechte Felder verändern das Ziel der Berechtigung, die verwendete Identität oder die auszuführende Operation auf niedriger Ebene.
Prüfe jede geplante Eingabe mit diesem Test: Kann der Agent mit einer Änderung dieses Werts eine privilegierte Anfrage an ein anderes System umleiten, den Kreis der betroffenen Ressourcen erweitern oder die Authentifizierung verändern? Wenn ja, entferne das Feld, verwandle es in eine vom Ausführer abgebildete Aufzählung oder teile die Operation in mehrere Verträge auf.
Eine Deployment-Schnittstelle zeigt den Punkt:
{
"name": "deploy_release",
"input_schema": {
"type": "object",
"additionalProperties": false,
"required": ["service", "environment", "version", "reason"],
"properties": {
"service": {"type": "string", "enum": ["api", "worker"]},
"environment": {"type": "string", "enum": ["test", "production"]},
"version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
"reason": {"type": "string", "maxLength": 500}
}
}
}
Das Schema verhindert unerwartete Felder wie url, headers, credential_name oder command. Der Ausführer kann service und environment einem bekannten Deployment-Ziel zuordnen. additionalProperties: false ist wichtiger, als es zunächst wirkt. Ohne diese Einstellung kann ein großzügiger Validator ein unbekanntes Feld beibehalten, das später «aus Gründen der Flexibilität» an einen HTTP-Client angeschlossen wird. So wird aus einer harmlosen Erweiterungsmöglichkeit ein Fluchtweg für Zugangsdaten.
Aufzählungen sind nicht immer die richtige Antwort. Ein Repository-Name, Branch, Ticketnummer oder Dateipfad muss möglicherweise variieren. Validiere solche Werte nach den Regeln ihres jeweiligen Bereichs und führe nach der Auflösung eine Grenzprüfung durch. Löse beispielsweise eine Repository-Kennung über eine lokale Allowlist auf und verwende anschließend den zugeordneten entfernten Ort. Akzeptiere keine Repository-URL, um danach zu beurteilen, ob sie vertrauenswürdig aussieht.
Freitext verdient eine eigene Betrachtung. Ein Agent muss möglicherweise eine Aufgabenbeschreibung, eine Pull-Request-Zusammenfassung oder eine Supportantwort verfassen. Dieser Text ist Inhalt, keine Berechtigung, kann aber durch Erwähnungen, Markup, Vorlagen oder eingebettete Befehle, die der nachgelagerte Dienst verarbeitet, trotzdem Schaden verursachen. Begrenze seine Länge, lege das Darstellungsverhalten fest und setze ihn niemals in einen Shell-Befehl ein. Wenn eine Aktion einen Befehl ausführen muss, erstelle das Argument-Array direkt und halte nicht vertrauenswürdigen Text in einem Datenargument, niemals in einer Befehlszeichenfolge.
Generische Anfrage-Tools erzeugen versteckte Richtlinien-Engines
Ein generisches HTTP-Tool ist beliebt, weil Teams einen Agenten innerhalb eines Nachmittags mit jedem Dienst verbinden können. Für die meisten privilegierten Agentenaufgaben ist es ungeeignet, weil jeder Prompt, jede Toolbeschreibung und jeder Codepfad zu einer inoffiziellen Autorisierungsrichtlinie wird.
Ein Team beginnt oft mit einem Wrapper wie:
request(method, url, headers, body)
Dann kommen Schutzmaßnahmen hinzu. Einige Domains blockieren. Authorization entfernen. Bestimmte Methoden erlauben. Ein URL-Präfix prüfen. localhost ablehnen. Für riskante Aufrufe einen Genehmigungsdialog verlangen. Monate später benötigt jemand einen neuen Endpunkt mit einem eigenen Header, fügt eine Ausnahme hinzu, und der Wrapper enthält nun eine Richtliniensprache ohne Tests und ohne klaren Verantwortlichen.
Das Problem ist nicht, dass generische Tools grundsätzlich schlecht sind. Sie passen zu einer von Menschen bedienten Debugging-Konsole, bei der der Bediener die Berechtigung bereits besitzt und jedes Byte prüfen kann. Sie passen auch zu einem Integrationsdienst, der Aufrufe aus kontrolliertem Code erhält und eine eng begrenzte Netzwerkidentität besitzt. Ein autonomer Agent ist anders, weil er viele Aufrufe durchführen, unerwartete Pfade entdecken und auf nicht vertrauenswürdigen Text reagieren kann. Er braucht weniger Freiheitsgrade.
Schreibe benannte Aktionen um stabile Arbeitseinheiten herum. Bei einem Quellcodeverwaltungsdienst sind read_merge_request, comment_on_merge_request und create_branch besser als ein universeller REST-Client. Für den Betrieb sind get_service_status, fetch_release_logs und request_deployment vorzuziehen. Du brauchst möglicherweise mehr Verträge, aber jeder hat einen Verantwortlichen, eine Testsuite, ein klares Genehmigungslabel und einen nachvollziehbaren Schadensradius.
Verstecke auch kein generisches Anfrage-Tool in einer benannten Aktion. Ein Tool namens update_ticket, das beliebige Werte für path, method und body akzeptiert, hat nur die Bezeichnung geändert. Der Vertrag muss diese Details binden. Wenn die nachgelagerte API ein Patch-Objekt benötigt, kann die Schnittstelle ein kontrolliertes Patch-Objekt anbieten. Der Ausführer sollte jedoch Endpunkt, HTTP-Methode, Inhaltstyp und Konto bestimmen.
Die Spezifikation des Model Context Protocol hilft bei der Tool-Erkennung, weil ein Server Toolnamen, Beschreibungen und JSON-Eingabeschemata an einen Client veröffentlichen kann. Dieses Schema ist nützlich, macht eine zu weit gefasste Aktion aber nicht sicher. Ein JSON-Schema kann mitteilen, dass eine URL eine Zeichenfolge ist. Es kann nicht feststellen, ob diese URL der einzige AbrechnungseEndpunkt ist, den deine Produktionszugangsdaten jemals erreichen dürfen. Die Autorisierung bleibt Aufgabe der Ausführungsschicht.
Die Genehmigung sollte die Aktion benennen, die ein Mensch beurteilen kann
Eine menschliche Genehmigung funktioniert, wenn die Person eine verständliche Anfrage sieht und sie schnell ablehnen kann. Sie scheitert, wenn jemand ein undurchsichtiges Paket von Transportdetails genehmigen soll, nachdem der Agent bereits die wichtigen Entscheidungen getroffen hat.
Vergleiche diese Genehmigungskarten:
Allow POST https://api.example/v1/resources/882?
Headers: Authorization, X-Region, X-Client
Deploy version 2.14.3 of api to production
Reason: Fixes failed payment retries
Requested by: signed agent process build-worker
Die zweite Karte ermöglicht es dem Bediener, die Absicht zu beurteilen. Außerdem liefert sie dem Prüfprotokoll einen verständlichen Satz. Die erste Karte verlangt, dass der Bediener die Bedeutung aus URL und Header-Liste rekonstruiert, und fördert dadurch Genehmigungsmüdigkeit. Menschen klicken sich durch unleserliche Anfragen, besonders wenn ein normaler Agentenlauf mehrere davon erzeugt.
Setze Genehmigungen an dem Punkt ein, an dem sich die Berechtigung ändert. Eine Ausführungsschicht kann einen neuen Agentenprozess einmal pro Sitzung autorisieren und anschließend für ausgewählte sensible Zugangsdaten oder destruktive Aktionen eine neue Entscheidung verlangen. So bleibt die alltägliche Arbeit praktikabel, ohne alle Zugangsdaten gleich zu behandeln. Ein schreibgeschütztes Projekttoken und eine Identität für Produktionsdeployments sollten nicht dieselbe Genehmigungsregel haben, nur weil beide in HTTP-Headern übertragen werden.
Die Sprache der Genehmigung muss angeben, wer die Operation angefordert hat. Die Prozessidentität ist nützlich, weil ein Terminal-Agent, ein Hintergrundhelfer und ein unbekanntes Programm nicht dasselbe Vertrauen verdienen. Unter macOS kann die Codesignatur der Person, die einen Lauf genehmigt, ein konkretes Signal zur Herkunft geben. Sie beweist nicht, dass jede Prompt-Anweisung sicher ist, beantwortet aber die erste Frage: Welcher Prozess verlangt, mit diesem Konto zu handeln?
Mache die Genehmigung niemals zur einzigen Kontrolle. Eine Person kann einen Prompt falsch lesen, unter Zeitdruck genehmigen oder eine Sitzung offen lassen. Der Vertrag braucht weiterhin eingeschränkte Eingaben und einen festen Zugangsdatenpfad. Umgekehrt solltest du keine Richtliniensprache einführen, wenn ein klarer Aktionsvertrag mit einer Genehmigungsentscheidung ausreicht. Regeln, die beliebige Felder, Zeitfenster, reguläre Ausdrücke und Nutzerangaben vergleichen, werden schnell zu einem weiteren Programm, das im Vorfall niemand zuverlässig prüfen kann.
Ein fehlgeschlagenes Deployment zeigt, wo lose Verträge versagen
Ein typischer Fehler beginnt mit einem Agenten, der über ein Shell-Tool in der Testumgebung deployen kann. Das Team speichert ein Cloud-Token in der Umgebung des Agenten, weil das Deployment-CLI es erwartet. Das Tool-Schema akzeptiert environment und extra_args, was harmlos wirkte, solange es nur die Testumgebung gab.
Ein Ticket bittet den Agenten, «den dringenden Fix in der Testumgebung zu prüfen und das Ergebnis zu teilen». Der Agent führt den erwarteten Befehl aus. Anschließend findet er eine veraltete Deployment-Nachricht im Repository und versucht ein zusätzliches Argument aus einem alten Skript. Dieses Argument wählt die Produktion, ändert ein Zielkonto oder injiziert eine Shell-Erweiterung. Das Token hatte Produktionsrechte, weil getrennte Zugangsdaten als zu aufwendig galten. An diesem Punkt hilft die Formulierung des Prompts nicht mehr. Der Prozess besitzt bereits weitreichende Rechte, und die Schnittstelle lässt ihn das Ziel auswählen.
Eine Vertragsgrenze verändert den Ablauf:
- Der Agent ruft
deploy_releasemit einem aufgezählten Dienst, einer Umgebung, einer Version und einer Begründung auf. - Der Ausführer löst die Umgebung in ein festes Ziel auf und wählt die diesem Ziel zugewiesene Identität.
- Der Ausführer bittet um eine Entscheidung, wenn diese Identität eine benötigt, und protokolliert das Ergebnis unter dem Agentenlauf, der die Anfrage gestellt hat.
- Der Ausführer gibt eine Deployment-ID und den Status zurück oder eine strukturierte Ablehnung, die dem Agenten den Grund für den Abbruch mitteilt.
Der Agent kann weder --account hinzufügen, einen Cloud-Endpunkt setzen noch ein Token lesen. Der Wert production kann weiterhin versehentlich gewählt werden, weil Menschen und Modelle die falsche Anfrage stellen können. Aber der Genehmigungstext nennt nun die Produktion in verständlicher Sprache, die ausgewählte Identität kann nur die für Produktionsdeployments vorgesehene Berechtigung besitzen, und der Aktionsdatensatz verbindet die Entscheidung mit Prozess und Anfrage.
Dieser Unterschied ist bei der Diagnose entscheidend. Im losen Design finden Ermittler oft nur Fragmente: einen Shell-Verlauf, Cloud-Prüfereignisse, ein CI-Protokoll und vielleicht einen Tokenwert, der nun ausgetauscht werden muss. Im Vertragsdesign können sie die angeforderte Aktion, das aufgelöste Ziel, die Identitätsbezeichnung, das Genehmigungsergebnis, den Antwortstatus und die Sitzung prüfen, die den Vorgang gestartet hat. Ein Prüfprotokoll macht einen Fehler nicht ungeschehen, verkürzt aber die Zeit, in der man den ausgeführten Pfad erraten muss.
Fehlermeldungen müssen die Wiederherstellung anleiten, ohne Interna offenzulegen
Eine sichere Aktionsschicht sollte Fehler zurückgeben, mit denen ein Agent handeln kann, ohne das Geheimnis, Signaturdaten der Anfrage oder die interne Struktur des Tresors offenzulegen. Vage Fehler treiben Agenten zu Wiederholungen und Umgehungen. Zu detaillierte Fehler machen aus Fehlerprotokollen einen Informationskanal.
Verwende stabile Fehlercodes und eine kleine öffentliche Struktur:
{
"ok": false,
"error": {
"code": "APPROVAL_REQUIRED",
"message": "Deployment to production needs user approval.",
"retryable": true,
"request_id": "act_01H..."
}
}
Ein gesperrter Tresor sollte VAULT_LOCKED melden, eine abgelehnte Nutzerentscheidung APPROVAL_DENIED, ein Verstoß gegen den Vertrag INVALID_ARGUMENT und ein nachgelagerter 429-Fehler REMOTE_RATE_LIMITED. Der Agent kann den Zustand melden, warten, nach einer Änderung der angegebenen Bedingung erneut versuchen oder eine nicht destruktive Alternative wählen. Er sollte keine Fehlermeldung erhalten, die einen rohen Autorisierungs-Header, eine Token-Subjektliste, eine private Hostkonfiguration oder eine vollständig signierte Anfrage enthält.
Trenne einen Autorisierungsfehler von einem Fehler des entfernten Dienstes. «Zugriff verweigert» kann bedeuten, dass der lokale Ausführer die Aktion abgelehnt hat, dass dem ausgewählten Remote-Konto die Berechtigung fehlt oder dass der nachgelagerte Dienst eine fehlerhafte Authentifizierung zurückgewiesen hat. Diese Fälle benötigen unterschiedliche Reparaturen. Die öffentliche Nachricht kann knapp bleiben, während das geschützte Prüfprotokoll des Ausführers einen genauen Fehlercode und den Status des entfernten Dienstes enthält.
Wiederholungen brauchen eine Semantik, die zum Vertrag passt. Leseoperationen vertragen Wiederholungen häufig. Beim Erstellen eines Tickets, Versenden einer Nachricht oder Starten eines Deployments ist das nicht unbedingt der Fall. Füge eine Idempotenzkennung ein, wenn die entfernte API sie unterstützt. Sie wird vom Ausführer erzeugt oder als eingeschränkte Anfragekennung geliefert. Protokolliere die Zuordnung vor dem Senden der Anfrage und verwende sie bei einer Wiederholung erneut. Lass einen Agenten nicht jedes Mal neue Kennungen erfinden, wenn er einen Timeout sieht. Sonst kann er bei seinem Hilfsversuch doppelte Arbeit erzeugen.
Für Aktionen ohne Unterstützung für Idempotenz kannst du einen Ablauf aus Vorbereitung und Bestätigung verwenden. Die Vorbereitungsaktion gibt einen kurzlebigen Plan zurück, der Ziel und Änderung beschreibt. Die Bestätigungsaktion verweist auf diesen Plan und benötigt eine aktuelle Genehmigung. Das kostet einen zusätzlichen Netzwerkumlauf, ist aber günstiger, als eine Zahlung, Löschung oder Produktionsänderung nach einem unklaren Netzwerkfehler zu wiederholen.
Prüfprotokolle brauchen zwei Ansichten und eine gemeinsame Quelle
Ein gutes Prüfsystem beantwortet zwei verschiedene Fragen: Was hat dieser Agentenlauf versucht, und was hat jeder privilegierte Aufruf bewirkt? Wenn du beides in einem undifferenzierten Ereignisstrom zusammenfasst, wird es entweder schwierig, eine Sitzung zu rekonstruieren, oder einen bestimmten Aufruf zu finden.
Führe für den Lauf ein Sitzungsjournal. Es sollte Prozessidentität, Beginn und Ende, Autorisierungsentscheidung, Widerrufsstatus und die während des Laufs angeforderten Aktionen zeigen. Führe zusätzlich ein Aktivitätsjournal für die Aufrufe. Es sollte Aktionsname, normalisierte Parameter, die Bezeichnung der ausgewählten Zugangsdaten ohne deren Geheimnis, Genehmigungsergebnis, Zeitangaben, Zielklasse und Ergebnis anzeigen.
Beide Ansichten sollten aus demselben unveränderlich ergänzten Datensatz abgeleitet werden. Andernfalls können Sitzungsansicht und Aufrufprotokoll voneinander abweichen, wenn ein Schreiber abstürzt oder Ereignisse anders filtert. Ein verschlüsseltes Protokoll, in das nur geschrieben werden kann, hat außerdem einen praktischen Vorteil: Die Komponente, die ein Ereignis anhängt, muss vergangene Einträge nicht entschlüsseln, nur um einen neuen zu schreiben.
Manipulationsnachweise brauchen eine Prüfung außerhalb des Systems. Eine Hashkette ermöglicht es einem Prüfer, gelöschte, ersetzte oder neu sortierte Einträge zu erkennen, wenn ihm die Reihenfolge des Protokolls vorliegt. Die Prüfung sollte über dem Chiffretext laufen, damit ein Prüfer die Kontinuität kontrollieren kann, ohne den Tresorschlüssel zu erhalten. Das beweist nicht, dass ein kompromittierter Rechner niemals ein Ereignis nicht protokolliert hat. Es beweist aber, dass eine erhaltene Kette nachträglich nicht unbemerkt bearbeitet wurde. Behandle diese Aussagen getrennt.
Ein Befehlszeilen-Prüfer sollte Fehler verständlich ausgeben. Die Ausgabe kann so schlicht aussehen:
$ sp audit verify audit.log
verified: 184 records
first sequence: 9012
last sequence: 9195
chain: valid
Wenn Datensatz 9137 geändert wurde, sollte der Befehl die erste unterbrochene Sequenz nennen und mit einem Fehlerstatus enden. Gib nicht nur «verification failed» aus. Einsatzkräfte müssen wissen, ab welcher Stelle die Beweiskette nicht mehr vertrauenswürdig ist.
Sallyport verwendet diese geteilte Ansicht für Agentensitzungen und einzelne Aktivitäten. Beide werden aus einem verschlüsselten, hashverketteten Prüfprotokoll erzeugt, das sp audit verify ohne den Tresorschlüssel prüfen kann. Das ist die richtige Form für ein lokales Agenten-Gateway, weil der Widerruf einer laufenden Sitzung und die Untersuchung eines einzelnen Aufrufs unterschiedliche Aufgaben sind.
Verträge brauchen Tests, die ihren Ausbruch versuchen
Tests für den Erfolgsfall zeigen, dass eine Aktion funktioniert. Sicherheitstests zeigen, dass ihre deklarierten Eingaben die einzigen Steuerungsmöglichkeiten des Aufrufers sind. Schreibe diese Tests, bevor du einen Komfortparameter hinzufügst, denn über solche Parameter schleichen sich Berechtigungen häufig wieder ein.
Teste für jede Aktion mindestens diese Fälle:
- Weise ein unerwartetes Feld zurück, einschließlich
headers,url,commandund Zugangsdatenreferenzen. - Weise Werte zurück, die außerhalb der zulässigen Ressourcenmenge der Aktion aufgelöst werden.
- Stelle sicher, dass ausgehende HTTP-Anfragen Zugangsdaten erst erhalten, nachdem der Ausführer das Ziel erstellt hat.
- Stelle sicher, dass Prüfprotokolle keine Tokenwerte, privaten Schlüssel oder signierten Autorisierungsfelder enthalten.
- Stelle sicher, dass eine abgelehnte oder widerrufene Sitzung eine frühere Genehmigung nicht wiederverwenden kann.
Verwende in Tests einen simulierten ausgehenden Server und prüfe die empfangene Anfrage. Der Test sollte die tatsächliche URL, Methode und die vom Ausführer erstellten Header sowie das Fehlen einer vom Aufrufer kontrollierten Authentifizierung bestätigen. Wer nur den internen Client des Ausführers simuliert, verpasst die entscheidende Frage: Was würde den Rechner verlassen, wenn der Agent schädliche Parameter liefert?
Teste außerdem die unangenehmen Eingaben, die ein Modell irgendwann erzeugen wird: eine Repository-Kennung mit einem Schema-Präfix, einen Branch-Namen mit Shell-Sonderzeichen, ein Unicode-Homoglyph in einem Umgebungslabel, wiederholte JSON-Felder, eine riesige Beschreibung und einen Timeout, nachdem der entfernte Dienst die Aktion akzeptiert hat. Die Vertragsvalidierung sollte standardmäßig ablehnen. Wenn der Ausführer ein angefordertes Ziel nicht zuverlässig auflösen kann, sollte er den Aufruf verweigern und einen hilfreichen Fehler zurückgeben.
Prüfe Verträge wie Code mit Berechtigungen. Frage, ob ein neu hinzugefügtes Feld dem Aufrufer einen Weg zu einem anderen Host, einem umfassenderen Konto, einem anderen Befehl oder einer anderen Objektklasse eröffnet. Wenn ja, mache die Berechtigung im Aktionsnamen und im Genehmigungsverhalten sichtbar. Eine einfache Aktion delete_file mit einem frei wählbaren absoluten Pfad ist schwerer zu beurteilen als remove_preview_asset mit einer Asset-ID, die innerhalb eines bekannten Projekts aufgelöst wird.
Der erste Vertrag, den man meist verbessern sollte, ist derjenige, der eine beliebige URL oder eine Shell-Zeichenfolge akzeptiert. Ersetze ihn durch die kleinste benannte Aktion, die die tatsächlich benötigte Arbeit abdeckt. Die Schnittstelle wird weniger clever, und der Agent erhält weniger Macht, deren Folgen du später nicht erklären kannst. Das ist ein Fortschritt.
FAQ
Kann ein KI-Agent eine API verwenden, ohne einen API-Schlüssel zu erhalten?
Ja. Ein Tool kann eine Anfrage authentifizieren, ohne die Zugangsdaten offenzulegen, wenn eine separate Ausführungsschicht die Zugangsdaten verwaltet und die Anfrage selbst ausführt. Der Agent übermittelt einen Aktionsnamen und eingeschränkte Parameter und erhält anschließend die Antwort oder einen Fehler.
Was ist ein Aktionsvertrag für einen KI-Agenten?
Ein Aktionsvertrag beschreibt die Absicht, die zulässigen Parameter, das erwartete Ergebnis und das Fehlerverhalten einer einzelnen Operation. Er ist enger gefasst als eine API-Spezifikation, weil er nur die Aktionen beschreiben sollte, die ein Agent von einer Ausführungsschicht anfordern darf.
Welche Felder sollte ich aus einer Agenten-Tool-Schnittstelle entfernen?
Ein Agenten-Tool sollte fachliche Eingaben wie Repository, Umgebung, Aufgabentext oder Ressourcenkennung akzeptieren. Es sollte keine Autorisierungs-Header, Cookie-Zeichenfolgen, Pfade zu privaten Schlüsseln oder beliebige Anfrageobjekte akzeptieren, mit denen der Aufrufer indirekt die Zugangsdaten auswählen kann.
Ist ein generisches HTTP-Anfrage-Tool für autonome Agenten sicher?
Nur dann, wenn die Operation bewusst als Transport-Grundbaustein gedacht ist und du die damit verbundene Berechtigung akzeptierst. Die meisten Tools für autonome Agenten sollten stattdessen benannte Operationen anbieten, weil ein allgemeines HTTP-Methoden-und-URL-Paar in jedem Prompt eine versteckte Richtlinien-Engine erzeugen kann.
Wie sollte ein Agent mit einer abgelehnten Aktion umgehen?
Das Gateway sollte einen stabilen, maschinenlesbaren Fehler zurückgeben, der mitteilt, dass die Aktion eine Genehmigung benötigt oder der Tresor gesperrt ist, ohne geheime Informationen offenzulegen. Der Agent kann diesen Zustand melden und warten. Er sollte niemals versuchen, die Ablehnung über einen anderen Zugangsdatenpfad zu umgehen.
Wie unterstütze ich mehrere Konten, ohne Zugangsdaten weiterzugeben?
Nimm die Auswahl des Kontos in den Vertrag auf, wenn mehrere Identitäten für dieselbe Aktion zulässig sind. Ordne diese Auswahl innerhalb der Ausführungsschicht einer gespeicherten Zugangsdatenquelle zu und lehne unbekannte Auswahlen ab, statt eine beliebige Zugangsdatenreferenz vom Agenten zu akzeptieren.
Löst das Schwärzen von Tool-Ausgaben das Problem der Zugangsdatenoffenlegung?
Nein. Das Filtern von Ausgaben kann versehentliche Offenlegung verringern, aber es kann keine Berechtigung zurücknehmen, die ein Agent bereits über ein Token oder einen privaten Schlüssel erhalten hat. Halte Zugangsdaten zuerst aus dem Prozess heraus und behandle die Verarbeitung von Antworten anschließend als eigenes Thema.
Können geheimnisfreie Tools mit SSH-Befehlen funktionieren?
SSH benötigt einen benannten Host, eine zulässige Befehlsform und eine gespeicherte Identität, die von der Ausführungsschicht ausgewählt wird. Die Weitergabe eines privaten Schlüssels über eine Umgebungsvariable, eine temporäre Datei oder einen Agentenparameter ändert nur den Ort des Lecks.
Wie verhindern Aktionsverträge doppelte destruktive Anfragen?
Verwende eine wiederholsichere Kennung, eine eng gefasste Operation und eine Anforderungs-ID, die die Ausführungsschicht protokolliert. Für nicht idempotente Aktionen ist eine menschliche Genehmigung direkt bei der Ausführung erforderlich. Alternativ kannst du einen Ablauf aus Vorbereitung und Bestätigung mit einem ausdrücklichen Ablaufdatum entwerfen.
Bietet MCP eine Autorisierung für Agenten-Tools?
Verwende das Model Context Protocol für die Auffindbarkeit von Tools und die Validierung von Eingaben, aber verwechsle die Schema-Validierung nicht mit Autorisierung. Der Vertrag muss die angeforderte Aktion weiterhin an Zugangsdaten binden, die außerhalb des Agentenprozesses gehalten werden, sowie an eine menschlich kontrollierte Ausführungsentscheidung.