Harness Engineering für AI Agents: Control Loops entwerfen
Automatische Übersetzung Dieser Artikel wurde automatisch aus der englischen Originalversion übersetzt.
Artikel-Update
Ursprünglich am 22. Juli 2026 veröffentlicht. Am 6. September 2026 geprüft und aktualisiert. Das Update ergänzt neuere Evidenz aus Harness-Benchmarks und Fälle mit Provider-Interventionen und präzisiert, was die berichteten Ergebnisse belegen.
Ein Agent kann seinen Turn beenden, obwohl die Arbeit noch nicht abgeschlossen ist. Für einen Coding Agent sind das geänderte Artefakt und die erforderlichen Testergebnisse die relevante Evidenz. Eine abschließende Nachricht mit dem Inhalt „fertig“ belegt weder das eine noch das andere.
Das Harness ist der Control Code rund um den Reasoning Loop. Es stellt Context bereit, validiert und autorisiert Tool Calls, protokolliert Ergebnisse und entscheidet, ob die Evidenz ausreicht, um die Arbeit zu akzeptieren. Der Runtime hält darunter Execution und State am Leben.
Bei der Prüfung eines Harness würde ich zwei Fragen stellen: Was hindert es daran, unvollständige Arbeit zu akzeptieren, und welche Fehler rechtfertigen die zusätzlichen Controls? Dieser Artikel behandelt Acceptance Checks, Retries und Handoffs und zeigt anschließend, wie sich ein Control gegen eine feste Baseline vergleichen lässt. Die Store-Beispiele sind fiktiv; das begleitende Lab ist eine deterministische Simulation und keine Messung eines laufenden Agenten.
Der einfachste Acceptance Check lässt sich für einen kleinen Research Agent wie denjenigen aus dieser Serie leicht schreiben — einen LangGraph Agent, der Marktdaten abruft und einen Analystenbericht verfasst. Ein Hook außerhalb des Models validiert den Bericht gegen ein Schema und prüft, ob er tatsächlich Aktienticker enthält; ein fehlerhafter Bericht hält den Run offen. Zwölf Zeilen gewöhnlicher Code reichen aus, und das Model darf seinen eigenen Output nicht als wohlgeformt deklarieren. Das Repository verwendet einen weicheren Check: Ein Evaluator mit frischem Context gibt eine Bewertung ab, anschließend prüft ein Mensch das Ergebnis. (Teil 4 skizziert die deterministische Variante.)
Was dieses Beispiel nicht zeigen kann, ist der interessante Teil: Was passiert, wenn die Evidenz mehrdeutig ist, ein Retry jemanden doppelt belasten könnte oder die Arbeit länger dauert als die Session, die sie gestartet hat? Dafür braucht es eine Aufgabe mit einer schärferen Pass/Fail-Grenze als ein Research-Bericht. Der Research Agent bleibt das Beispiel für den Acceptance Check; für die Fälle mit Retry und Handoff kommt ein kleines fiktives Store-Repository hinzu. Die Coding-Aufgabe besteht darin, den Schwellenwert für einen automatischen Rabatt von 10 % in src/checkout.py von $100 auf $75 zu senken. Das Repository hat zwei erforderliche Checks:
pytest tests/test_checkout.pyverifiziert die Rabattberechnung.pnpm playwright test tests/checkout_discount.spec.tsfügt in einem lokalen Test-Store einen Artikel für $80 hinzu und prüft, ob die Checkout-Seite einen Rabatt von $8 anzeigt.
Das Beispiel ist ein Lehr-Fixture und keine reale Anwendung oder ein Benchmark. Jeder Versuch startet beim selben Commit und mit denselben initialisierten Testdaten. Das Harness darf die Änderung nur akzeptieren, wenn beide Commands erfolgreich sind und ein dauerhaftes Acceptance Record beide Ergebnisse mit einem sauberen committed Candidate oder einem Digest des vollständig getesteten Snapshots verknüpft, einschließlich relevanter nicht getrackter Dateien.
Das Diagramm verfolgt die Rabattänderung von der Proposal bis zur Evidenz. Das Harness stellt Task und Dateien bereit, prüft die vorgeschlagenen edit_file-Argumente und Berechtigungen und dispatcht den akzeptierten Call. Nachdem die Runtime die Änderung angewendet hat, führt das Harness die benannten Unit- und Browser-Acceptance-Tests aus. Ein fehlgeschlagener Command geht als Evidenz für einen weiteren Turn an das Model zurück; zwei erfolgreiche Commands machen die Änderung für die Acceptance qualifiziert.
Was das Harness besitzt
OpenAIs Codex Loop Walkthrough beschreibt den grundlegenden Zyklus. Das Harness stellt einen Prompt zusammen, fragt das Model nach der nächsten Aktion, sendet einen akzeptierten Tool Call an die Runtime und hängt das Ergebnis an. Danach fragt es erneut. Dies wiederholt sich, bis das Harness das Ergebnis akzeptiert oder die Kontrolle an den User zurückgibt.
Implementierungen können mehrere Verantwortlichkeiten in einem Prozess zusammenfassen. Die Failure Boundaries bleiben dennoch unterschiedlich:
| Begriff | Aufgabe | Beispiel für einen Coding Agent |
|---|---|---|
| Model | Schlägt Text, einen Tool Call oder eine finale Antwort vor | Schlägt eine Änderung an src/checkout.py vor |
| Reasoning Loop | Wählt aus dem verfügbaren Context den nächsten Schritt | Inspizieren, ändern, testen, erneut inspizieren |
| Harness | Stellt Context bereit, validiert Proposals, autorisiert sie, dispatcht akzeptierte Calls, protokolliert Ergebnisse und prüft den Abschluss | Erlaubt Änderungen unter src/ und verlangt beide benannten Tests |
| Runtime | Führt akzeptierte Calls aus und hält State außerhalb des Worker-Prozesses am Leben | Session-Log, Sandbox, Checkpoint Store, Trace Backend |
Die Runtime-Zeile umfasst vier Dinge: Session, Sandbox, Checkpoint und Trace. Alle vier speichern State oder begrenzen die Execution. Das Model schlägt die Aktion vor, und der Reasoning Loop wählt den nächsten Schritt. Das Harness entscheidet, ob ein vorgeschlagener Call ausgeführt werden darf und ob die Evidenz für den Abschluss ausreicht. Deshalb erhält es einen eigenen Artikel. Teil 5 zählt das Harness neben diesen vier Komponenten als eines von fünf Primitives, die vor dem Shipping platziert werden müssen; dieser Artikel löst es wieder heraus.
Wenn ein Fehler auftritt, diagnostiziere die Boundary, die darauf reagieren sollte. Ein schlechter Plan erfordert möglicherweise bessere Instructions oder besseres Model Reasoning. Wenn edit_file auf einen Pfad außerhalb von src/ zielt, sollte das Harness ihn ablehnen. Ein Sandbox-Prozess, der stirbt, bevor die Änderung ausgeführt wird, gehört zur Runtime; diese muss den Worker neu starten oder den Crash melden.
Wo die früheren Teile einzuordnen sind
Die Harness-Zeile oben übernimmt den größten Teil der Arbeit in dieser Tabelle; dort enden die Teile 2, 3 und 4. Jeder dieser Teile entscheidet eine Sache über einen einzelnen Turn:
| Früherer Teil | Was er für diesen Turn entscheidet | Wo er im Walkthrough des nächsten Abschnitts wirkt |
|---|---|---|
| Teil 2 — Memory | Welcher vorherige State in den Prompt gelangt | Schritt 1, der Context Builder |
| Teil 3 — Tool Use | Welche Aktionen existieren und wie ein validiertes Ergebnis aussieht | Argumentvalidierung in Schritt 3 und Result Shape in Schritt 4 |
| Teil 4 — Security | Ob dieser konkrete Call jetzt ausgeführt werden darf | Schritt 3, Pfadprüfung und Approval-Entscheidung |
| Teil 6 — dieser Artikel | Ob die resultierende Evidenz den Run beendet | Schritte 5 bis 7, Acceptance Checks und Trace |
Die Teile 3 und 4 teilen sich Schritt 3. Genau das ist das Argument dafür, sie als ein Programm zu behandeln. Dieselbe Harness-Code-Schicht, die ein fehlerhaftes Argument ablehnt, lehnt auch einen Call ab, der zwar erlaubt, aber noch nicht genehmigt ist. Wenn Validation und Authorization in getrennten Services laufen, müssen die validierten Argumente über diese Boundary hinweg erhalten bleiben, damit die Authorization-Entscheidung für den Call gilt, der tatsächlich ausgeführt wird.
Für das Debugging bleibt die Trennung wichtig: Eine Änderung an der falschen Datei ist eine Pfadregel aus Teil 4 und kein Retrieval-Problem aus Teil 2. Ein Abschnitt gegen Ende dieses Artikels überführt das in eine Routing-Tabelle.
OpenAIs eigene Fallstudie zu Harness Engineering beschreibt eine bootfähige Anwendungsinstanz für jedes Worktree. Das Team band außerdem Browser-Automation in die Agent-Umgebung ein und stellte Logs, Metriken und Traces bereit.
Eine Aufgabe wie „Kein Span in diesen vier kritischen User Journeys darf zwei Sekunden überschreiten“ wurde testbar, weil der Agent die Anwendung ausführen und dieselben Signals abfragen konnte, die auch ein Engineer untersuchen würde. Die Fallstudie ist produktspezifisch. Übertragbar ist die Bedingung hinter dem Ergebnis: Anwendung und Performance-Signale mussten innerhalb der Agent-Umgebung verfügbar sein.
Lopopolo, der Autor dieser Fallstudie, pflegt einen Field Guide für Harness Engineering. Er benennt die beiden Hebel, die dieser Artikel nutzt: Model und Coding Agent als Black Box unverändert lassen und den Context sowie die Tools darum herum entwickeln. Sein Framing erklärt auch, warum ein so großer Teil des Harness aus gewöhnlichem Code besteht.
Der Qualitätsmaßstab einer Organisation, ihre Verfahren, die Historie von Ausnahmen und ihre Autoritätsbeziehungen liegen außerhalb dessen, was ein General-Purpose Model wissen kann. Das Harness macht sie als Repository Instructions, Permission Rules und Acceptance Checks sichtbar. Jeder akzeptierte Run kann seine Lessons in diese Artefakte zurückführen, statt darauf zu vertrauen, dass die nächste Session sie erneut entdeckt.
Die Rabattänderung von der Proposal bis zur Acceptance verfolgen
Für die oben definierte Rabattaufgabe schlägt das Model vor, calculate_discount in src/checkout.py zu ändern. Bevor diese Änderung als Fortschritt zählt, passiert Folgendes:
- Der Context Builder stellt Task, Repository Instructions, relevante Dateien, frühere Tool Results und den aktuellen Plan bereit.
- Das Model schlägt einen
edit_file-Call mit einem Pfad und Replacement Text vor. - Die Tool Boundary (der Harness-Code zwischen Proposal und Execution) validiert die Argumente, prüft den Pfad gegen den erlaubten Scope und fordert Approval an, wenn die Operation dies benötigt.
- Die Runtime wendet die Änderung in der Sandbox an und gibt ein strukturiertes Result zurück.
- Das Harness führt
pytest tests/test_checkout.pyund anschließendpnpm playwright test tests/checkout_discount.spec.tsaus und liest beide Exit Codes. Der Browser-Test prüft den sichtbaren Rabatt von $8 im initialisierten $80-Warenkorb. - Das Harness entscheidet, was die Results bedeuten. Ein fehlgeschlagener Check wird zum neuen Context für den nächsten Model Turn; ein erfolgreicher Run macht die Aufgabe zu einem Completion Candidate.
- Ein erfolgreiches Result wird erst dann zur Completion Evidence, wenn das Harness Command, Exit Code, getesteten Snapshot, Grader und Environment-Versionen dauerhaft protokolliert hat; ein Trace kann auf diesen Record verweisen.
Nach Schritt 2 wurde noch keine Datei geändert. Das Harness kann ../../secrets.env ablehnen, für einen destruktiven Command Approval verlangen oder einen Run stoppen, der sein Budget ausgeschöpft hat. Das ist der letzte günstige Zeitpunkt. Nach der Ausführung der Tests liest das Harness deren Exit Codes selbst. Das Model kann seine eigene Änderung nicht als erfolgreich markieren.
Das Acceptance Record sollte den getesteten Snapshot, beide Commands und Results sowie die Versionen von Grader und Environment identifizieren; Traces können auf diesen Record verweisen. Halte die erforderlichen Tests außerhalb des schreibbaren Scopes des Agents oder genehmige Änderungen vor dem Grading unabhängig. Jede spätere Dateiänderung macht das Result ungültig. Diese Checks implementieren die Prinzipien der stabilen Umgebung und des Bypass-resistenten Graders aus Anthropics Evaluation Guidance. Eine finale done-Nachricht ohne diese Records beweist nicht, dass diese Änderung ihre erforderlichen Checks bestanden hat.
Entscheiden, wo jede Regel erzwungen wird
Die Anforderung, dass tests/checkout_discount.spec.ts erfolgreich ist, gehört in deterministischen Code und nicht in den Prompt. Das Harness dispatcht den Playwright-Command an die Runtime, liest dessen Exit Code und weigert sich, den Run zu beenden, solange er fehlschlägt. Ein Prompt kann das Model daran erinnern, den Test auszuführen. Er kann das Model jedoch nicht daran hindern, ohne Evidenz Erfolg zu deklarieren.
Andere Regeln passen in andere Schichten:
| Regel platzieren in | Geeignet für | Beispiel |
|---|---|---|
| Prompt oder Skill | Search Order, Coding Conventions und Plan Format | Vor Änderungen am Checkout-Code AGENTS.md lesen |
| Tool Boundary | Argumentvalidierung, erlaubte Pfade, Approvals und Tool Access | Writes nur unter src/ erlauben |
| Deterministischer Code | Budgets, Timeouts, Retries, Test-Exit-Codes und Release-Anforderungen | Run offen halten, solange der Playwright-Test fehlschlägt |
| Evaluator mit frischem Context | Visuelle Prüfung oder Kriterien, die menschenähnliches Urteil erfordern | Ein generiertes Diagramm mit einer schriftlichen Rubrik vergleichen |
Tool Contracts trennen Proposal und Permission
Die Rabattaufgabe benötigt nur Dateiänderungen und Test-Commands. Eine State-verändernde API hat einen anderen Failure Mode, daher wechseln wir für diesen Abschnitt das Beispiel. Angenommen, der Agent kann beim Anlegen von Testdaten create_test_order gegen einen Staging Order Service aufrufen. Dieses Tool gehört nicht zu den Acceptance Checks der Rabattaufgabe. Es ist hier nützlich, weil ein Timeout verbergen kann, ob der Service eine Bestellung angelegt hat.
Die Tool Boundary braucht mehr als eine Beschreibung in natürlicher Sprache. Sie braucht einen expliziten Tool Contract. Teil 3 argumentierte aus Sicht des Models dafür: klare Aktionen, kompakte Rückmeldungen und recoverable Errors. Das Harness benötigt denselben Contract aus einem anderen Grund. Es muss ohne Nachfrage beim Model entscheiden, ob ein Call ausgeführt werden darf und ob ein fehlgeschlagener Call wiederholt werden darf. Für create_test_order bedeutet das einen Contract mit:
- validierten Argumenten, damit fehlerhafte Eingaben vor der Execution abgelehnt werden
- einem strukturierten Result wie
{ "order_id": "123", "created": true }, damit spätere Checks keinen Freitext parsen müssen - einer Effect Category, die festhält, ob der Call nur Informationen abruft oder eine Datei, einen Datenbankeintrag oder einen externen Service verändert. Sie hält außerdem fest, ob eine Wiederholung des Calls sicher ist. Dieses Label teilt dem Harness mit, ob ein automatischer Retry Arbeit duplizieren könnte. Das Harness kann
get_order_statuswiederholen, wenn der Service diesen Lookup als read-only definiert.create_test_orderdarf es nicht blind wiederholen, weil der erste Call die Bestellung bereits angelegt haben könnte - einer Timeout- und Retry-Policy, damit eine verlorene Antwort keine unbegrenzte Sequenz von Calls auslöst
- einer Permission Rule, die festlegt, welches Approval erforderlich ist. Das Lesen des Bestellstatus kann automatisch erfolgen, während das Anlegen einer Bestellung eine Bestätigung erfordern kann
Die Beschreibung in natürlicher Sprache ist Text, der dem Model angezeigt wird. Sie könnte lauten: „Lege eine Testbestellung zur Checkout-Verifizierung an.“ Dieser Satz hilft dem Model bei der Entscheidung, wann es create_test_order vorschlagen sollte. Er autorisiert den Call jedoch nicht. In diesem Beispiel validiert der MCP-Client des Harness die Argumente, wendet eigene Regeln an und prüft Server Trust, Approval-Anforderungen und Retry Safety, bevor irgendetwas dispatcht wird. Damit werden die in Teil 4 besprochenen Permission Rules und Pre-Tool Checks kombiniert, ergänzt um eine Frage: Darf ein bereits fehlgeschlagener Call erneut gesendet werden?
Ein MCP Server veröffentlicht Tool Descriptions und optionale Behavior Annotations für den Client. Ein fehlerhafter oder bösartiger Server könnte ein State-veränderndes Tool als harmlos beschreiben. Ein Client, der diese Aussage automatisch akzeptiert, könnte create_test_order ohne Approval ausführen oder wiederholen und eine Duplikat-Bestellung anlegen. Die MCP-Spezifikation verlangt daher, dass Clients Tool Annotations als nicht vertrauenswürdig behandeln, sofern der Server selbst nicht vertrauenswürdig ist.
Die Spezifikation schreibt keine universelle Trust-Einstellung vor. Deshalb brauchst du für dein Deployment eine explizite Trust Policy; ein Server kann seine eigenen Annotations nicht vertrauenswürdig machen. Diese Policy entscheidet, welche Metadaten Permission- oder Retry-Entscheidungen beeinflussen dürfen und welche Annotations nur beratenden Charakter haben.
Retries für einen State-verändernden Call benötigen Replay Protection
Teil 5 verlangt für Side Effects, die sich bei einem Retry duplizieren können, eine dauerhafte Operation Identity. Das Harness entscheidet, wann dieser Key diese Aufgabe übernehmen muss. create_test_order legt die Bestellung an, aber die HTTP-Antwort geht verloren. Das Harness sieht einen Timeout und kann nicht feststellen, ob der Server die Anfrage abgeschlossen hat. Eine Wiederholung des Calls könnte eine zweite Bestellung anlegen.
Persistiere vor dem Dispatch eine anwendungsseitig verwaltete Operation ID und binde sie an die genehmigten Argumente. Verwende sie bei der Wiederherstellung derselben beabsichtigten Bestellung erneut, selbst wenn das Model eine neue Tool-Call-ID erzeugt; bewahre Model IDs für die Korrelation separat auf. Gleiche geänderte Payloads oder abgelaufene Deduplication Windows des Providers ab, statt sie blind erneut zu senden. Stripes Contract erlaubt beispielsweise das Entfernen von Keys nach mindestens 24 Stunden.
Ein Status-Lookup kann wiederholt werden, wenn der Service ihn als read-only definiert. Ein Creation Call benötigt den Key: Der Client hängt eine eindeutige Request ID an, und der Service gibt beim erneuten Auftreten dieser ID das erste Result zurück, statt eine weitere Bestellung anzulegen. Ohne diesen Schutz sollte das Harness prüfen, ob die Bestellung existiert, oder vor einem weiteren Versuch eine menschliche Entscheidung einholen. AWS dokumentiert dieses Muster in seiner Guidance zu idempotenten APIs.
Acceptance benötigt unabhängige Evidenz
Eine erfolgreiche Antwort von create_test_order belegt nur, dass das Tool Daten zurückgegeben hat. Sie beweist nicht, dass eine Coding-Aufgabe ihre Tests bestanden hat. Wenn ein späterer Browser-Test von der angelegten Bestellung abhängt, muss das Harness das Result-Schema validieren und diesen Test trotzdem ausführen, bevor es die Codeänderung akzeptiert.
Einige Kriterien lassen sich nicht auf einen Exit Code reduzieren. Für eine separate Visual-Design-Aufgabe kann ein Evaluator mit frischem Context eine gerenderte Seite oder ein Diagramm mit einer schriftlichen Rubrik vergleichen — „frischer Context“ bedeutet eine zweite Model Session, die ohne Verlauf des Runs startet und die erzeugten Artefakte statt des Transcripts liest. Vergleiche diesen Evaluator mit menschlichen Reviews, bevor du sein Result darüber entscheiden lässt, ob die Aufgabe abgeschlossen ist.
Eine Migration des Payment Adapters benötigt einen Handoff
Wechseln wir erneut die Aufgabe, bleiben aber im fiktiven Store-Repository. Der Agent muss den Checkout vom Payment Adapter v1 auf v2 migrieren. Die Arbeit umfasst den Checkout Handler, den Payment Client, die Configuration und die Tests und kann daher länger dauern als eine Model Session — ein zusammenhängender Abschnitt des Model Context, der durch einen Restart oder einen bewussten Neustart beendet wird, statt fortgeführt zu werden.
Bevor die erste Session ihr Context Limit erreicht, hat sie mehrere Dateien geändert, eine lokale Payment Sandbox gestartet und tests/payment_migration.spec.ts fehlschlagen lassen. Dieser Browser-Acceptance-Test führt eine Zahlung über Adapter v2 aus und verifiziert die aufgezeichnete Provider ID. Eine Conversation Summary kann die nächste Model Session orientieren, aber sie kann die Sandbox nicht neu starten und nicht belegen, welche Dateien aktuell geändert sind.
Die nächste Session muss drei Dinge wiederherstellen:
| Was wiederhergestellt werden muss | Was es umfasst | Wie es fehlschlagen kann |
|---|---|---|
| Conversation History | Messages, Tool Calls und zurückgegebene Results | Alte Details verdrängen den aktuellen Task |
| Working Environment | Dateien, Payment Sandbox und Browser-Test-State | Das Transcript sagt, ein Service laufe, obwohl er beendet wurde |
| Task Progress | Plan, abgeschlossene Checks, ausstehendes Approval, nächster Schritt | Die nächste Session wiederholt abgeschlossene Arbeit |
Compaction ersetzt ältere Messages durch eine kürzere Summary, damit die aktuelle Session fortgesetzt werden kann. Ein Progress Handoff hält fest, was die nächste Session benötigt: den aktuellen Branch, geänderte Dateien, den letzten Test-Command mit Output und den nächsten ungelösten Schritt.
Eine Handoff-Datei ist Document Memory für die nächste Model Session. Ein Checkpoint kann Plan, abgeschlossene Schritte, Results und verbleibende Arbeit bereits bewahren. Füge einen Handoff hinzu, wenn diese Details im nächsten Context fehlen oder unbrauchbar sind, und verifiziere Dateien sowie laufende Services gegen die Live-Umgebung.
Wenn die alte Conversation veraltete Annahmen enthält, kann das Harness eine neue Model Session mit diesem Handoff und dem aktuellen Workspace starten. Das Ersetzen eines abgestürzten Workers und die Wiederherstellung seiner Prozesse ist eine separate Runtime-Recovery-Aufgabe.
Eine kleine Dokumentationsänderung benötigt möglicherweise keinen dieser Mechanismen. Die Payment-Migration braucht einen Handoff, wenn ihr gespeicherter State keinen nutzbaren Task Progress enthält, weil die nächste Model Session sowohl Workspace als auch Task Status rekonstruieren muss.
Anthropics Experimente mit Long-Running Coding Agents verwendeten Git History und eine Progress-Datei zwischen Sessions. Anthropics späterer Bericht zum Harness Design trennt Compaction von einem Handoff mit frischem Context und berichtet, dass Handoffs zusätzliche Orchestration, Token und Wall Time verursachen, ohne Zahlen zu veröffentlichen, die einen dieser Overheads dem Handoff selbst zuschreiben.
Traces verwenden, um drei Fehler zu unterscheiden
Die nächsten drei Zeilen sind illustrative Trace-Skizzen und keine gemessenen Runs oder Outputs aus dem begleitenden Lab. Jede Zeile zeigt einen anderen Fehler und damit eine andere Harness-Reaktion.
| Was der Trace aufzeichnet | Was passiert ist | Korrekte Reaktion |
|---|---|---|
Der read-only get_order_status-Call gibt 503 zurück; kein State-verändernder Call läuft | Ein transienter Lookup ist fehlgeschlagen | Lookup mit Limit und Backoff wiederholen |
create_test_order läuft in einen Timeout, anschließend findet ein Status-Lookup Bestellung 123 unter Idempotency Key checkout-42 | Der Service hat die Bestellung angelegt, aber die Antwort ging verloren | Existierende Bestellung zurückgeben; keine weitere anlegen |
Änderung und Unit Test sind erfolgreich, aber der Trace enthält für tests/checkout_discount.spec.ts auf dem getesteten Snapshot kein Result | Erforderliche Acceptance Evidence fehlt | Run offen halten und Browser-Acceptance-Test dispatchen |
Ein transient wirkender Fehler macht nicht jeden Call sicher wiederholbar. Die erste Zeile betrifft einen read-only Lookup. Die zweite Zeile betrifft eine State-verändernde Anfrage; daher entscheiden Idempotency Key und serverseitiger Status, ob ein weiterer Creation-Versuch zulässig ist. Die dritte Zeile ist überhaupt kein Tool Failure; das Harness hat die für die Acceptance der Rabattänderung erforderliche Evidenz noch nicht gesammelt.
Ein Chat Transcript hält fest, was das Model gesehen hat. Es kann nicht beweisen, ob der Order Service eine Anfrage committed hat, bevor die Antwort verschwunden ist. Ein Trace kann diese Evidenz nur liefern, wenn er das relevante Server Result oder den Status-Lookup enthält; ein clientseitiger Timeout allein lässt das Result offen. Die dauerhaften Operation- und Acceptance-Records müssen Client Call, Approval-Entscheidung, Operation Identity, Server Result oder Status-Lookup, getesteten Snapshot und Acceptance-Test-Result verknüpfen. Traces können diese Verbindungen für das Debugging sichtbar machen, ohne zum Recovery Ledger zu werden. Anhand dieser Felder erkennt das Harness, auf welchem der drei Pfade es sich befindet.
| Wiederkehrendes Symptom | Kleine zu testende Änderung | Was zu messen ist |
|---|---|---|
| Read-only Lookups schlagen transient fehl | Bounded Retry mit Backoff | Recovery Rate, zusätzliche Calls, Wall Time |
| Resumte Sessions wiederholen abgeschlossene Arbeit | Strukturiertes Progress Handoff | Doppelte Tool Actions nach Resume |
| Erforderliche Tests fehlen beim Abschluss | Completion ablehnen, bis jeder erforderliche Check erfolgreich ist | Ohne alle erforderlichen Checks akzeptierte Tasks |
| Visuelle Fehler überleben deterministische Checks | Evaluator mit frischem Context und Rubrik | Entdeckte Fehler, False Rejections, Review-Zeit |
| Der Agent ändert Dateien außerhalb seines Scopes | Engere Tool Permission | Blockierte Calls und manuelle Overrides |
| Abgerufene Memory verdrängt den aktuellen Task | Abgerufene Fakten begrenzen; vor dem Injizieren ranken | Für Recall verwendete Tokens, abgeschlossene Tasks, Kosten pro Task |
Für optionale Unterstützung wie Planning Aids, Summaries und zusätzliche Evaluators solltest du den Fehler benennen und messen, ob die Komponente ihre Kosten rechtfertigt. Authorization, Isolation, Privacy Requirements und verpflichtende Acceptance Checks bleiben auch dann in Kraft, wenn gewöhnliche Tasks ohne sie erfolgreich sind. Teste diese Constraints mit adversarial Cases und expliziten Invariants; ein kleiner Success-Benchmark kann ihre Entfernung nicht rechtfertigen.
Diese wiederkehrenden Fehler in eine versionierte Regression Suite zu überführen, ist eine eigene Aufgabe. Ich habe sie separat in AI Agent Evaluation in Production beschrieben.
Jeweils nur eine Änderung messen
Eine Ablation misst, ob eine Harness-Komponente den erwarteten Effekt verursacht, indem diese Komponente geändert oder entfernt wird, während der Rest des Experiments konstant bleibt. Hilft beispielsweise Editor Linting diesem Model auf dieser Task Suite?
Verwende das folgende Protokoll:
- Friere Model-Version, Task Instances, Environment, Grader und Prompts außerhalb der getesteten Komponente ein.
- Gib beiden Varianten dasselbe Gesamtbudget für Tokens, Zeit und Geld.
- Lege die Anzahl der Trials oder die Stopping Rule vor dem Vergleich fest.
- Führe in beiden Varianten dieselben Task Instances aus. Da Model Outputs variieren, wiederhole jede Aufgabe mehrmals.
- Berichte den Mittelwert zusammen mit Streuung oder Confidence Interval.
- Zähle jeden gestarteten Trial, einschließlich Timeouts, Policy Stops, Harness Crashes und Evaluator Failures.
Die Success Rate allein kann eine teure Komponente verbergen. Verfolge mindestens als vollständig akzeptierte, aber fehlerhafte Tasks, Kosten und Wall Time pro abgeschlossenem Task, Tool Errors, doppelte Bestellungen, Review-Minuten und manuelle Permission Overrides. Wähle die Metrik, die für dein Produkt die tatsächlichen Kosten abbildet. Ein Anstieg um zwei abgeschlossene Tasks ist ein schlechter Trade-off, wenn sich dadurch deine Review Queue verdoppelt.
Ein gepaartes Payment-Migration-Experiment macht den Progress Handoff messbar. Jedes Control/Treatment-Paar startet beim selben Repository-Commit und mit demselben initialisierten Checkpoint sowie demselben Model, Task, Grader und Gesamtbudget. Der Handoff ist der einzige Schalter. Die primäre Metrik zählt doppelte Tool Actions nach dem Resume: Eine Action ist doppelt, wenn Operation und Artefakt einem Schritt entsprechen, den die vorherige Session bereits abgeschlossen hatte.
Das SWE-agent-Paper verwendet GPT-4 Turbo auf dem 300-Task-Split von SWE-bench Lite als festes Model und berichtet 18,0 % gelöste Tasks mit seinem vollständigen Interface, verglichen mit 11,0 % für einen Shell-only Agent mit Worked Demonstration und 7,3 % für denselben Agent ohne eine solche Demonstration. Die im Paper hervorgehobene Differenz von 10,7 Prozentpunkten wird gegenüber der 7,3-%-Baseline gemessen; Teil 3 leitet dieselben drei Zahlen aus der Perspektive des Interface Designs her. Das Paper änderte außerdem einzelne Interface Features:
| Interface-Änderung | Gelöst |
|---|---|
| Vollständiges SWE-agent Interface (Referenz, unverändert) | 18,0 % |
| Editor ohne Linting | 15,0 % |
| Vollständige Datei statt eines 100-Zeilen-Viewers | 12,7 % |
| Vollständige Observation History statt der letzten fünf | 15,0 % |
Diese Zahlen gehören zu jenem Model, Benchmark und $4-pro-Task-Limit. Die drei Zeilen unterhalb der Referenz sind die nützlichen One-Feature-Tests: In jedem Fall wurde ein Interface Feature geändert, während Model und Evaluation Setup unverändert blieben.
LangChain veröffentlichte einen breiteren Fixed-Model-Vergleich für deepagents-cli. Darin wird für Terminal-Bench 2.0 ein Anstieg von 52,8 % auf 66,5 % berichtet, während gpt-5.2-codex unverändert blieb und das Team System Prompt, Tools und Middleware änderte. Der Post bündelt mehrere Änderungen und enthält weder ein Confidence Interval noch einen Vergleich mit festem Gesamtbudget oder eine Ablation-Tabelle pro Änderung. Das Ergebnis kann daher nicht identifizieren, welche Änderung geholfen hat. Die Model-Namen in diesem Abschnitt sind diejenigen, die jede Studie zum Zeitpunkt ihrer Durchführung eingefroren hatte; Übertragbar ist das Protokoll, nicht die Model-Liste.
Ein neuerer Vergleich zeigt, warum die API-Configuration zur eingefrorenen Baseline gehört. In seinem ARC-AGI-3-Bericht vom 29. Juli 2026 berichtet OpenAI, dass der Public-Set-Score von GPT-5.6 Sol von 13,3 % auf 38,3 % stieg, wenn das Harness Reasoning beibehielt und Compaction verwendete, statt Reasoning zu verwerfen und die History abzuschneiden. Die Metrik ist Relative Human Action Efficiency und nicht der Anteil gelöster Tasks. Dies ist ein vom Vendor berichteter, gebündelter Vergleich; er isoliert die beiden Settings nicht und belegt keine Effect Size in Production. Halte bei einem Upgrade API, Reasoning Retention, Compaction Policy und Budgets zusammen mit der Model ID fest. Andernfalls kann eine scheinbare Model-Regression auf eine fehlende Capability im Adapter zurückgehen.
Nimm Provider Intervention in die Failure Suite auf. Ein misalignment_policy_violation muss auch nach gestreamtem Output einen Stop-and-Review-Pfad erreichen; es ist kein Fall für einen transienten Retry. Teil 4 behandelt seinen API-abhängigen Scope. Teste, dass das Harness den Dispatch stoppt und bereits abgeschlossene Effects protokolliert.
Anthropics Bericht zu Long-Running Applications ist eine qualitative, produktspezifische Fallstudie und kein kontrollierter Benchmark. Die Anwendung heißt RetroForge, ein 2D Retro Game Maker; in Sprint 3 prüfte der Harness Evaluator 27 Kriterien für dessen Level Editor. Die Arbeit begann mit früheren Opus-Modellen. Als Opus 4.6 erschien, entfernte das Team Harness-Komponenten einzeln, um zu sehen, welche davon das neuere Model redundant gemacht hatte. Der Bericht besagt, dass Evaluator Calls auf Tasks, die Opus 4.6 zuverlässig allein erledigen konnte, zum Overhead wurden, an der Grenze des Models aber weiterhin halfen. Das Beispiel ist ein Grund, altes Scaffolding bei einem Model-Wechsel erneut zu validieren; es schätzt keine allgemeine Effect Size.
Das Harness nach seiner Rechtfertigung editierbar halten
Ablation hält ein Harness klein, doch sein Code kann das Model überleben, für das er optimiert wurde. Eine Anforderung wie „Secrets in jedem Capture Path maskieren“ beschreibt ein Verhalten und keine Datei. In einem Production Harness kann sich dieses Verhalten über Execution Stages und Shared State erstrecken. Bevor du es sicher ändern kannst, musst du jede Implementierungsstelle finden — ebenso wie der Coding Agent, dem du diese Aufgabe überträgst.
Eine Option im Research-Stadium ist ein Preprint von Wang et al. aus dem Jahr 2026, das Harness Handbook. Es bezeichnet diese Suche als Behavior Localization. Das Handbook erstellt eine verhaltensorientierte Map der Harness-Codebase. Statische Analyse, die keine Model Calls benötigt, extrahiert einen Program Graph; anschließend organisiert ein LLM dessen Units in Execution Stages.
Der Maintainer oder Coding Agent beginnt mit einem System Overview, öffnet die relevante Execution Stage und steigt zu Source-grounded Entries für eine Function oder Datei hinab. Ein State Register hält fest, wo Shared State zwischen Stages geschrieben und gelesen wird. Diese Hierarchie hält den Overview klein und bewahrt zugleich einen Pfad zur Source.
Freshness ist eine separate Regel. Die Map ist eine Navigationshilfe; Live Source definiert das Verhalten. Jeder Locator muss sich gegen das Live Repository auflösen lassen. Das Handbook friert veraltete Entries ein, statt zu raten, und jeder nichtleere Diff synchronisiert die betroffenen Entries neu.
Das Diagramm komprimiert den Modification Loop: Eine reine Behavior-Request steigt durch die Ebenen des Handbooks ab, jeder mögliche Locator wird vor dem Schreiben des Plans gegen das Live Repository verifiziert, und jeder angewendete Diff synchronisiert die Map neu.
Die Handbook Evaluation vergleicht gematchte Arme mit jeweils 30 Requests pro Repository. Sie belegt weder gleiche Gesamtbudgets noch wiederholte stochastische Trials oder Unsicherheitsabschätzungen; außerdem schließen die berichteten Vergleiche fehlende Outputs und Planner Errors aus. Sie illustriert daher nur einen Teil des oben beschriebenen Protokolls. Sie umfasst zwei Open-Source-Harnesses: Terminus-2 (sechs Python-Dateien) und das Codex Monorepo (2.267 Rust-Dateien). In beiden Fällen untersuchte ein read-only Planner, betrieben mit DeepSeek-V4-Pro, das Repository entweder direkt oder über das Handbook. Requests, Repository, Tool Permissions und Decoding waren in beiden Armen identisch. Drei Judges (GPT-5.5, Opus 4.8, DeepSeek-V4-Pro) bewerteten jeden Edit Plan nach Localization, Scope Control und Reasoning — wobei zu beachten ist, dass einer der Judges dasselbe Model ist, das die Pläne erzeugt hat. Ein Win bedeutet, dass der Quality Score eines Arms auf einer Skala von 0 bis 100 den anderen um mindestens drei Punkte übertraf; andernfalls galt der Vergleich zwischen Judge und Request als Tie. Die berichtete Rate ist die Anzahl der Wins geteilt durch die Zahl gültiger Judge-Request-Vergleiche:
| Harness | Win Rate der Baseline | Win Rate mit Handbook | Planner Tokens |
|---|---|---|---|
| Terminus-2 (6 Dateien) | 26,7 % | 45,6 % | −8,6 % |
| Codex Monorepo (2.267 Dateien) | 28,3 % | 38,3 % | −12,7 % |
Der Handbook-unterstützte Planner gewann in beiden Repositories häufiger und verwendete weniger Planner Tokens. Diese Bedingungen gehören zum Ergebnis: Drei LLM Judges bewerteten Edit Plans, die ein Planner Model für zwei Harnesses erzeugt hatte. Die Studie evaluierte Pläne und keine ausgeführten Diffs oder Defect Rates in Production.
Die Methode im begleitenden Lab ausprobieren
Das harness-demo-Projekt bei Commit 517353f3 ist eine kleine deterministische Übung mit 12 generischen synthetischen Tasks, die Codeänderungen wie fix-parser-edge-case, split-large-module und wire-browser-test abdecken. Das Projekt implementiert nicht das fiktive Store-Repository.
Jedes Task-Fixture definiert eine Difficulty sowie vier boolesche Bedingungen: ein flaky Tool, verlorener Progress, eine übersehene Implementierungslücke und mehrdeutiger Abschluss. Der Simulator leitet für schwierige Tasks, die außerdem eine Progress-Datei benötigen, eine fünfte Bedingung ab: Ohne context_reset bewahrt Compaction veraltete Annahmen. Ein deterministischer Grader markiert einen Task nur dann als bestanden, wenn die ausgewählte Configuration jede zutreffende Bedingung behandelt. Es läuft kein Model und kein externer Service.
Die Commands beantworten unterschiedliche Fragen:
make checkführt Ruff und sieben Unit Tests aus, einschließlich des Validators, der jedes Ablation-Paar ablehnt, das mehr als eine Komponente ändert.make rungibt eine kumulative Teaching Matrix und anschließend fünf gültige Leave-One-Component-Out-Vergleiche aus.make failuresnennt für jeden fehlgeschlagenen Task die nicht behandelte Bedingung. Das vollständige Harness sollte mitall synthetic tasks passenden.
make check
make run
make failures
Der kausale Abschnitt von make run sieht so aus:
component control treatment delta
retry_policy 8/12 12/12 +4
progress_handoff 7/12 12/12 +5
evaluator 8/12 12/12 +4
fail_closed_acceptance 7/12 12/12 +5
context_reset 10/12 12/12 +2
Für jede Zeile ist das Control die vollständige Configuration mit einer entfernten Komponente; das Treatment stellt nur diese Komponente wieder her. Die frühere kumulative Matrix ist zur Orientierung nützlich, aber einige ihrer benachbarten Zeilen fügen mehrere Komponenten gleichzeitig hinzu und können daher keine Ursache identifizieren.
Das Lab validiert jedes deklarierte Paar, bevor es ausgeführt wird. Seine Regressionstests enthalten außerdem absichtlich ein ungültiges Paar, das Retry Policy und Evaluator gemeinsam ändert; der Validator weist es zurück.
Das Lab vergleicht bei der Validierung eines Paars alle fünf Component Fields. Dieser ausführbare Auszug zeigt denselben Guard an einem gültigen Progress-Handoff-Paar:
from dataclasses import dataclass, fields
@dataclass(frozen=True)
class Config:
progress_handoff: bool = False
evaluator: bool = False
retry_policy: bool = False
fail_closed_acceptance: bool = False
context_reset: bool = False
def changed_components(control: Config, treatment: Config) -> tuple[str, ...]:
return tuple(
field.name
for field in fields(control)
if getattr(control, field.name) != getattr(treatment, field.name)
)
control = Config(progress_handoff=False, evaluator=True, retry_policy=True)
treatment = Config(progress_handoff=True, evaluator=True, retry_policy=True)
assert changed_components(control, treatment) == ("progress_handoff",)
Welche Schicht bei einem fehlerhaften Run zu öffnen ist
Die Serie verlief vom Reasoning Loop nach außen. Beginne mit dem ersten Fehler, den du siehst, und untersuche anschließend die Komponente, die für diese Aufgabe zuständig ist. Ein Run kann mehr als eine Komponente betreffen:
| Was der Run getan hat | Wo die Korrektur liegt | Teil |
|---|---|---|
| Mit den richtigen Informationen vor sich den falschen nächsten Schritt gewählt | Reasoning Loop oder Model | 1 |
| Arbeit wiederholt oder eine vor einer Stunde getroffene Entscheidung verloren | Context Assembly und Handoffs | 2 |
| Die benötigte Aktion nicht ausdrücken können oder ein zurückgegebenes Result falsch interpretiert | Tool Contract | 3 |
| Etwas getan, das er niemals hätte tun dürfen | Permission Rules | 4 |
| Bei einem Worker-Tod mitten im Call alles verloren | Session, Checkpoint, Sandbox | 5 |
| Den Erfolg einer nicht erledigten Arbeit deklariert | Acceptance Checks und Traces | 6 |
Vier Zeilen verweisen auf Harness Code, Zeile 5 dagegen auf die Runtime. Instructions können das Verhalten beeinflussen, aber keine Permission Check, keinen dauerhaften Checkpoint und keinen Acceptance Test ersetzen.
Mit einem Loop und einem Acceptance Check beginnen
Ich würde ein Coding-Agent-Harness mit einem leistungsfähigen Model, Repository Instructions, einigen engen Tools, einer Sandbox und einem expliziten Acceptance Test beginnen. Ich würde Tool Calls, Results, Kosten und diesen finalen Test in einem Trace protokollieren, damit die ersten nützlichen Fehler sichtbar sind, ohne sie aus Terminal Logs und Chat Transcripts rekonstruieren zu müssen. Das ist eine vorgeschlagene Baseline und keine Evidenz aus einem deployed System.
Füge von dort aus nur hinzu, was ein Trace rechtfertigt. Halte fest, wer jede Komponente pflegt, wie viele Tokens oder Sekunden sie hinzufügt und welcher Regression Test ihre Entfernung nach einem Model Upgrade rechtfertigen würde.
Sechs Monate später sollte jemand, der progress_handoff=True sieht, die fehlgeschlagenen Traces finden können, die sie gerechtfertigt haben, sowie die Regression Cases, die sie weiterhin erforderlich machen. Die Traces erklären, warum die Komponente existiert; eine aktuelle Behavior Map erklärt, wo sie geändert werden muss.
Wenn du über eine Suche hierher gelangt bist, haben die fünf vorherigen Artikel ein System rund um einen Reasoning Loop aufgebaut:
- Der Loop wählt den nächsten Schritt.
- Memory stellt Context bereit, und ein echter Postgres Checkpoint Store bewahrt ihn.
- Tool Contracts definieren Aktionen und Result Shapes, die spätere Checks lesen können.
- Security ergänzt den Deny Hook und den Stop-Hook-Validator. Beide bleiben im Beispiel Skizzen, markieren aber die Control Points.
- Die Runtime hält den Prozess über Sessions und Fehler hinweg am Leben.
Die Serie ergänzte außerdem eine optionale MCP Server Surface und einen Evaluator Node, der den Draft Report prüft, bevor ein Mensch ihn sieht. Das Routing des Workers über einen Credential-haltenden Proxy bleibt eine vorgeschlagene Erweiterung. Dies sind gewöhnliche Code-Bausteine rund um einen Model Call. Der Router ist aus demselben Grund Harness Code: Er wählt das Reasoning Pattern, bevor der Reasoning Loop beginnt.
Für die nächste optionale Assistance-Komponente solltest du den fehlgeschlagenen Trace, die Acceptance Rule und den Vergleich mit deaktivierter Komponente gemeinsam aufbewahren. Lass sie weg, wenn du ihren Nutzen nicht identifizieren kannst. Erforderliche Security- und Acceptance-Constraints hängen nicht von diesem Vergleich ab.
Referenzen
- OpenAI, Unrolling the Codex Agent Loop.
- OpenAI, Harness Engineering: Leveraging Codex in an Agent-First World.
- Lopopolo, Harness Engineering: Anthology, Field Guide, and Agent Context Bundle.
- Anthropic Engineering, Effective Harnesses for Long-Running Agents.
- Anthropic Engineering, Harness Design for Long-Running Application Development.
- LangChain, Improving Deep Agents with Harness Engineering.
- Yang et al., SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering.
- Wang et al., Harness Handbook: Making Evolving Agent Harnesses Readable, Navigable, and Editable, arXiv:2607.13285, 2026.
- AWS, Making Retries Safe with Idempotent APIs.
- Model Context Protocol, Tools Specification.
- Market Analyst Agent Repository
Der Code des Market Analyst Agent befindet sich auf GitHub.