Tips & Tricks (Aktualisiert: 21.7.2026)

Harness Engineering: Codex-Beispiel und sichere Umsetzung für Einsteiger

Harness Engineering erklärt: Codex-Fallstudie, klare Rollen, sichere Dateigrenzen und ausführbare Node.js-Tests.

Harness Engineering: Codex-Beispiel und sichere Umsetzung für Einsteiger

Ein KI-Agent soll ein Repository aufräumen und ändert dabei eine Konfigurationsdatei, die gar nicht zum Auftrag gehört. Oder er meldet „Tests bestanden“, ohne einen nachvollziehbaren Testlauf zu hinterlassen. Wer zum ersten Mal Arbeit an Claude Code, Codex oder einen anderen Coding-Agenten delegiert, stößt schnell auf solche Situationen.

Das Problem liegt nicht nur im Prompt. Oft fehlen klare Grenzen: Welche Dateien darf der Agent lesen? Welche Werkzeuge darf er einsetzen? Wann muss er anhalten? Und welcher überprüfbare Beleg zählt als erledigte Arbeit? Harness Engineering gestaltet dieses Umfeld. Ein Harness ist das Arbeitsgerüst, das einem Agenten Orientierung gibt, riskante Aktionen begrenzt und Ergebnisse prüfbar macht.

Dieser Leitfaden ordnet den Begriff anhand der veröffentlichten Codex-Fallstudie von OpenAI ein. Anschließend bauen wir ein kleines Beispiel, das Dateizugriffe begrenzt, Überschreiben verhindert und die wichtigsten Regeln ohne kostenpflichtigen API-Aufruf testet.

Das Wichtigste in Kürze

  • Ein Harness ist kein einzelnes Wrapper-Skript. Es verbindet Repository-Wissen, Werkzeuge, Berechtigungen, Tests, Protokolle, Wiederherstellung und menschliche Freigaben.
  • OpenAI machte für Codex sowohl die Struktur des Repositorys als auch die Anwendung und ihre Qualitätsregeln direkt lesbar und maschinell prüfbar.
  • Agenten eignen sich für Suche, Entwürfe und wiederholbare Arbeit. Löschen, Produktionsänderungen, externe Kommunikation und Ausgaben bleiben zunächst menschliche Entscheidungen.
  • Eine reine Prüfung des Pfadpräfixes ist keine vollständige Sandbox. Symlinks, Überschreiben, Prozessrechte und die Isolation durch das Betriebssystem müssen ebenfalls berücksichtigt werden.
  • „Getestet“ ist nur dann aussagekräftig, wenn Befehl, Ergebnis und Prüfumfang genannt werden.

Was Harness Engineering konkret bedeutet

Ein Prompt beschreibt, was in einem einzelnen Lauf erreicht werden soll. Das Harness bestimmt, unter welchen Bedingungen dieser Auftrag ausgeführt wird.

EbeneLeitfrageKleines Beispiel
KontextWas darf der Agent wissen?AGENTS.md, ein begrenztes Verzeichnis, eine versionierte Spezifikation
WerkzeugeWas darf er tun?Lesen, testen und einen Entwurf anlegen
BerechtigungenWo muss er stoppen?Freigabe vor Löschen oder Versenden
VerifikationWann ist die Aufgabe erledigt?npm test endet mit Status 0
BeobachtbarkeitWie lässt sich ein Fehler nachvollziehen?Befehl, Diff und relevante Fehlermeldung
WiederherstellungWie wird ein schlechter Lauf zurückgenommen?Kleine Commits, Dry-Runs und Rollback-Schritte

Das Modell ist nur ein Teil dieses Kreislaufs:

Ziel und Freigaberegeln des Menschen
              ↓
Repository-Regeln → KI-Agent → erlaubte Werkzeuge
       ↑                ↓
Spezifikationen     Tests, Logs und Diffs
       └── bei Fehlern nachbessern, bei Ermessensfragen eskalieren ──┘

Ein leistungsfähigeres Modell kann keine interne Designentscheidung erkennen, die nur im Kopf eines Kollegen steckt. Umgekehrt arbeitet dasselbe Modell verlässlicher, wenn relevante Informationen auffindbar und Abnahmekriterien ausführbar sind.

Warum der Begriff 2026 so viel Aufmerksamkeit bekam

Eine wichtige Grundlage der aktuellen Diskussion ist der OpenAI-Beitrag Harness engineering: leveraging Codex in an agent-first world, veröffentlicht am 11. Februar 2026.

OpenAI berichtet dort über ein Experiment, bei dem zunächst ein leeres Git-Repository verwendet wurde. In ungefähr fünf Monaten eröffneten und mergten drei Ingenieure mithilfe von Codex rund 1.500 Pull Requests. Laut dem Beitrag umfasste das Repository zu diesem Zeitpunkt ungefähr eine Million Codezeilen; der interne Produkt-Beta-Betrieb hatte tägliche Nutzer und externe Alpha-Tester. Diese Zahlen stammen aus der Fallstudie und sind kein allgemeines Leistungsversprechen für andere Teams.

Entscheidend ist nicht die Zahl der Pull Requests, sondern der Umbau des Arbeitsumfelds. Die Menschen steuerten Ziele und Abnahmekriterien, während Codex die Umsetzung übernahm. OpenAI beschreibt unter anderem diese Maßnahmen:

  • Pläne, Architekturentscheidungen und Qualitätswissen liegen als versionierte Artefakte im Repository.
  • AGENTS.md dient als kurze Karte zu vertiefenden Quellen, nicht als riesiges Handbuch.
  • Benutzeroberfläche, Logs, Metriken und Traces sind für den Agenten direkt untersuchbar.
  • Abhängigkeitsrichtungen, Benennungen und andere Invarianten werden mit eigenen Lintern und Strukturtests erzwungen.
  • Ein Fehlschlag gilt als Hinweis auf ein fehlendes Werkzeug, eine unklare Regel oder eine ungeeignete Abstraktion; „Versuch es noch einmal“ ist keine systematische Lösung.
  • Wiederkehrende Aufräumläufe suchen nach veralteter Dokumentation und struktureller Abweichung.

OpenAI weist zugleich darauf hin, dass dieses Verhalten stark von der eigens aufgebauten Repository-Struktur und den Werkzeugen abhängt. Man darf die dort erreichte Autonomie nicht ohne vergleichbare Investitionen auf jedes Projekt übertragen.

Für Claude Code gilt dasselbe Grundprinzip. Die offizielle Dokumentation zu Hooks im Claude Agent SDK zeigt beispielsweise, wie eine Werkzeuganfrage geprüft, abgelehnt, verändert oder protokolliert werden kann. Die Oberfläche ist je nach Produkt anders; die Aufgabe des Harness bleibt gleich: Grenzen und eine Rückkopplungsschleife schaffen.

Was der Agent übernimmt und was ein Mensch entscheidet

Beginnen Sie nicht mit vollständiger Autonomie. Automatisieren Sie zuerst reversible Aufgaben und fordern Sie eine Freigabe, sobald Kunden, Geld, sensible Daten oder die Produktion betroffen sind.

Gut für den EinstiegNur unter Bedingungen delegierenMenschliche Entscheidung behalten
Dateien durchsuchenBestehende Dateien bearbeitenProduktionsdaten löschen
Tests ausführenEine Abhängigkeit hinzufügenEine Kundenmail absenden
Einen Diff zusammenfassenAuf Staging deployenAbrechnung oder Verträge ändern
Einen Entwurf erstellenEinen Branch pushenSensible personenbezogene Daten verarbeiten

Zwei Fragen helfen bei der Einordnung: Lässt sich der Vorgang günstig rückgängig machen? Kann er jemanden außerhalb des Teams betreffen? Starten Sie mit Lesezugriff und temporären Ausgaben. Erst wenn erfolgreiche und fehlgeschlagene Fälle sichtbar sind, wird eine eng umrissene Aktion automatisch freigegeben.

Ein minimales Harness bauen

Das Beispiel stellt dem Modell nur zwei Fähigkeiten bereit:

  1. Textdateien innerhalb von sandbox lesen;
  2. eine neue Textdatei innerhalb von sandbox anlegen.

Es gibt kein Werkzeug zum Löschen, Überschreiben, Ausführen einer Shell oder Zugreifen auf das Netzwerk. Das Beispiel wurde mit Node.js 22 geprüft. Die SDK-Version entspricht dem Stand der hier dokumentierten Prüfung.

mkdir harness-demo
cd harness-demo
npm init -y
npm install @anthropic-ai/[email protected]
mkdir sandbox
echo "# meeting notes" > sandbox/note.md

Legen Sie policy.json an:

{
  "workspace": "./sandbox",
  "maxSteps": 6,
  "maxToolResultChars": 4000
}

1. Die Dateigrenze im Code erzwingen

Erstellen Sie safe-files.mjs. Eine Prüfung wie candidate.startsWith(root) reicht allein nicht aus: Ein ähnlich benanntes Verzeichnis kann ebenfalls passen, und ein Symlink innerhalb des Arbeitsbereichs kann auf ein Ziel außerhalb zeigen. Der folgende Leseweg prüft deshalb den aufgelösten Zielpfad. Schreibzugriffe sind auf neue Dateien beschränkt.

import { open, readFile, realpath } from "node:fs/promises";
import path from "node:path";

function assertInside(root, candidate) {
  if (candidate !== root && !candidate.startsWith(root + path.sep)) {
    throw new Error(`outside workspace: ${candidate}`);
  }
}

export async function createFileGate(workspace) {
  const root = await realpath(path.resolve(workspace));

  async function readText(relativePath) {
    const requested = path.resolve(root, relativePath);
    assertInside(root, requested);
    const actual = await realpath(requested);
    assertInside(root, actual);
    return readFile(actual, "utf8");
  }

  async function createText(relativePath, content) {
    const requested = path.resolve(root, relativePath);
    assertInside(root, requested);
    const actualParent = await realpath(path.dirname(requested));
    assertInside(root, actualParent);

    let handle;
    try {
      handle = await open(requested, "wx", 0o600);
      await handle.writeFile(content, "utf8");
    } catch (error) {
      if (error.code === "EEXIST") {
        throw new Error(`refusing to overwrite: ${relativePath}`);
      }
      throw error;
    } finally {
      await handle?.close();
    }
    return "created";
  }

  return { readText, createText };
}

Dies ist eine Schutzschicht der Anwendung, keine vollständige Sicherheitsgrenze. Wenn stärkere Isolation nötig ist, verwenden Sie zusätzlich einen Container, eine virtuelle Maschine, Betriebssystemrechte oder die Sandbox des jeweiligen Produkts. Eine Anwendungskontrolle hebt weitreichende Prozessrechte nicht auf.

2. Dem Modell nur zwei Werkzeuge anbieten

Erstellen Sie agent.mjs. Der Modellname wird bewusst über ANTHROPIC_MODEL gesetzt und nicht im Artikel festgeschrieben, weil sich Kontozugriff und Modellverfügbarkeit ändern können.

import Anthropic from "@anthropic-ai/sdk";
import { readFile } from "node:fs/promises";
import { createFileGate } from "./safe-files.mjs";

const model = process.env.ANTHROPIC_MODEL;
if (!model) throw new Error("Set ANTHROPIC_MODEL to a model available to your account.");

const policy = JSON.parse(await readFile("./policy.json", "utf8"));
const gate = await createFileGate(policy.workspace);
const client = new Anthropic();

const tools = [
  {
    name: "read_file",
    description: "Read a UTF-8 text file inside the workspace",
    input_schema: {
      type: "object",
      properties: { path: { type: "string" } },
      required: ["path"],
      additionalProperties: false
    }
  },
  {
    name: "create_file",
    description: "Create a new UTF-8 file; existing files cannot be overwritten",
    input_schema: {
      type: "object",
      properties: {
        path: { type: "string" },
        content: { type: "string" }
      },
      required: ["path", "content"],
      additionalProperties: false
    }
  }
];

async function runTool(name, input) {
  if (name === "read_file") return gate.readText(input.path);
  if (name === "create_file") return gate.createText(input.path, input.content);
  throw new Error(`unknown tool: ${name}`);
}

const prompt = process.argv.slice(2).join(" ") ||
  "Read note.md and create summary.md with a three-line summary.";
const messages = [{ role: "user", content: prompt }];

for (let step = 0; step < policy.maxSteps; step += 1) {
  const response = await client.messages.create({
    model,
    max_tokens: 1200,
    system: "Use only the supplied tools. Never claim a file was created unless the tool succeeded.",
    tools,
    messages
  });
  messages.push({ role: "assistant", content: response.content });

  const calls = response.content.filter((block) => block.type === "tool_use");
  if (calls.length === 0) {
    console.log(response.content.find((block) => block.type === "text")?.text ?? "done");
    process.exit(0);
  }

  const results = [];
  for (const call of calls) {
    try {
      const value = await runTool(call.name, call.input);
      results.push({
        type: "tool_result",
        tool_use_id: call.id,
        content: String(value).slice(0, policy.maxToolResultChars)
      });
    } catch (error) {
      results.push({
        type: "tool_result",
        tool_use_id: call.id,
        is_error: true,
        content: error.message
      });
    }
  }
  messages.push({ role: "user", content: results });
}

throw new Error(`step limit exceeded: ${policy.maxSteps}`);

3. Die Schutzschicht vor dem Modellaufruf testen

Die kritische Grenze lässt sich lokal und ohne API-Kosten prüfen. Erstellen Sie safe-files.test.mjs:

import assert from "node:assert/strict";
import test from "node:test";
import { mkdtemp, mkdir, rm, symlink, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { createFileGate } from "./safe-files.mjs";

test("file gate blocks traversal, overwrite, and outside symlinks", async () => {
  const base = await mkdtemp(path.join(tmpdir(), "harness-test-"));
  const root = path.join(base, "sandbox");
  const outside = path.join(base, "outside.txt");

  try {
    await mkdir(root);
    await writeFile(path.join(root, "note.md"), "hello", "utf8");
    await writeFile(outside, "secret", "utf8");
    const gate = await createFileGate(root);

    assert.equal(await gate.readText("note.md"), "hello");
    await assert.rejects(() => gate.readText("../outside.txt"), /outside workspace/);
    await assert.rejects(() => gate.createText("note.md", "replace"), /refusing to overwrite/);

    try {
      await symlink(outside, path.join(root, "outside-link.txt"), "file");
      await assert.rejects(() => gate.readText("outside-link.txt"), /outside workspace/);
    } catch (error) {
      if (error.code !== "EPERM") throw error;
    }

    assert.equal(await gate.createText("summary.md", "safe"), "created");
  } finally {
    await rm(base, { recursive: true, force: true });
  }
});

Führen Sie die Offline-Prüfungen aus:

node --test safe-files.test.mjs
node --check agent.mjs

Erst danach setzen Sie ANTHROPIC_API_KEY und ANTHROPIC_MODEL und führen node agent.mjs aus. Zugangsdaten gehören weder in die Versionsverwaltung noch in policy.json.

Drei praktische Use Cases

1. Softwareentwicklung: einen Pull Request umsetzen und prüfen

Der Agent erhält ein klar abgegrenztes Issue, die relevanten Verzeichnisse und die Testbefehle. „Code wurde geschrieben“ ist kein Abnahmekriterium. Verlangen Sie eine zunächst fehlschlagende Reproduktion, einen erfolgreichen Test nach der Korrektur und einen verständlichen Diff. Produktionsdeployment und Migrationen bleiben freigabepflichtig.

2. Medienbetrieb: einen Artikel vor der Veröffentlichung prüfen

Trennen Sie die Texterstellung von Prüfungen auf doppelte Themen, ausreichende Tiefe, Codesyntax, Links und mobile Darstellung. Eine fehlgeschlagene Prüfung stoppt die Veröffentlichung und liefert eine konkrete Fehlermeldung zurück. So wird aus „der Text wirkt fertig“ ein reproduzierbarer Freigabeprozess.

3. Kundenservice: Anfrage klassifizieren und Antwort entwerfen

Der Agent darf eine Anfrage einordnen und einen begründeten Antwortentwurf erstellen. Änderungen am Kundendatensatz und der tatsächliche Versand brauchen menschliche Zustimmung. Übergeben Sie nur die für die Klassifikation nötigen personenbezogenen Daten und speichern Sie vollständige Nachrichten nicht unnötig in langlebigen Logs.

ROI ohne Wunschdenken berechnen

Messen Sie gesparte Prüfzeit und weniger Nacharbeit, nicht erzeugte Tokens. Angenommen, ein Team prüft 15 Aufgaben pro Woche jeweils 20 Minuten lang. Das sind fünf Stunden. Kostet der Aufbau des Harness sechs Stunden und sinkt die laufende Pflege auf eine Stunde pro Woche, ist der anfängliche Aufwand rechnerisch nach ungefähr eineinhalb Wochen wieder eingespielt.

Das ist nur ein Rechenbeispiel, kein versprochenes Ergebnis. Erfassen Sie zwei Wochen vor und nach der Einführung:

  • menschliche Minuten pro Aufgabe;
  • Anteil der Aufgaben mit Nacharbeit;
  • vor der Produktion gefundene Fehler;
  • Anzahl der Eskalationen zur menschlichen Freigabe.

Zu viele Freigabeanfragen können bedeuten, dass eine nachweislich risikoarme Aktion enger definiert und automatisiert werden kann. Mehr Fehler oder Nacharbeit bedeuten dagegen: eine weitere Prüfung oder klarerer Kontext fehlt. Sie sind kein Argument für breitere Autonomie.

Pitfalls und passende Korrekturen

Einen Ordnernamen mit einer Sandbox verwechseln

Ein Pfad kann wie ein Ziel im Arbeitsbereich aussehen, obwohl ein Symlink nach außen führt. Lösen Sie Ziele auf, verhindern Sie Überschreiben und setzen Sie Betriebssystemrechte als zweite Grenze ein.

Nur „keine gefährlichen Aktionen“ in den Prompt schreiben

Text gibt Orientierung, erzwingt aber keine Grenze. Ein gefährliches Werkzeug sollte gar nicht angeboten oder durch einen Hook vor dem Einsatz abgelehnt werden. Der Leitfaden zu Claude-Code-Berechtigungen zeigt eine konkrete Konfiguration.

Die Meldung „Tests bestanden“ als Beleg akzeptieren

Protokollieren Sie Befehl, Exit-Code und Prüfumfang. Änderungen an einer Oberfläche benötigen zusätzlich einen tatsächlich durchlaufenen Bedienpfad oder einen Screenshot. Der Workflow für Verifikationsbelege zeigt, wie sich diese Nachweise festhalten lassen.

Jedes Dokument in jeden Lauf laden

Ein sehr langer Kontext kann genau die wichtige Regel verdecken. Geben Sie dem Agenten einen kurzen Einstieg mit Links zu fokussierten, versionierten Quellen. Kennzeichnen Sie Aktualität und Prüfstatus, damit veraltete Dokumentation auffällt.

Fazit

Harness Engineering bedeutet nicht, immer längere Prompts zu verfassen. Es macht relevantes Wissen auffindbar, begrenzt Werkzeuge, sperrt sensible Aktionen, bewertet Ergebnisse mit ausführbaren Prüfungen und übersetzt Fehler in bessere Regeln und Tests.

Wählen Sie für den Einstieg einen einzigen Arbeitsablauf und notieren Sie vier Punkte: Eingabe, erlaubte Aktionen, Abnahmebefehl und Aktionen mit menschlicher Freigabe. Teams, die Berechtigungen, Verifikation und Review-Grenzen in einem echten Repository einführen möchten, können diese Schritte in der Claude-Code-Schulung und Einführungsberatung auf ihren eigenen Ablauf übertragen.

Tatsächlich durchgeführte Prüfung

Am 21. Juli 2026 wurden die Blöcke safe-files.mjs und safe-files.test.mjs aus diesem Artikel in ein temporäres Verzeichnis extrahiert und mit Node.js ausgeführt. Die Test-Fixture prüft normales Lesen, das Anlegen einer neuen Datei, die Ablehnung von ../-Pfadüberschreitung und die Ablehnung des Überschreibens. Auf Systemen, auf denen der Testprozess Symlinks anlegen darf, wird außerdem ein nach außen zeigender Symlink abgelehnt. Für agent.mjs wurde die Syntax geprüft.

Ein Live-Aufruf der Anthropic API gehört nicht zu diesem Prüfumfang, weil Modellzugriff und Kosten vom jeweiligen Konto abhängen. Diese Einschränkung ist beabsichtigt: „veröffentlicht“, „syntaktisch geprüft“, „offline getestet“ und „gegen eine kostenpflichtige externe API ausgeführt“ sind unterschiedliche Aussagen.

#claude-code #codex #harness-engineering #ki-agenten #einsteiger
Kostenlos

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.