Article

Agent Harness Engineering: Wie man AI-Agenten wirklich baut

AI Agents Claude Codex Engineering

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.

Link: Hugging Face Agent Glossar