Inhalt
Einleitung
Claude Code (v2.1.47) enthält eine experimentelle Funktion namens Agent Teams: Mehrere Claude-Code-Sitzungen koordinieren gemeinsame Arbeit in einer Topologie aus Teamleitung und Teammitgliedern. Ich entwickle Hive, einen Orchestrator für mehrere Coding-Agenten mit ähnlichen Zielen, aber einer ganz anderen Architektur. Deshalb wollte ich verstehen, wie der Ansatz von Anthropic unter der Haube funktioniert.
Dieser Artikel dokumentiert, was ich auf folgenden Wegen herausgefunden habe:
- Lesen der offiziellen Dokumentation
- Untersuchen tatsächlicher Artefakte, die frühere Teamsitzungen auf dem Datenträger hinterlassen haben
- Claude die Binärdatei von Claude Code (v2.1.47) auf Implementierungsdetails analysieren lassen (ha!)
Inhaltsverzeichnis
- 1. Architektur im Überblick
- 2. Die gemeinsame Aufgabenliste
- 3. Kommunikation zwischen Agenten
- 4. Starten von Agenten und Lebenszyklus
- 5. Qualitätskontrollen und Hooks
- 6. Token-Ökonomie
- 7. Zusammenfassung der Architektur
- Quellen
1. Architektur im Überblick
Ein Agententeam besteht aus vier Komponenten:
| Komponente | Rolle |
|---|---|
| Teamleitung | Die Hauptsitzung von Claude Code, die das Team erstellt und Teammitglieder startet |
| Teammitglieder | Separate Claude-Code-Instanzen mit jeweils eigenem Kontextfenster |
| Aufgabenliste | Gemeinsame Arbeitsaufträge, die als einzelne JSON-Dateien auf dem Datenträger gespeichert werden |
| Postfach | Eigene Posteingangsdateien pro Agent für die Nachrichtenzustellung |
Die gesamte Koordinationsschicht ist dateibasiert. Das Dateisystem unter ~/.claude/ bildet die einzige Koordinationsgrundlage:
~/.claude/
├── teams/{team-name}/
│ ├── config.json # team membership registry
│ └── inboxes/{agent-name}.json # per-agent mailbox
└── tasks/{team-name}/
├── .lock # flock() for concurrent task claiming
├── .highwatermark # auto-increment counter
├── 1.json # individual task files
├── 2.json
└── ...
Dies ist ein grundlegend dezentrales Design. Die Teamleitung ist einfach eine weitere Claude-Sitzung mit zusätzlichen Werkzeugen (TeamCreate, TeamDelete, SendMessage). Es gibt keinen Hintergrundprozess. Die Koordination ergibt sich aus dem gemeinsamen Dateizugriff.
Wenn du Claude in einer aktiven Sitzung bittest, ein Team für eine Aufgabe zu starten, und anschließend Folgendes in einem anderen Fenster ausführst, kannst du die Änderungen im Dateisystem in Echtzeit beobachten.
watch -n 0.5 'tree ~/.claude/teams/ 2>/dev/null; echo "---"; tree ~/.claude/tasks/ 2>/dev/null'
Zum Beispiel mit folgendem Prompt:
can you spawn an agent team to examine this codebase?
- have one look for bugs
- have one look for complexity
- have one look for good things to call out and play devil's advocate against the other two agents
Dabei habe ich Folgendes beobachtet:
teams
└── code-review
├── config.json
└── inboxes
├── bug-hunter.json
├── complexity-analyst.json
├── devils-advocate.json
└── team-lead.json
Teamkonfiguration
Die Teamkonfiguration unter ~/.claude/teams/{team-name}/config.json enthält ein members-Array, das die Teammitglieder lesen, um einander zu finden:
{
"members": [
{ "name": "team-lead", "agentId": "abc-123", "agentType": "leader" },
{
"name": "researcher",
"agentId": "def-456",
"agentType": "general-purpose"
}
]
}
Namen sind der primäre Adressierungsmechanismus (UUIDs existieren, werden aber nicht für das Routing verwendet). Für sämtliche Nachrichten und Aufgabenzuweisungen wird das Feld name verwendet.
2. Die gemeinsame Aufgabenliste
Dateiformat
Jede Aufgabe wird als einzelne JSON-Datei in ~/.claude/tasks/{team-name}/ gespeichert. Hier ist ein echtes Beispiel aus einer früheren Sitzung:
{
"id": "1",
"subject": "Hunt for bugs across the codebase",
"description": "...",
"activeForm": "Hunting for bugs",
"owner": "bug-hunter",
"status": "completed",
"blocks": [],
"blockedBy": []
}
Aufgabenschema:
| Feld | Typ | Beschreibung |
|---|---|---|
id |
string | Numerische ID, automatisch über .highwatermark hochgezählt |
subject |
string | Titel in Befehlsform (z. B. "Tests ausführen") |
description |
string | Detaillierte Anforderungen und Akzeptanzkriterien |
activeForm |
string | Verlaufsform für die Aktivitätsanzeige ("Tests werden ausgeführt") |
status |
string | pending → in_progress → completed (oder deleted) |
blocks |
string[] | IDs der Aufgaben, die diese Aufgabe blockiert |
blockedBy |
string[] | IDs der Aufgaben, die abgeschlossen sein müssen, bevor diese Aufgabe beginnen kann |
Nebenläufigkeitskontrolle
Zwei spezielle Dateien ermöglichen die Koordination:
.lock: Eine 0-Byte-Datei für gegenseitigen Ausschluss auf Dateisystemebene (flock()). In allen 42 Aufgabenverzeichnissen vorhanden, die ich auf meinem Rechner vorgefunden habe..highwatermark: Enthält eine einzelne Ganzzahl (z. B."3","13"). Die nächste verfügbare Aufgaben-ID für die automatische Hochzählung.
Aufgabenübernahme
Die Aufgabenübernahme verwendet Dateisperren, um Race Conditions zu verhindern. Teammitglieder bevorzugen Aufgaben mit der niedrigsten ID. Eine Aufgabe mit einem nicht leeren blockedBy-Array kann erst übernommen werden, wenn sich alle blockierenden Aufgaben in einem Endzustand befinden.
Beobachtung: Die meisten Aufgabenverzeichnisse sind leer
Von 42 Aufgabenverzeichnissen auf meinem Rechner enthielten nur 5 tatsächliche Aufgaben-JSON-Dateien. Die übrigen 37 enthielten nur .lock und .highwatermark. Das bedeutet vermutlich, dass Aufgaben nach ihrem Abschluss bereinigt werden oder dass dies Sitzungen waren, in denen Claude die interne Aufgabenliste (seit Einführung der Aufgabenlistenfunktion verfügbar) nutzte, ohne eine Aufteilung in Unteraufgabendateien vorzunehmen.
3. Kommunikation zwischen Agenten
Postfachmuster
Jeder Agent hat unter ~/.claude/teams/{team-name}/inboxes/{agent-name}.json eine Datei mit einem JSON-Array. Hier ist ein echter Posteingang aus einer früheren Sitzung, in der eine Teamleitung Arbeit an einen controlplane-agent verteilte:
[
{
"from": "team-lead",
"text": "{\"type\":\"task_assignment\",\"taskId\":\"1\",\"subject\":\"Phase 2: Control-plane - remove participants/presence\",\"description\":\"Remove multiplayer code from the control-plane package...\",\"assignedBy\":\"team-lead\",\"timestamp\":\"2026-02-18T02:37:16.890Z\"}",
"timestamp": "2026-02-18T02:37:16.890Z",
"read": false
}
]
Beachte die JSON-in-JSON-Kodierung: Das Feld text ist ein JSON-String, der ein serialisiertes Nachrichtenobjekt enthält. Die äußere Hülle enthält die Felder from, text, timestamp und read.
Nachrichtentypen
Das Feld type innerhalb der Nutzlast text unterstützt:
| Typ | Richtung | Zweck |
|---|---|---|
task_assignment |
Teamleitung → Teammitglied | Eine Aufgabe mit allen Details zuweisen |
message |
beliebiger Agent → beliebiger Agent | Direktnachricht an einen Empfänger |
broadcast |
Teamleitung → alle | Dieselbe Nachricht an jedes Teammitglied |
shutdown_request |
Teamleitung → Teammitglied | Geordnetes Herunterfahren anfordern |
shutdown_response |
Teammitglied → Teamleitung | Herunterfahren genehmigen oder ablehnen |
plan_approval_request |
Teammitglied → Teamleitung | Einen Plan zur Prüfung einreichen |
plan_approval_response |
Teamleitung → Teammitglied | Mit Feedback genehmigen oder ablehnen |
idle_notification |
Teammitglied → Teamleitung | Wird automatisch gesendet, wenn die Gesprächsrunde des Teammitglieds endet |
Zustellungsmechanismus
Schreibpfad: Der Absender hängt einen neuen Eintrag an die JSON-Array-Datei im Posteingang des Empfängers an.
Lesepfad: Der Empfänger fragt seine eigene Posteingangsdatei regelmäßig ab. Neue Nachrichten werden als synthetische Gesprächsrunden eingefügt (sie erscheinen, als hätte ein Nutzer sie gesendet).
Broadcast: Schreibt buchstäblich dieselbe Nachricht in die Posteingangsdatei jedes Teammitglieds. Die Token-Kosten steigen linear mit der Teamgröße.
Die Kommunikation besteht lediglich aus dem Anhängen an Dateien und dem Lesen von Dateien. Die Latenz zwischen Versand und Empfang hängt vom Abfrageintervall des Empfängers ab.
Sichtbarkeit von Direktnachrichten zwischen Teammitgliedern
Wenn ein Teammitglied einem anderen eine Direktnachricht sendet, enthält die Leerlaufbenachrichtigung an die Teamleitung eine kurze Zusammenfassung. Dadurch erhält die Teamleitung Einblick in die Zusammenarbeit zwischen Teammitgliedern, ohne den vollständigen Nachrichteninhalt zu sehen.
4. Starten von Agenten und Lebenszyklus
Wie Teammitglieder erstellt werden
Jedes Teammitglied ist ein separater claude-CLI-Prozess. Die Teamleitung startet sie über das Werkzeug Task mit den Parametern team_name und name. Für den gestarteten Prozess werden Umgebungsvariablen gesetzt:
CLAUDE_CODE_TEAM_NAME: bei gestarteten Teammitgliedern automatisch gesetztCLAUDE_CODE_PLAN_MODE_REQUIRED: auftruegesetzt, wenn eine Plangenehmigung erforderlich ist
Kontextinitialisierung
Teammitglieder laden denselben Projektkontext wie jede neue Sitzung:
CLAUDE.md-Dateien aus dem Arbeitsverzeichnis- MCP-Server
- Skills
- Den Start-Prompt der Teamleitung
Der Gesprächsverlauf der Teamleitung wird NICHT übernommen. Jedes Teammitglied beginnt von vorn und hat nur den Start-Prompt als Kontext.
Interne Implementierung
Die Binäranalyse von Claude Code v2.1.47 zeigt, dass der Kontext der Teammitglieder über AsyncLocalStorage mit diesen Feldern verwaltet wird:
agentId,agentName,teamNameparentSessionId,colorplanModeRequired
Wichtige interne Funktionen:
isTeammate()/isTeamLead(): RollenerkennungwaitForTeammatesToBecomeIdle(): Synchronisationsprimitiv für die TeamleitunggetTeammateContext()/setDynamicTeamContext(): Verwaltung des Laufzeitkontexts
Leerlauferkennung
Nach jeder LLM-Gesprächsrunde wechselt ein Teammitglied automatisch in den Leerlauf und sendet eine idle_notification an die Teamleitung. Dies ist der normale Ruhezustand und kein Hinweis auf einen Fehler oder fehlenden Fortschritt. Eine Nachricht an ein Teammitglied im Leerlauf weckt es wieder auf (der nächste Abfragezyklus erfasst die Nachricht im Posteingang).
Protokoll zum Herunterfahren
- Die Teamleitung sendet
shutdown_requestan ein Teammitglied - Das Teammitglied kann zustimmen (beendet sich geordnet) oder ablehnen (arbeitet mit einer Erklärung weiter)
- Die Teambereinigung über
TeamDeleteentfernt~/.claude/teams/{team-name}/und~/.claude/tasks/{team-name}/ - Die Bereinigung schlägt fehl, wenn noch Teammitglieder aktiv sind; sie müssen zuerst heruntergefahren werden
Vererbung von Berechtigungen
Teammitglieder erben beim Start den Berechtigungsmodus der Teamleitung. Wenn die Teamleitung mit --dangerously-skip-permissions läuft, gilt das auch für alle Teammitglieder. Die Modi einzelner Teammitglieder lassen sich nach dem Start ändern, beim Start jedoch nicht individuell konfigurieren.
5. Qualitätskontrollen und Hooks
Agent Teams ist zur Durchsetzung von Qualitätsanforderungen in das Hook-System von Claude Code integriert:
TeammateIdle-Hook
Wird ausgelöst, wenn ein Teammitglied kurz davorsteht, in den Leerlauf zu wechseln. Exit-Code 2 gibt stderr als Feedback zurück und verhindert den Wechsel in den Leerlauf, sodass das Teammitglied weiterarbeitet.
{
"hook_event_name": "TeammateIdle",
"teammate_name": "researcher",
"team_name": "my-project"
}
TaskCompleted-Hook
Wird ausgelöst, wenn eine Aufgabe als abgeschlossen markiert wird. Exit-Code 2 verhindert den Abschluss und gibt stderr als Feedback zurück.
{
"hook_event_name": "TaskCompleted",
"task_id": "task-001",
"task_subject": "Implement user authentication",
"task_description": "Add login and signup endpoints",
"teammate_name": "implementer",
"team_name": "my-project"
}
Dieser Hook wird in zwei Situationen ausgelöst: (1) wenn ein beliebiger Agent eine Aufgabe über TaskUpdate ausdrücklich als abgeschlossen markiert oder (2) wenn ein Teammitglied eines Agententeams seine Gesprächsrunde mit laufenden Aufgaben beendet.
Typen von Hook-Handlern
| Typ | Beschreibung |
|---|---|
command |
Shell-Skript. JSON über stdin, Exit-Codes für Entscheidungen. |
prompt |
LLM-Auswertung in einer Gesprächsrunde. Gibt {ok, reason} zurück. |
agent |
Subagent mit Lesewerkzeugen und mehreren Gesprächsrunden. Bis zu 50 Runden. |
6. Token-Ökonomie
Agententeams verbrauchen ungefähr 7× mehr Token als Standardsitzungen, wenn die Teammitglieder im Planmodus laufen. Jedes Teammitglied verwaltet als separate Claude-Instanz sein eigenes vollständiges Kontextfenster.
Basiswerte
- Durchschnittliche Nutzung von Claude Code: ~6 $/Entwickler/Tag
- Agententeams: zusätzlich zum Grundverbrauch ungefähr proportional zur Teamgröße
7. Zusammenfassung der Architektur
| Dimension | Claude Code Agent Teams |
|---|---|
| Koordinationsgrundlage | Einfache Dateien (~/.claude/tasks/, ~/.claude/teams/) |
| Aufgabenformat | Eine JSON-Datei pro Aufgabe + .lock für die Übernahme |
| Nachrichtenaustausch | JSON-Posteingangsdateien (Anhängen + Abfragen) |
| Agentenlebenszyklus | Sich selbst verwaltende CLI-Prozesse |
| Isolation der Arbeit | Gemeinsames Arbeitsverzeichnis |
| Merge-Strategie | Keine (Agenten bearbeiten Dateien direkt) |
| Wiederholungsversuche/Eskalation | Manuell (Teamleitung entscheidet oder Nutzer greift ein) |
| Topologie | Teamleitung + Teammitglieder auf einer Ebene, Peer-to-Peer-Nachrichten |
| Aufgabenplanung | Eigenständige Übernahme (Teammitglieder nehmen sich die nächste Aufgabe) |
| Zustandspersistenz | Nur Dateien; keine Wiederaufnahme von Teammitgliedern im selben Prozess |
| Qualitätskontrollen | Shell-Hooks (TeammateIdle, TaskCompleted) |
| Token-Erfassung | Nur pro Sitzung, keine agentenübergreifende Aggregation |
| Erkennung von Stillständen | Manuell (Nutzer bemerkt den Stillstand eines Teammitglieds) |
| Nebenläufigkeitskontrolle | Implizit (Teamgröße = Anzahl der Teammitglieder) |
| Abhängigkeitsmodell | blocks/blockedBy in Aufgabendateien |
Quellen
Offizielle Dokumentation
- Teams aus Claude-Code-Sitzungen: Architektur
- Interaktiver Modus — Aufgabenliste
- Agententeams — Aufgaben zuweisen und übernehmen
- Agententeams — Kontext und Kommunikation
- Agententeams — Teammitglieder herunterfahren
- Agententeams — Das Team bereinigen
- Agententeams — Berechtigungen
- Agententeams — Einschränkungen
- Agententeams — Bewährte Vorgehensweisen
- Hooks
- Kosten — Token-Kosten von Agententeams
- Einstellungen
- Subagenten
Artefakte auf dem Datenträger (Claude Code v2.1.47)
Beobachtet unter /Users/tau/.claude/:
- Teamverzeichnisse mit
config.json- undinboxes/{agent-name}.json-Dateien - Aufgabenverzeichnisse mit
.lock,.highwatermarkund einzelnen Aufgaben-JSON-Dateien - Beispiel einer Nachricht zur Aufgabenzuweisung von
team-leadancp-agentmit dem Zeitstempel2026-02-18T02:37:16.890Z
Binäranalyse
Binärdatei von Claude Code v2.1.47. Durch Zeichenkettenanalyse identifizierte interne Funktionen: getTeamName, getAgentName, getAgentId, isTeammate, isTeamLead, waitForTeammatesToBecomeIdle, getTeammateContext, setDynamicTeamContext, createTeammateContext. Kontextfelder von AsyncLocalStorage: agentId, agentName, teamName, parentSessionId, color, planModeRequired.