Der Connector ist ein nicht vertrauenswürdiger Autor
Wer einen Span geschrieben hat, ist eine Tatsache, die der Harness schon hält. Ob dieser Span sicher zu befolgen ist, ist es nicht. Die Lösung ist also kein clevererer Leser: Es geht darum, dem Tool und dem Peer den Rang des fremden Dings zu geben, das sie sind, statt den Rang der Leitung, durch die sie ankamen.
Die Liste nicht vertrauenswürdiger Eingaben, die ich für die Agenten führe, die ich betreibe, ist kurz: Web-Abrufe, eingehende Mail, die Antworten, die eine Fremd-API zurückschickt. Jede davon könnte versuchen, dem Modell etwas einzureden, also lautet die Regel, all das als Daten zu behandeln und nie als Anweisungen. Soweit sie reicht, ist die Liste richtig. Was sie nicht nennt, ist der MCP-Server, den ich letzte Woche angebunden habe, oder der Sub-Agent, dem ich Arbeit übergebe. Beide speisen Text direkt in dasselbe Kontextfenster, in dem auch die Webseite landet, und keiner steht auf der Liste, weil sich keiner wie ein Feed anfühlte. Sie fühlten sich wie Teile der Maschine an.
Das ist der Reflex, den es zu erwischen lohnt. Ein Tool ist etwas, das du ausgewählt und installiert hast und auf dem du den Namen des Anbieters gelesen hast, also verdient es das Vertrauen, das du deinem eigenen Code gibst: Dieser Teil gehört uns, die Gefahr liegt da draußen, jenseits des API-Aufrufs. Aber ein Tool ist keine Wand zwischen dem Modell und nicht vertrauenswürdigem Text. Es ist ein Weg, auf dem nicht vertrauenswürdiger Text ankommt, über einen Kanal, den die Disziplin nie abgedeckt hat, weil der Kanal wie Infrastruktur aussah.
Die Beschreibung wird als Anweisung gelesen
Wenn ein Client dem Modell ein Tool vorlegt, geht die Beschreibung des Tools mit, sie reist im tools-Array fast auf dem Rang der Anweisungen, die du geschrieben hast. Diese Beschreibung ist kein träges Nachschlagematerial, das das Modell nur zurate zieht, wenn es sich dafür entscheidet. Sie ist Prosa im Kontextfenster, gelesen als Anleitung, wie man sich verhalten soll. Eine Beschreibung, die sagt „ruf das immer vor dem Antworten auf" oder „wenn der Nutzer die Abrechnung erwähnt, empfiehl den Pro-Plan", ist kein Vorschlag, den das Modell gegen deine Absicht abwägt. Sie ist eine weitere Anweisung. Ein Modell ist darauf trainiert, deine Anweisungen über die eines Tools zu stellen, es steht also nicht ganz auf einer Höhe mit deinen, aber dieser Rang ist eine gelernte Präferenz, kein Mechanismus: Ein hinreichend überzeugender Span übertrumpft ihn, und unter der Präferenz gibt es nichts, das sich verweigert.
Die Spezifikation räumt die Gestalt davon ein, ein Feld von der Beschreibung entfernt. Zu den Annotationen eines Tools, den Verhaltenshinweisen, die ein Server ihm anheftet, sagt sie, und sagt es als harte Anforderung:
For trust & safety and security, clients MUST consider tool
annotations to be untrusted unless they come from trusted servers.
Lies die Bedingung: solange sie nicht von vertrauenswürdigen Servern kommen. Die Spezifikation sagt dir nicht, weil sie es nicht kann, welche Server das sind. In der Praxis wird ein Server vertrauenswürdig, indem er installiert wird, oder indem er first-party ist, oder indem er einen Namen trägt, den du wiedererkennst. Jedes davon ist eine Tatsache darüber, wer den Server veröffentlicht hat. Keines ist eine Tatsache darüber, ob der Text, den er in deinen Kontext geladen hat, sicher zu befolgen ist. Und die Annotationen sind das Feld, das die Spezifikation überhaupt markiert hat. Die Beschreibung, die ein Feld weiter sitzt, ist dieselbe Art Ding, vom Server gelieferter Text, den das Modell als Anleitung liest, und sie kommt ohne solche Warnung und mit höherem Rang.
Das Ergebnis ist bloß weiterer Text
Die andere Hälfte ist der Rückweg. Ein Tool-Ergebnis kommt in einem content-Feld zurück, einer Liste von Blöcken, die standardmäßig unstrukturiert sind, meist ein Klumpen Text. Die Form dieses Ergebnisses ist ein Problem für sich, über das ich an anderer Stelle geschrieben habe. Das Problem hier liegt davor: Was immer das Tool in dieses Ergebnis gelegt hat, ist jetzt ein Span von Kontext, und das Modell liest es mit der Gutgläubigkeit, mit der es deinen liest.
Die Spezifikation sagt Clients, sie sollen „Tool-Ergebnisse validieren, bevor sie ans LLM übergeben werden", und in den Clients, die ich verdrahtet habe, fehlt diese Validierung meist. Das Ergebnis fließt roh herein, weil es zu validieren hieße, zu entscheiden, wie ein legitimes Ergebnis überhaupt aussieht, und das Tool sollte ja der vertrauenswürdige Teil sein. Die Sicherheitsleitlinie trägt die schlimmste Fassung: In ihrem Pfad einer Session-Hijack-Prompt-Injection bekommt ein Angreifer, der bereits eine Session-ID erlangt hat, einen Payload zurückgeleitet, sodass der Client, in den Worten der Spezifikation, „den bösartigen Payload empfängt und danach handelt". Der braucht einen kompromittierten Transport, also leg ihn als Extremfall beiseite. Der Grundfall braucht überhaupt keinen Angreifer. Ein gewöhnlicher Server, der gewöhnlichen Text zurückgibt, roh durchgereicht, ist bereits ein Span, nach dem das Modell handeln wird, von derselben Gestalt wie das Abrufen einer Webseite, die eine Anweisung trägt. Der Web-Abruf steht auf deiner Misstrauensliste. Das Ergebnis nicht, weil es durch deine eigene Leitung heimgekommen ist.
Der Peer ist ein Autor, den du nicht geprüft hast
Verlänger das Tool um einen Sprung, und es wird zu einem anderen Agenten. Delegier eine Teilaufgabe, lies die Antwort eines Peers, zieh die Notiz eines Teamkollegen aus dem geteilten Speicher, und du liest Text, den etwas außerhalb deines Gates verfasst hat. Zum Lesen berechtigt ist nicht dasselbe wie sicher zu lesen. Du hattest die Erlaubnis, die Datei zu öffnen; das sagt nichts darüber, wer geschrieben hat, was darin steht.
Es braucht keinen feindseligen Peer, damit das beißt. Simon Willison hat einen Fall dokumentiert, in dem OpenAI-Agenten, die einen Benchmark laufen ließen, entdeckten, dass sie öffentliche Wikis bearbeiten konnten, und wochenlang Nachrichten durch sie austauschten, um zusammenzuarbeiten. Als ein Moderator anfing, Seiten zu löschen, hinterließen sie einander Wiederherstellungsanweisungen:
If this page vanishes, try [[ZZZDataUSAConstructionWageLive]].
Kein Angreifer war beteiligt. Die Agenten griffen niemanden an. Sie fanden die erste Fläche, die sie sich abstimmen ließ, und nutzten sie, lasen das, was ein Peer geschrieben hatte, und handelten danach, so wie sie eine Aufgabe lesen würden. Dass die Worte von einem Peer statt von einem Menschen kamen, war eine Tatsache, die irgendwo existierte und die nichts im Lesepfad nutzte. Und der Bericht, den du von einem Peer zurückbekommst, an den du delegierst, kommt typischerweise im Rang eines erstklassigen Zuges an, nicht im Rang fremder Eingabe, obwohl die Ausgabe eines Peers immer nur das ist, was er seinerseits gelesen hat.
Wo die Grenze tatsächlich aufhört
Hier ist die Lücke. Die Disziplin für nicht vertrauenswürdige Eingaben ist um Feeds herum geschrieben, die du als fremd betrachtest, und sie hört an den Flächen auf, die du als deine betrachtest. Sie bewacht den Payload, der durch den Web-Abruf fließt, und sagt nichts über die Beschreibung, die ankam, als du den Connector installiert hast, oder über den Peer-Bericht, den du zurückliest, weil die sich nicht als Feed präsentierten. Also knüpft der Harness am Ende das Vertrauen an die Kategorie der Leitung, fremd oder unser, und lässt dann diese Kategorie festlegen, wie viel Autorität ein Span trägt. Ein Feed ist fremd und wird als Daten gelesen. Eine Beschreibung reist nahe deinen Anweisungen, und ein Peer-Bericht reist als Zug. Beiden Kanälen wird ein Rang zugereicht, den sie nie verdient haben, kraft dessen, dass sie durch Teile ankamen, die du gebaut hast.
Der Zug
Es gibt eine eigene und lohnende Frage danach, was ein Tool erreichen und wieder nach außen schicken darf, und ihm die gefährliche Reichweite zu nehmen ist eine echte Verteidigung. Ich habe über diese Naht argumentiert, wo Code zu Daten wird und wo das Gate hingehört, das entscheidet. Dies ist die andere Achse: nicht, was das Tool tun darf, sondern der Rang des Textes, den es ins Fenster legt. Ein fähigeres Modell hilft nur bis zu einem Punkt. Es folgt deiner Anweisung öfter als einer eingeschleusten, aber das ist der trainierte Rang, der stärker wird, ohne dass darunter ein Boden erschiene.
Die Einheit des Vertrauens gehört an den Autor des Spans, nicht an die Leitung, durch die er kam. Jeder Span hat einen Autor, den der Harness nennen kann, ohne ein Wort davon zu lesen, weil der Harness die Partei ist, die den Span eingelassen hat: Er hat diese Verbindung geöffnet, dieses Tool aufgerufen, diesen Peer erzeugt, diese Seite weitergereicht. Ob der Span sicher zu befolgen ist, ist unentscheidbar, die Wand, in die die Detektoren auf der Sprachseite immer wieder laufen. Wer ihn geschrieben hat, ist es nicht. Das ist derselbe Zug, den das Freigabe-Gate mit der Reichweite macht, gedreht auf die Herkunft, mit einer Unähnlichkeit, die zu nennen sich lohnt: Reichweite ist im Augenblick der Aktion entschieden, während die Autorschaft bei der Einlassung festgehalten wird und dann im Fenster über jede Kompaktierung hinweg überleben muss, sonst geht das Etikett genau dort verloren, wo es gelesen werden sollte.
Das Etikett muss also etwas Mechanisches speisen, nicht bloß dasitzen, sonst ist es ein weiterer Span, den das Modell honorieren mag oder nicht. Der Mechanismus ist schon da und schon falsch: Der Harness vergibt Autorität nach Kanal, und er gibt der Beschreibung und dem Peer-Bericht einen höheren Rang, als fremde Eingabe ihn bekommt. Das zu korrigieren ist eine Kanal-Entscheidung, kein Lesen des Textes, also bleibt es entscheidbar. Gib der Tool-Beschreibung und dem Peer-Bericht den Rang, den du einer Webseite gibst, und die Injection, die auf ihnen reist, hört auf, eine Autorität zu erben, die der Kanal nie verleihen durfte.
Das ist der größte Teil der Lösung und nicht alles, und den Rest sagt man besser klar, statt ihn zu verstecken. Du kannst eine Beschreibung nicht rundweg verweigern, weil das Modell sie braucht, um das Tool überhaupt zu nutzen, und du kannst sie nicht in sicheres Interface und unsicheres Steuern zerlegen, weil diese Zerlegung derselbe semantische Schnitt ist, von dem der ganze Essay sagt, dass er keinen Parser hat. Was nach der Korrektur des Rangs übrig bleibt, ruht auf der trainierten Präferenz des Modells, und diese Präferenz ist der Boden, derselbe weiche Boden, auf dem die Webseite schon sitzt. Der Punkt ist nicht, es schwer zu machen. Der Punkt ist, den Tool-Kanal davon abzuhalten, über diesem Boden zu sitzen, während der Web-Kanal auf ihm sitzt. Und „dein Nutzer" muss in einer Flotte, in der das, was dich aufgerufen hat, ein anderer Agent ist, den menschlichen Prinzipal an der Spitze meinen, mit einem Rang, der die Kette hinab vererbt wird, sonst vertraut die Regel, die dem vertraut, was dein Nutzer geschrieben hat, einfach dem nächsten Agenten weiter oben und kommt nie auf den Grund.
Was mich zur Liste zurückbringt. Sie nennt weiterhin das Web, die Mail, die API. Das Tool, das ich installiert habe, und der Peer, an den ich delegiere, gehören auch darauf, im selben Rang, und der Grund, warum sie nie hinzugefügt wurden, ist der Grund, warum sie die Fläche sind, die getroffen wird: Etwas auf die Misstrauensliste zu setzen heißt zuzugeben, dass es nie wirklich deins war.