Ein Agent Harness ist das Gerüst um einen LLM, das ihn in einen praktischen Agenten verwandelt. Dieser Artikel erklärt Konzepte, Architektur und Entscheidungshilfen.
Definition: Der Harness-Begriff
Der Begriff "Harness" stammt ursprünglich aus der Fertigung und bedeutet: die Struktur, die ein System zusammenhält und funktionsfähig macht.
In der AI:
Agent Harness = Alle Komponenten AUSSER dem Sprachmodell, die einen Agenten in die Lage versetzen, sich selbst zu steuern, Werkzeuge zu benutzen und ein Ziel zu erreichen.
Vereinfachte Formel
Sprachmodell (GPT, Claude, etc.)
↓
+ Harness
├─ Memory/Context
├─ Tool Bindings
├─ Planning Logic
├─ Evaluation
└─ Guardrails
↓
= Funktionaler Agent
Die 5 Kern-Komponenten eines Harness
1. Memory & Context Management
Das Gedächtnis des Agenten: Was weiß er bereits, was muss beibehalten werden?
# Beispiel: Context Window Management
class AgentMemory:
def __init__(self, max_tokens=8000):
self.context = []
self.max_tokens = max_tokens
self.token_count = 0
def add_interaction(self, user_msg, assistant_msg):
"""Add interaction, prune old if needed"""
new_tokens = count_tokens(user_msg + assistant_msg)
if self.token_count + new_tokens > self.max_tokens:
# Prune oldest non-critical context
self.context = self._summarize_and_prune()
self.context.append({
"user": user_msg,
"assistant": assistant_msg,
"timestamp": datetime.now()
})
self.token_count += new_tokens
def _summarize_and_prune(self):
"""Use LLM to summarize and compress old context"""
old_context = self.context[:-10] # Keep last 10
summary_prompt = f"Zusammenfasse kurz: {old_context}"
summary = llm.call(summary_prompt)
return [{"summary": summary}] + self.context[-10:]
def get_context(self):
"""Return current context for LLM"""
return "\n".join([
f"User: {c['user']}\nAssistant: {c['assistant']}"
for c in self.context
])
Techniken:
- Sliding Window: Nur die letzten N Token im Context
- Summarization: Alte Context komprimieren
- Semantic Chunking: Relevante Teile identifizieren
- Vector Stores: Embeddings für Retrieval
2. Tool Binding & Execution
Die Fähigkeit, externe Funktionen aufzurufen.
# Tool Registry Pattern
class ToolRegistry:
def __init__(self):
self.tools = {}
def register(self, name, func, description, parameters):
"""Register a tool the agent can use"""
self.tools[name] = {
"func": func,
"description": description,
"parameters": parameters
}
def call_tool(self, tool_name, **kwargs):
"""Execute tool with safety checks"""
if tool_name not in self.tools:
raise ValueError(f"Tool {tool_name} not found")
tool = self.tools[tool_name]
# Validate parameters
for param, value in kwargs.items():
if param not in tool["parameters"]:
raise ValueError(f"Unknown parameter: {param}")
# Execute with timeout
try:
result = timeout(
tool["func"](**kwargs),
timeout_seconds=30
)
return {"success": True, "result": result}
except Exception as e:
return {"success": False, "error": str(e)}
def get_tool_descriptions(self):
"""Format tools for LLM context"""
descriptions = []
for name, tool in self.tools.items():
desc = f"""
Tool: {name}
Description: {tool['description']}
Parameters: {json.dumps(tool['parameters'])}
"""
descriptions.append(desc)
return "\n".join(descriptions)
# Usage
registry = ToolRegistry()
registry.register(
"search_web",
web_search,
"Search the web for information",
{"query": "string", "max_results": "integer"}
)
registry.register(
"read_file",
lambda path: open(path).read(),
"Read file contents",
{"path": "string"}
)
3. Planning & Reasoning
Wie der Agent sein Ziel strukturiert angeht.
# Planning Agent mit ReAct Pattern
class PlanningAgent:
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
self.plan = []
def create_plan(self, goal):
"""Use LLM to create an execution plan"""
prompt = f"""
Erstelle einen Schritt-für-Schritt Plan für:
{goal}
Format:
1. [Schritt]
2. [Schritt]
...
Nutze diese Tools:
{self.tools.get_tool_descriptions()}
"""
response = self.llm.call(prompt)
self.plan = self._parse_plan(response)
return self.plan
def execute_plan(self):
"""Execute each step, adapt if needed"""
for i, step in enumerate(self.plan):
print(f"Executing step {i+1}: {step}")
# Reasoning phase (Thought)
reasoning = self.llm.call(f"Reason about this step: {step}")
# Action phase (Action)
tool_call = self._parse_tool_call(reasoning)
if tool_call:
result = self.tools.call_tool(**tool_call)
# Observation
print(f"Observation: {result}")
# Adapt if needed
if not result["success"]:
new_step = self.llm.call(
f"The step failed: {result['error']}. What should we do instead?"
)
self.plan[i] = new_step
def _parse_plan(self, response):
"""Parse numbered plan from LLM response"""
lines = response.split('\n')
return [line.split('. ')[1] for line in lines if line[0].isdigit()]
def _parse_tool_call(self, reasoning):
"""Extract tool call from reasoning"""
# Parse something like: "Action: search_web(query='...')"
import re
match = re.search(r'Action: (\w+)\((.*?)\)', reasoning)
if match:
tool_name = match.group(1)
args_str = match.group(2)
# Parse arguments
return {"tool": tool_name, **parse_args(args_str)}
return None
4. Evaluation & Feedback
Wie der Agent prüft, ob er sein Ziel erreicht hat.
# Evaluation Framework
class AgentEvaluator:
def __init__(self, llm):
self.llm = llm
def evaluate_action(self, goal, action, result):
"""Evaluate if action moved towards goal"""
prompt = f"""
Goal: {goal}
Aktion: {action}
Ergebnis: {result}
War diese Aktion hilfreich? (ja/nein/teilweise)
Erklärung:
"""
evaluation = self.llm.call(prompt)
return self._parse_evaluation(evaluation)
def evaluate_completion(self, goal, conversation):
"""Check if goal was achieved"""
prompt = f"""
Ursprüngliches Ziel: {goal}
Gesamte Konversation:
{conversation}
Wurde das Ziel erreicht? (ja/nein/teilweise)
Verbleibende Aufgaben:
"""
result = self.llm.call(prompt)
return self._parse_completion(result)
def _parse_evaluation(self, response):
if "ja" in response.lower():
return {"helpful": True, "explanation": response}
elif "nein" in response.lower():
return {"helpful": False, "explanation": response}
else:
return {"helpful": "partial", "explanation": response}
def _parse_completion(self, response):
return {
"completed": "ja" in response.lower(),
"remaining": extract_remaining_tasks(response)
}
5. Guardrails & Safety
Wie der Agent am sicheren Gleis bleibt.
# Guardrails System
class SafetyGuardrails:
def __init__(self):
self.blocked_patterns = [
r'DROP\s+TABLE', # SQL Injection
r'rm\s+-rf', # Dangerous commands
r'API_KEY', # Secret exposure
]
self.rate_limits = {
"tool_calls": 100,
"api_requests": 1000,
"per_minute": 10
}
self.usage_tracker = {}
def check_tool_call(self, tool_name, args):
"""Check if tool call is safe"""
# Check rate limits
self._check_rate_limit(tool_name)
# Check for dangerous patterns
args_str = str(args)
for pattern in self.blocked_patterns:
if re.search(pattern, args_str, re.IGNORECASE):
raise SecurityError(f"Blocked pattern: {pattern}")
# Check permissions
if not self._has_permission(tool_name):
raise PermissionError(f"No permission for {tool_name}")
return True
def check_output(self, output):
"""Sanitize output before returning to user"""
# Remove API keys
output = re.sub(r'sk-\w+', '[REDACTED]', output)
# Remove internal IPs
output = re.sub(r'192\.168\.\d+\.\d+', '[INTERNAL_IP]', output)
# Remove credentials
output = re.sub(r'password[:\s]*\w+', '[REDACTED]', output, flags=re.IGNORECASE)
return output
def _check_rate_limit(self, tool_name):
"""Enforce rate limits"""
key = f"tool_{tool_name}"
self.usage_tracker[key] = self.usage_tracker.get(key, 0) + 1
if self.usage_tracker[key] > self.rate_limits["tool_calls"]:
raise RateLimitError(f"Rate limit exceeded for {tool_name}")
def _has_permission(self, tool_name):
"""Check if agent has permission for tool"""
# Implementation depends on permission model
return True
Agent Harness vs Framework vs SDK
Unterschiede
| Aspekt | Harness | Framework | SDK |
|---|---|---|---|
| Zweck | Einzelner Agent | Multi-Agent System | Integration |
| Scope | Koordination eines LLM | Mehrere Agenten + Kommunikation | Library für Entwickler |
| Abstraktion | Hoch | Mittel | Niedrig |
| Komplexität | Mittel | Hoch | Niedrig |
| Best für | Standalone Agenten | Komplexe Workflows | Integration bestehender Code |
Beispiele
Harness:
- Claude Code eigenes System
- OpenAI Assistants API
- LlamaIndex QueryEngine
Framework:
- AutoGen (Microsoft)
- CrewAI
- LangGraph (LangChain)
SDK:
- LangChain SDK
- Anthropic SDK
- OpenAI Python SDK
Geschichte: Von Prompts zu Harnesses
Evolution
1. Era: Raw LLM Prompting (2018-2020)
- Nur Text-In, Text-Out
- Kein Memory, keine Tools
2. Era: Few-Shot Examples (2020-2021)
- In-Context Learning
- Better prompts, gleiche Grenzen
3. Era: Function Calling (2021-2023)
- Tool Integration (OpenAI, Claude)
- Erste primitive Harnesses
4. Era: Full Agent Harnesses (2023-present)
- Memory Management
- Planning + Reasoning
- Safety Guardrails
- Multi-Agent Orchestration
5. Era: Production Harnesses (2024-present)
- Enterprise Safety
- Cost Optimization
- Audit Logging
- Compliance Integration
Design Patterns für Harnesses
Pattern 1: Single-Agent Linear
Eingabe → Plan → Aktion → Evaluation → Output
Best für: Einfache Tasks, Klassifizierung, Standard-Workflows
Pattern 2: Hierarchical Reasoning
Manager Agent
↙ ↘
Worker 1 Worker 2
(spezialisiert)
↘ ↙
Aggregator
Best für: Komplexe Multi-Domain Aufgaben
Pattern 3: Swarm Intelligence
Agent A ↔ Agent B
↓ ↑ ↑ ↓
↔ Agent C ↔
Best für: Kollaborative Problem-Lösung, Brainstorming
Pattern 4: Hierarchical + Feedback Loop
LLM Agent
↓
Tool Call
↓
Evaluation → Failure → Retry / Adapt
↓
Success
Best für: Iterative Refinement, Learning
Claude Code als Harness
Claude Code als Harness bietet:
class ClaudeCodeHarness:
"""Claude Code = Harness mit eingebautem Orchestrator"""
components = {
"memory": "Session Context + Multi-Turn",
"tools": [
"Read", "Write", "Edit", # Filesystem
"Bash", "Glob", # Shell
"Grep", # Search
"Git", # Version Control
"MCP Servers" # External APIs
],
"planning": "Automatic Multi-Step Reasoning",
"evaluation": "User Feedback Loop",
"guardrails": {
"permissions": "Tool Whitelist/Blacklist",
"safety": "Output Sanitization",
"audit": "Full Session Logging",
"rate_limits": "Configurable"
},
"orchestration": "Native Agent Sequencing"
}
def create_agent(self, CLAUDE_md_config):
"""Create configured agent from CLAUDE.md"""
return Agent(
model=config.model,
tools=config.tools,
hooks=config.hooks,
skills=config.skills,
permissions=config.permissions
)
Erweiterung des Harness
Claude Code Harness kann erweitert werden durch:
Plugins
# Neue Tools hinzufügen
capabilities: [csv-processor, ml-pipeline, blockchain]
Skills
# Spezialisierte Workflows
skills:
- data-analysis
- code-generation
- security-audit
Hooks
// Pre/Post Execution Logic
{
"PreToolUse": [custom_validator],
"PostExecution": [audit_log]
}
MCP Servers
{
"mcp_servers": {
"stripe": "http://localhost:3000",
"slack": "http://localhost:3001",
"salesforce": "http://localhost:3002"
}
}
Evaluations-Metriken für Harnesses
Wie misst man ob ein Harness gut ist?
| Metrik | Beschreibung | Ziel |
|---|---|---|
| Task Completion Rate | % Aufgaben komplett gelöst | >90% |
| Time to Completion | Durchschnittliche Dauer | Baseline |
| Tool Accuracy | % korrekte Tool Calls | >95% |
| Safety Score | Keine Safety Violations | 100% |
| Cost per Task | Durchschnittliche API Kosten | Minimize |
| User Satisfaction | Feedback-Score | >4.5/5 |
Community Harnesses (die Claude Code erweitern)
ECC (Extensible Claude Code)
Komplett offene Harness-Implementierung mit erweiterbarer Plugin-Architektur.
Features:
- Multi-Agent Coordination
- Advanced Memory Management
- Custom Tool Development Framework
URL: https://github.com/community/ecc-harness
Ruflo
Focused Harness für Data Processing Workflows mit optimierter Memory Compression.
Features:
- Token-effiziente Context Windows
- Specialized Data Transformation Tools
- Built-in ML Integration
URL: https://github.com/datasets/ruflo
Build vs Buy vs Extend: Entscheidungsrahmen
┌─────────────────────┐
│ Anforderungen │
│ Eindeutig? │
└──────────┬──────────┘
│
┌─────┴─────┐
│ │
Ja │ │ Nein
│ │
▼ ▼
Standard- Custom
Harness (Build)
(Claude Code)
│ │
└─────┬─────┘
│
┌─────▼──────┐
│ Komplexität│
│ Hoch? │
└─────┬──────┘
│
┌─────┴──────┐
│ │
Ja │ │ Nein
│ │
▼ ▼
Framework Extend
(AutoGen) (Plugins)
