Article
Agent Harness Engineering: Wie man AI-Agenten wirklich baut
Agent-Glossare sind gut. Aber wie baut man einen Agenten tatsächlich? Das Hugging Face Glossar liefert die Konzepte – hier ist der Engineering-Teil.
Die Architektur verstehen
Ein Agent besteht aus:
- Model: Das LLM (Claude, GPT, Qwen)
- Scaffolding: System-Prompts, Tool-Beschreibungen, Output-Format, Context-Management
- Harness: Die Ausführungsebene – ruft das Modell auf, verarbeitet Tool-Calls, entscheidet über Termination
Die Formel: Agent = Model + Harness
Scaffolding gestalten
Scaffolding ist nicht nur Prompt-Engineering. Es umfasst:
System-Prompt: Wer ist der Agent? Was sind seine Grenzen? Wie soll er entscheiden?
Tool-Beschreibungen: Jedes Tool braucht eine präzise Beschreibung – Name, Parameter, Rückgabeformat, Fehlerbehandlung.
Output-Parsing: Wie antwortet der Agent? JSON, Markdown, Code? Ein Parser muss die Antworten in ausführbare Aktionen übersetzen.
Context-Management: Was bleibt im Context Window? Wie rotiert die Historie? Welche Tool-Ergebnisse werden behalten?
Harness implementieren
Der Harness ist der Controller – die Schleife, die das Modell treibt:
function runAgent(model, scaffolding, task) {
context = scaffolding.initContext(task)
while (!shouldTerminate(context)) {
response = model.call(context)
if (response.toolCall) {
result = executeTool(response.toolCall)
context = scaffolding.update(context, result)
}
context = scaffolding.update(context, response)
}
return context.finalResult
}
Die Kernfrage: Wann terminiert?
Termination-Strategien
- Fixed iterations: Stop nach N Runden – simpel, aber blind
- Success signal: Stop, wenn Agent ein Success-Flag setzt
- Idle detection: Stop, wenn Agent keine Tool-Calls mehr macht
- Error threshold: Stop nach N aufeinanderfolgenden Fehler
- Human-in-the-loop: Stop für Approval vor kritischen Aktionen
Die Wahl hängt vom Use-Case ab. Ein Coding-Agent kann nach “task completed” stoppen. Ein Research-Agent nach “no more tools needed”.
Tool-Design
Tools sind die Hände des Agenten. Ein Tool braucht:
- Klaren Namen (keine Abkürzungen)
- Parameter-Schema (JSON-typisiert)
- Fehler-Rückgabe (nicht Exception)
- Timeout-Handling
- Idempotency wenn möglich
Beispiel: File-Write Tool. Ein schlechtes Tool überschreibt blind. Ein gutes Tool:
- Prüft, ob Datei existiert
- Fragt nach Bestätigung oder lädt vorherige Version
- Gibt klare Status-Response zurück
Context Engineering
Context ist teuer und endlich. Token-Limits sind real. Strategien:
Rolling window: Nur die letzten N Turns behalten – einfach, verliert aber frühe Context.
Summary extraction: Alte Conversations zusammenfassen und als ein Turn injecten – spart Tokens, verliert Details.
Priority queue: Tool-Ergebnisse und wichtige Fakten markieren, weniger wichtige rotieren.
Memory injection: Externe Memories bei Bedarf laden – Memory als Tool.
Sub-Agents
Ein Agent kann andere Agenten aufrufen. Das ist mehr als ein Tool-Call:
- Tool: Eine Funktion, die einen Wert zurückgibt
- Skill: Ein strukturiertes Paket von Wissen und Werkzeugen
- Sub-Agent: Ein eigener Agent mit eigenem Modell, eigenem Scaffolding, eigener Loop
Sub-Agents sind nützlich für komplexe, unabhängige Subtasks. Der Orchestrator muss nicht wissen, wie der Sub-Agent arbeitet. Nur, was er zurückgibt.
Testing und Debugging
Agenten sind schwer zu testen – sie sind nicht-deterministisch. Best Practices:
Record-Replay: Session aufzeichnen, deterministisch wiedergeben. Bei Fehlern: Replay mit Logging.
Mock tools: Tool-Responses mocken für isolierte Tests. Das Modell bleibt echt, die Tools sind kontrolliert.
Eval harness: Feste Szenarien mit erwarteten Outcomes. Score: Wie oft erreicht der Agent das Ziel?
Logging: Jeden Turn, jede Decision, jeden Tool-Call loggen. Bei Problemen: Trace durchgehen.
Beispiel: Ein File-Edit Agent
from hermes_agent import Agent, Tool
def edit_file(file_path: str, changes: list) -> str:
\"\"\"Edit a file with specified changes\"\"\"
# Implementation
return result
agent = Agent(
model=\"claude-3-opus\",
scaffolding={
\"system_prompt\": \"Edit files carefully...\",
\"tools\": [Tool(edit_file)]
},
harness={
\"max_turns\": 10,
\"termination\": \"success_or_idle\"
}
)
result = agent.run(\"Fix the bug in main.py\")
Produktions-Überlegungen
Wenn der Agent live geht:
Rate limiting: Nicht zu viele API-Calls pro Minute Cost limits: Max-Tokens pro Session Error handling: Graceful degradation, nicht Crash Monitoring: Alerts bei anomalem Verhalten Fallback: Was passiert, wenn das Modell nicht erreichbar?
Fazit
Harness Engineering ist der unterschätzte Teil der Agent-Entwicklung. Das Modell ist nur ein Teil – wichtig, aber nicht hinreichend. Der Harness entscheidet:
- Ob der Agent terminiert oder endlos looped
- Ob Fehler graceful behandelt werden
- Ob der Context effizient verwaltet wird
- Ob Tools robust implementiert sind
Wer Agenten bauen will, muss Scaffolding und Harness verstehen. Prompt-Engineering allein reicht nicht.