Harness Engineering: Der vollständige Leitfaden zum Bau von KI-Agenten nach Claude-Code-Vorbild
Mit Prompts allein beherrscht man kein LLM. Lerne, wie Werkzeuge, Kontext und Kontrollschleifen zu einem Harness verwoben werden – mit lauffähigem Code und Claude Codes eigener Architektur.
Die Ära des „einfach einen Prompt an ChatGPT werfen” ist vorbei. Seit 2025 verlagert sich der Schwerpunkt der KI-Entwicklung rasant hin zum Harness Engineering. In den internen Blogs von Anthropic und in der Agenten-Forschung von OpenAI gehört der Begriff zu den am häufigsten genannten.
Doch fragt man jemanden „Was ist ein Harness?”, bleibt die Antwort meist vage. Dieser Artikel seziert Harness Engineering anhand von lauffähigem Code und der Architektur von Claude Code selbst. Am Ende hast du alles, um deinen eigenen Agenten von Grund auf zu bauen.
Ein Harness ist das „Gerüst” rund um die KI
„Harness” heißt ursprünglich Pferdegeschirr oder Sicherheitsgurt. In der Softwarewelt denken wir an das Testharness: die äußere Konstruktion, die etwas überhaupt zum Laufen bringt.
Im KI-Kontext ist ein Harness die Wrapper-Schicht um ein LLM. Konkret bündelt sie alles, was das Modell für reale Aufgaben braucht:
- Werkzeuge: Dateien lesen, Kommandos ausführen, APIs aufrufen
- Kontextmanagement: Was merken, was vergessen, was komprimieren?
- Kontrollschleife: Wann aufrufen, wann stoppen, wann erneut versuchen?
- Berechtigungen und Sicherungen: damit destruktive Aktionen nicht ungefragt laufen
- Gedächtnis: Wissen, das sitzungsübergreifend bleibt
Der Prompt ist nur ein Input in dieses Harness. Ist das Harness schwach, stößt selbst der klügste Prompt an eine Leistungsgrenze. Genau deshalb heißt es: „Prompt Engineering allein reicht nicht mehr.”
Warum der Harness entscheidend ist: die OODA-Schleife
Ein LLM allein kann nur „den nächsten Token erzeugen”. Reale Aufgaben verlangen eine OODA-Schleife (Observe → Orient → Decide → Act) aus der Militärstrategie.
| Phase | Inhalt | Zuständig |
|---|---|---|
| Observe (Beobachten) | Umgebung lesen (Dateien, DB-Abfragen) | Harness |
| Orient (Einordnen) | Informationen aufbereiten und dem LLM geben | Harness |
| Decide (Entscheiden) | Nächsten Schritt wählen | LLM |
| Act (Handeln) | Ausführen (Kommandos, API-Calls) | Harness |
Wie man sieht, liegen drei von vier Phasen beim Harness. Das LLM glänzt nur beim Entscheiden. Die Qualität des Gerüsts rundherum bestimmt die Gesamtqualität des Agenten.
Drei Harness-Stufen im Beispiel
Lösen wir dieselbe Aufgabe „Blogartikel generieren” auf drei Eskalationsstufen.
Stufe 1: Nackter API-Aufruf (nahezu kein Harness)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const res = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
messages: [{ role: "user", content: "Schreibe einen Blogartikel" }],
});
console.log(res.content[0].text);
Ergebnis: allgemeiner, hohler Text. Thema und Struktur variieren jedes Mal.
Stufe 2: Werkzeuge einführen (mittleres Harness)
const tools = [
{
name: "read_existing_posts",
description: "Liste vorhandener Blogartikel mit ihren Titeln liefern",
input_schema: { type: "object", properties: {} },
},
{
name: "write_post",
description: "MDX-Datei schreiben",
input_schema: {
type: "object",
properties: {
slug: { type: "string" },
frontmatter: { type: "object" },
body: { type: "string" },
},
required: ["slug", "frontmatter", "body"],
},
},
];
async function runAgent(userGoal: string) {
let messages = [{ role: "user", content: userGoal }];
while (true) {
const res = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
tools,
messages,
});
if (res.stop_reason === "end_turn") break;
// Das Harness führt den Tool-Aufruf aus
const toolUse = res.content.find((c) => c.type === "tool_use");
const result = await executeTool(toolUse.name, toolUse.input);
messages.push({ role: "assistant", content: res.content });
messages.push({
role: "user",
content: [{ type: "tool_result", tool_use_id: toolUse.id, content: result }],
});
}
}
Ergebnis: Es wird ein nicht-redundantes Thema gewählt und ein formal korrektes MDX erzeugt. Allein das Hinzufügen von Werkzeugen verändert die Qualität drastisch.
Stufe 3: Ein vollwertiges Harness im Claude-Code-Stil
- Autonome Schleife (Benutzerfreigabe, Fehler-Retry)
- Kontextkompression (lange Gespräche zusammenfassen, Tokens sparen)
- Subagent-Delegation (Übersetzung in isoliertem Kontext)
- Prompt Caching (statischen Präfix nicht erneut senden)
- Hooks (automatisches Lint vor dem Commit)
Das alles selbst zu bauen ist ein Großprojekt. Genau deshalb lohnt es, Claude Code als Referenzimplementierung zu studieren.
Das Harness von Claude Code zerlegt
Claude Code ist das am besten ausgearbeitete Agenten-Harness innerhalb von Anthropic. Es lässt sich in fünf Schichten zerlegen.
Schicht 1: Werkzeugdesign
Ab Werk gibt es Read, Edit, Write, Bash, Glob, Grep, Agent usw. Bemerkenswert ist die Granularität:
Grepist kein simplesgrep, sondern ein ripgrep-Wrapper – präzise und schnellEditschreibt nicht die ganze Datei neu, sondern ersetzt gezielt Strings – minimale DiffsAgentstartet einen Subagenten mit isoliertem Kontext
Tool-Qualität schlägt direkt auf Agenten-Qualität durch. „Hauptsache es läuft” reicht nicht. Werkzeuge müssen idempotent sein, klare Fehlermeldungen liefern und eine einzige Verantwortung tragen.
Schicht 2: Geschichteter Kontext
~/.claude/CLAUDE.md ← globale Regeln
./CLAUDE.md ← Projektregeln (automatisch geladen)
~/.claude/memory/ ← Langzeitgedächtnis (sitzungsübergreifend)
├── user_profile.md
├── feedback_xxx.md
└── project_xxx.md
Gesprächsverlauf ← letzte Züge
Tasks/Plan ← Fortschritt der aktuellen Sitzung
Jede Schicht hat andere Lebensdauer und Rolle. Schreibt man an die falsche Stelle, verschwindet Information sofort oder – schlimmer – veraltete Daten bleiben hartnäckig. „Nur diese Sitzung” gehört in Tasks, „immer wieder nötig” gehört ins Memory.
Schicht 3: Subagent-Delegation
Mit dem Agent-Werkzeug startet man einen Agenten in separatem Kontext.
# Der Haupt-Agent gibt Anweisungen, die Schwerarbeit macht der Subagent
Agent(
subagent_type: "general-purpose",
prompt: "blog/harness.mdx ins Englische und in 8 weitere Sprachen übersetzen,
jeweils unter blog-{lang}/ speichern, danach berichten"
)
So bleibt der Hauptkontext frei von Log-Lärm. Lange Build-Logs, Zwischen-Übersetzungen, Suchauszüge – alles, wovon man nur das Ergebnis braucht, lässt sich komplett auslagern.
Schicht 4: Hooks (deterministische Verarbeitung)
In .claude/settings.json kann man Shell-Kommandos vor und nach Tool-Aufrufen einhängen.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npx tsc --noEmit" }
]
}
]
}
}
Nach jeder Bearbeitung läuft automatisch der Typ-Check. Was „besser deterministisch als bei jedem Aufruf vom LLM erledigt” werden sollte, gehört in einen Hook.
Schicht 5: Berechtigungsmodi
{
"permissions": {
"allow": ["Read", "Grep", "Glob"],
"deny": ["Bash(rm -rf*)", "Bash(git push --force*)"],
"ask": ["Write", "Edit", "Bash"]
}
}
Destruktive Kommandos explizit verbieten, Schreibvorgänge zur Bestätigung vorlegen. Unfälle passieren, wenn etwas unbeaufsichtigt ausgeführt wird – daher entscheidet diese Schicht über die Betriebssicherheit.
Fünf klassische Stolperfallen
1. Zu viele Werkzeuge Mit 30 Tools verzettelt sich das Modell und wird ungenauer. Faustregel: 5 bis 15. Fehlende Funktionen gehören in Subagenten.
2. Prompt-Caching bleibt ungenutzt
Wer cache_control der Claude-API ignoriert, schickt den langen System-Prompt jedes Mal komplett – und zahlt dafür. TTL von fünf Minuten im Blick behalten und statische Teile cachen.
messages: [{
role: "system",
content: [
{ type: "text", text: longStaticInstructions,
cache_control: { type: "ephemeral" } }, // ← genau das
{ type: "text", text: dynamicContext },
],
}]
3. Fehlermeldungen, die das LLM nicht versteht
Liefert ein Tool nur Error: undefined, kann sich das Modell nicht selbst reparieren. Schreib hinein, was schiefgelaufen ist und wie es zu beheben ist.
throw new Error(
`Datei '${path}' existiert nicht. ` +
`Aktuelle Dateien in scripts/: ${list.join(", ")}`
);
4. Menschliche Freigabe auslassen Automatisch genehmigte destruktive Aktionen (Löschen, Force-Push, DB-Update) führen zwangsläufig irgendwann zum Unfall. Standard: „Schreiben fragt, Löschen verboten.”
5. Gedächtnis nie entrümpeln
Veraltete Informationen ziehen den Agenten zu falschen Annahmen. Auch Memory braucht regelmäßiges Ausmisten (in Claude Code per /compact oder manueller Bearbeitung).
Bau dir dein eigenes Mini-Harness
Zum Schluss ein lokal lauffähiges Mini-Harness in Node.js + TypeScript.
// mini-harness.ts
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync, writeFileSync } from "fs";
const client = new Anthropic();
const tools = [
{ name: "read_file",
description: "Eine Textdatei lesen",
input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
{ name: "write_file",
description: "Eine Textdatei schreiben",
input_schema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } },
];
const executors = {
read_file: ({ path }) => readFileSync(path, "utf-8"),
write_file: ({ path, content }) => { writeFileSync(path, content); return `written ${path}`; },
};
async function loop(goal: string, maxSteps = 10) {
const messages: any[] = [{ role: "user", content: goal }];
for (let i = 0; i < maxSteps; i++) {
const res = await client.messages.create({
model: "claude-opus-4-6", max_tokens: 4096, tools, messages,
});
messages.push({ role: "assistant", content: res.content });
if (res.stop_reason === "end_turn") return res.content;
const toolUse = res.content.find((c: any) => c.type === "tool_use") as any;
if (!toolUse) return res.content;
const result = executors[toolUse.name](toolUse.input);
messages.push({
role: "user",
content: [{ type: "tool_result", tool_use_id: toolUse.id, content: String(result) }],
});
}
}
await loop("Lies README.md und speichere eine dreizeilige Zusammenfassung in TL;DR.md");
Damit steht bereits ein Mini-Agent, der bestehende Dateien lesen und neue schreiben kann. Ergänzt um Grep-, Bash- und Agent-Werkzeuge entsteht ein Claude Code im Kleinformat.
Fazit: Vom Prompt-Autor zum Harness-Architekten
| Alte Sichtweise | Neue Sichtweise |
|---|---|
| Guter Prompt, gutes Ergebnis | Gutes Harness, gutes Ergebnis |
| Modell auswählen | Modell + Werkzeuge + Kontext + Rechte entwerfen |
| Einzelne Fragen | Fortlaufender Schleifenbetrieb |
Claude Code ist das beste Lehrbuch, um diesen Perspektivwechsel zu erfahren. Nicht bloß benutzen – zerlegen und die Ideen in den eigenen Agenten übertragen. Das ist die Haltung, die KI-Ingenieur:innen ab 2026 verlangt wird.
Kopiere zuerst das obige Mini-Harness und starte es. Zehn Minuten später hast du den ersten Schritt zu deinem eigenen Agenten gemacht.
Verwandte Artikel
- 10 Subagent-Muster in Claude Code
- CLAUDE.md Best Practices
- Token-Optimierung in Claude Code
- Anleitung zu Berechtigungen in Claude Code
Weiterführende Quellen
Bring deinen Claude-Code-Workflow aufs nächste Level
50 in der Praxis erprobte Prompt-Vorlagen zum direkten Copy-and-paste in Claude Code.
Kostenloses PDF: Claude-Code-Spickzettel in 5 Minuten
Trag einfach deine E-Mail-Adresse ein – wir senden dir den A4-Spickzettel als PDF sofort zu.
Wir behandeln deine Daten sorgfältig und senden niemals Spam.
Über den Autor
Masa
Ingenieur, der Claude Code intensiv nutzt. Betreibt claudecode-lab.com, ein Tech-Medium in 10 Sprachen mit über 2.000 Seiten.
Ähnliche Artikel
Claude Code Sicherheits-Best-Practices: API-Schlüssel, Berechtigungen & Produktionsschutz
Ein praxisorientierter Sicherheitsleitfaden für den sicheren Einsatz von Claude Code. Von API-Schlüsselverwaltung über Berechtigungseinstellungen bis hin zu Hook-Automatisierung und Produktionsschutz — mit funktionierenden Codebeispielen.
7 Sicherheitsvorfälle mit Claude Code | Echte Unfälle und Prävention
Sieben reale Sicherheitsvorfälle mit Claude Code: .env-Lecks, Produktionsdatenbank-Löschungen, Abrechnungsexplosionen und mehr — mit Ursachenanalyse und Präventionscode.
Vollständiger Leitfaden zu Claude Code Berechtigungen | settings.json, Hooks & Allowlist erklärt
Vollständige Erklärung der Claude Code Berechtigungen. allow/deny/ask richtig einsetzen, Automatisierung mit Hooks, umgebungsspezifische settings.json und praktische Muster – mit funktionierendem Code.