Phase 11 Ausbau: AUTO-Heuristik + Custom Sub-Agents + Delegations-Badge

Bridge (scripts/claude-bridge.js):
- chooseAutoMode(): Keyword-Heuristik wählt solo/handlanger/experten
  basierend auf Aufgabenkomplexität und Nachrichtenlänge
- auto-mode-chosen Event fuer Frontend-Feedback
- effectiveMode statt agentMode durchs ganze sendMessage-Flow

Custom Sub-Agents via SDK agents-Option:
- HANDLANGER_AGENTS.worker: Haiku, exakte Ausfuehrung, max 500 Tokens
- EXPERTEN_AGENTS: research/implement/test/review mit eigenen Tools+Prompts
- Orchestrator-Prompts verweisen auf subagent_type Namen
- Kostenersparnis im Handlanger-Modus durch Haiku-Delegation

UI (AgentView.svelte):
- Delegations-Badge bei Sub-Agent-Knoten (farbcodiert nach Modus)
- Nur sichtbar bei depth > 0 und Modus != solo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Eddy 2026-04-14 18:50:30 +02:00
parent 314042a01f
commit de90c2da19
3 changed files with 227 additions and 41 deletions

View file

@ -35,6 +35,7 @@ Stand: 14.04.2026
| **Context-Management (Phase 9)** | ✅ | eb91e54 | | **Context-Management (Phase 9)** | ✅ | eb91e54 |
| **Sprach-Interface (Phase 10)** | ✅ | 14.04.2026 | | **Sprach-Interface (Phase 10)** | ✅ | 14.04.2026 |
| **Multi-Agent-Modi (Phase 11 — Basis)** | ✅ | 14.04.2026 | | **Multi-Agent-Modi (Phase 11 — Basis)** | ✅ | 14.04.2026 |
| **Multi-Agent-Ausbau (Phase 11 — Vollendung)** | ✅ | 14.04.2026 |
--- ---
@ -348,7 +349,7 @@ Benötigt `OPENAI_API_KEY` Umgebungsvariable für Whisper + TTS.
--- ---
## Phase 11: Multi-Agent-Architektur (Context-Einsparung) 🚧 TEIL-ERLEDIGT ## Phase 11: Multi-Agent-Architektur (Context-Einsparung) ERLEDIGT
> **Basis-Implementierung:** 14.04.2026 (Tool-Filterung + Persistenz + UI-Badge) > **Basis-Implementierung:** 14.04.2026 (Tool-Filterung + Persistenz + UI-Badge)
@ -369,7 +370,30 @@ Benötigt `OPENAI_API_KEY` Umgebungsvariable für Whisper + TTS.
- ✅ **Frontend: mode-changed Listener** (`events.ts`) - ✅ **Frontend: mode-changed Listener** (`events.ts`)
- Badge aktualisiert sich bei Modus-Wechsel live - Badge aktualisiert sich bei Modus-Wechsel live
### Noch offen (Ausbau) ### Ausbau-Implementierung (14.04.2026)
- ✅ **AUTO-Modus Keyword-Heuristik** (`chooseAutoMode()` in Bridge)
- < 80 Zeichen solo
- "implementiere/refactor/baue…" → experten
- "lies/suche/finde/analysiere…" + > 120 Zeichen → handlanger
- > 300 Zeichen ohne klare Keywords → handlanger (safer default)
- Sendet `auto-mode-chosen` Event ans Frontend
- ✅ **Custom Sub-Agent-Definitionen via SDK `agents` Option**
- **Handlanger**: Sub-Agent "worker" auf **Haiku** — nur Ausführung, max 500 Tokens Rückmeldung
- **Experten**: 4 autonome Agents
- `research` — Code/Docs durchsuchen (Read, Grep, Glob, Bash)
- `implement` — Code schreiben nach Best-Practices (volle Tools)
- `test` — Testfälle wählen und ausführen (volle Tools)
- `review` — Code prüfen auf Qualität/Sicherheit (read-only)
- Experten erben Modell (`model: 'inherit'`), Handlanger nutzt explizit Haiku
- ✅ **AgentView: Delegations-Badge**
- Bei Sub-Agent-Knoten wird der aktuelle Delegations-Modus farbcodiert angezeigt
- 👷 Handlanger (orange), 🎓 Experten (lila), 🤖 Auto (cyan)
- ✅ **Orchestrator-Prompts angepasst**
- Verweisen explizit auf `subagent_type` der verfügbaren Custom Agents
- Anweisung: Formuliere WAS (Experten) oder EXAKT WIE (Handlanger)
### Alle Phase 11 Features implementiert!
### Die drei Agent-Modi (einstellbar!) ### Die drei Agent-Modi (einstellbar!)

View file

@ -33,43 +33,46 @@ Du bist der HAUPT-AGENT und arbeitest im HANDLANGER-MODUS.
WICHTIG: Du denkst und planst, aber Sub-Agents führen aus! WICHTIG: Du denkst und planst, aber Sub-Agents führen aus!
Wenn du eine Aufgabe bekommst: Dir steht das Task-Tool zur Verfügung mit dem Sub-Agent-Typ "worker".
1. ANALYSIERE was nötig ist Der Worker läuft auf Haiku (günstig) und führt genau aus was du sagst.
2. DELEGIERE an passende Sub-Agents mit EXAKTEN Anweisungen
3. Sub-Agents führen GENAU aus, was du sagst sie denken NICHT selbst Arbeitsweise:
4. Du erhältst ZUSAMMENFASSUNGEN zurück (keine Rohdaten) 1. ANALYSIERE die Aufgabe
5. Du entscheidest den nächsten Schritt 2. Zerlege in EXAKTE Ausführungsschritte
3. Delegiere jeden Schritt per Task(subagent_type: "worker", prompt: "...")
4. Formuliere den Task-Prompt als exakte Anweisung, nicht als Frage
5. Sammle die Zusammenfassungen, entscheide den nächsten Schritt
Beispiel-Delegationen: Beispiel-Delegationen:
- "Lies Datei X, gib mir Zeilen 10-50 zurück" - Task(subagent_type:"worker", prompt:"Lies src/lib.rs, gib mir Zeilen 10-50 zurück")
- "Suche nach 'handleError' in src/, liste die Dateien" - Task(subagent_type:"worker", prompt:"Suche 'handleError' in src/ via Grep, liste die Dateien")
- "Führe 'npm test' aus, berichte nur ob passed/failed" - Task(subagent_type:"worker", prompt:"Führe 'npm test' aus, berichte nur passed/failed + Fehlerzeile")
Halte deinen Context klein lass Sub-Agents die Details bearbeiten! Halte deinen Context klein lass den Worker die Rohdaten bearbeiten!
`, `,
experten: ` experten: `
Du bist der HAUPT-AGENT und arbeitest im EXPERTEN-MODUS. Du bist der HAUPT-AGENT und arbeitest im EXPERTEN-MODUS.
WICHTIG: Du koordinierst autonome Experten-Agents! WICHTIG: Du koordinierst vier autonome Experten-Agents!
Deine Experten: Task-Tool Sub-Agent-Typen (autonome Experten):
- **Research**: Durchsucht Code, findet Informationen, PLANT SELBST wie er sucht - **research**: Durchsucht Code/Docs, findet Infos. Wähle diesen für "Finde heraus…", "Wo ist…"
- **Implement**: Schreibt Code, ENTSCHEIDET SELBST wie er es macht (Best Practices) - **implement**: Schreibt Code nach Best-Practices. Wähle diesen für "Implementiere…", "Baue…"
- **Test**: Schreibt und führt Tests aus, WÄHLT SELBST passende Testfälle - **test**: Schreibt und führt Tests. Wähle diesen für "Teste…"
- **Review**: Prüft Code, FINDET SELBST Probleme - **review**: Prüft Code auf Qualität/Sicherheit. Wähle diesen für "Prüfe…"
Wenn du eine Aufgabe bekommst: Arbeitsweise:
1. TEILE sie in Experten-Bereiche auf 1. ZERLEGE die Aufgabe in Experten-Bereiche
2. DELEGIERE an den passenden Experten mit dem WAS, nicht dem WIE 2. DELEGIERE via Task(subagent_type: "research"|"implement"|"test"|"review", prompt: "...")
3. Der Experte arbeitet AUTONOM und liefert eine Zusammenfassung 3. Formuliere das WAS, nicht das WIE die Experten planen selbst
4. Du INTEGRIERST die Ergebnisse 4. Integriere die Zusammenfassungen, orchestriere weitere Schritte
Beispiel-Delegationen: Beispiel-Delegationen:
- Research: "Finde heraus wie Authentication in diesem Projekt implementiert ist" - Task(subagent_type:"research", prompt:"Finde heraus wie Authentication implementiert ist")
- Implement: "Füge OAuth2-Support hinzu" (ohne exakte Code-Vorgabe) - Task(subagent_type:"implement", prompt:"Füge OAuth2-Support hinzu mit Token-Refresh")
- Test: "Teste die neue Auth-Funktionalität" - Task(subagent_type:"test", prompt:"Teste die neue Auth-Funktionalität")
- Review: "Prüfe die OAuth-Implementierung auf Sicherheitsprobleme" - Task(subagent_type:"review", prompt:"Prüfe die OAuth-Implementierung auf Sicherheitsprobleme")
`, `,
auto: ` auto: `
@ -84,6 +87,82 @@ Teile deine Wahl am Anfang mit: "[Modus: X] Begründung"
`, `,
}; };
// ============ Custom Sub-Agent Definitionen ============
// Werden je nach Modus an query() übergeben
const HANDLANGER_AGENTS = {
worker: {
description: 'Führt exakte Anweisungen des Haupt-Agents aus (lesen, suchen, triviale Edits). Denkt NICHT selbst, berichtet komprimiert zurück.',
// Günstiges Modell — Handlanger muss nicht planen
model: 'haiku',
tools: ['Read', 'Grep', 'Glob', 'Bash', 'Edit', 'Write'],
prompt: `Du bist ein HANDLANGER-Agent.
WICHTIG:
1. Führe GENAU aus was der Haupt-Agent verlangt denke NICHT selbst
2. Plane keine eigene Herangehensweise
3. Berichte KOMPRIMIERT zurück (max. 500 Tokens):
- Bei Read: Relevante Zeilen/Passagen, keine Volltext-Dumps
- Bei Grep: Liste der Treffer mit Zeilennummern
- Bei Bash: Exit-Code + wichtigste Ausgabe-Zeilen
- Bei Edit/Write: Bestätigung was geändert wurde
4. Keine Erklärungen, keine Vorschläge nur das verlangte Ergebnis`,
},
};
const EXPERTEN_AGENTS = {
research: {
description: 'Durchsucht Code und Dokumentation autonom. Findet selbst heraus was relevant ist.',
model: 'inherit',
tools: ['Read', 'Grep', 'Glob', 'Bash'],
prompt: `Du bist ein RESEARCH-Experte.
Du bekommst eine Frage plane selbst wie du sie beantwortest:
- Wähle selbst welche Dateien/Patterns zu suchen sind
- Priorisiere wichtige Infos
- Berichte strukturiert: Was gefunden, wo (Pfade/Zeilen), warum relevant
- Max 1000 Tokens Zusammenfassung`,
},
implement: {
description: 'Schreibt Code-Änderungen nach Best-Practices. Entscheidet selbst über Architektur und Details.',
model: 'inherit',
tools: ['Read', 'Grep', 'Glob', 'Edit', 'Write', 'Bash'],
prompt: `Du bist ein IMPLEMENT-Experte.
Du bekommst das WAS entscheide selbst das WIE:
- Lies relevanten Code zum Verständnis
- Implementiere nach Best-Practices (Codierrichtlinien des Projekts beachten)
- Berichte: welche Dateien geändert, was war der Kern, was beibehalten
- Max 800 Tokens Zusammenfassung`,
},
test: {
description: 'Schreibt und führt Tests aus. Wählt selbst sinnvolle Testfälle.',
model: 'inherit',
tools: ['Read', 'Grep', 'Glob', 'Edit', 'Write', 'Bash'],
prompt: `Du bist ein TEST-Experte.
Du bekommst ein Feature wähle selbst passende Testfälle:
- Happy Path + sinnvolle Edge Cases
- Nutze vorhandene Test-Infrastruktur
- Berichte: Tests geschrieben (Anzahl), was ist abgedeckt, passed/failed
- Max 500 Tokens Zusammenfassung`,
},
review: {
description: 'Prüft Code auf Qualität, Sicherheit und Stil. Findet selbst Probleme.',
model: 'inherit',
tools: ['Read', 'Grep', 'Glob', 'Bash'],
prompt: `Du bist ein REVIEW-Experte.
Du bekommst Code zum Prüfen finde selbst Probleme:
- Sicherheit (Injections, Secrets, Auth)
- Performance (N+1, unnötige Loops)
- Fehlerbehandlung (Boundary-Cases)
- Stil (Konsistenz mit Projekt)
- Berichte strukturiert nach Schwere (kritisch/warnung/info)
- Max 800 Tokens`,
},
};
// Subagent-Tracking // Subagent-Tracking
// Map: toolUseId → { agentId, parentId, type, task, depth } // Map: toolUseId → { agentId, parentId, type, task, depth }
const activeSubagents = new Map(); const activeSubagents = new Map();
@ -147,6 +226,38 @@ function sendMonitorEvent(type, summary, details = {}, options = {}) {
}); });
} }
// AUTO-Modus: Heuristik wählt passenden Modus basierend auf Aufgabe
// Rückgabe: 'solo' | 'handlanger' | 'experten'
function chooseAutoMode(message) {
const text = (message || '').toLowerCase();
const charCount = text.length;
// Keywords die klar auf Experten-Aufgaben hinweisen (komplexe, parallelisierbare Arbeit)
const expertKeywords = [
'implementiere', 'implementier ', 'refactor', 'architektur', 'entwickle',
'erstelle feature', 'feature ', 'design', 'baue ', 'optimiere',
'migration', 'umbau', 'umstruktur',
];
// Keywords die auf Handlanger-Aufgaben hinweisen (viel koordinieren/sammeln)
const handlangerKeywords = [
'lies ', 'suche ', 'finde ', 'zeig mir ', 'untersuche',
'analysiere', 'durchsuche', 'alle dateien', 'sammle',
'liste alle', 'vergleiche',
];
// Klar triviale Aufgaben → solo
if (charCount < 80) return 'solo';
if (expertKeywords.some(kw => text.includes(kw))) return 'experten';
if (handlangerKeywords.some(kw => text.includes(kw)) && charCount > 120) return 'handlanger';
// Längere Nachrichten ohne klare Keywords → handlanger (safer default)
if (charCount > 300) return 'handlanger';
return 'solo';
}
// Tool-Input für Logging kürzen (sensitive Daten maskieren) // Tool-Input für Logging kürzen (sensitive Daten maskieren)
function summarizeToolInput(tool, input) { function summarizeToolInput(tool, input) {
if (!input) return ''; if (!input) return '';
@ -221,13 +332,24 @@ async function sendMessage(message, requestId, model = null, contextOverride = n
resumeSessionId: resumeSessionId || null, resumeSessionId: resumeSessionId || null,
}); });
sendResponse(requestId, { agentId: currentAgentId, status: 'gestartet', model: useModel, resuming: isResuming, mode: agentMode }); // AUTO-Modus: Effektiven Modus aus der Nachricht ableiten
let effectiveMode = agentMode;
if (agentMode === 'auto') {
effectiveMode = chooseAutoMode(message);
sendEvent('auto-mode-chosen', { chosen: effectiveMode, messageLength: message.length });
sendMonitorEvent('agent', `Auto-Modus gewählt: ${effectiveMode}`, {
chosen: effectiveMode,
messageLength: message.length,
});
}
// Orchestrator-Prompt für nicht-Solo Modi sendResponse(requestId, { agentId: currentAgentId, status: 'gestartet', model: useModel, resuming: isResuming, mode: agentMode, effectiveMode });
// Orchestrator-Prompt für nicht-Solo Modi (nutzt effektiven Modus)
let orchestratorPrompt = ''; let orchestratorPrompt = '';
if (agentMode !== 'solo' && ORCHESTRATOR_PROMPTS[agentMode]) { if (effectiveMode !== 'solo' && ORCHESTRATOR_PROMPTS[effectiveMode]) {
orchestratorPrompt = ORCHESTRATOR_PROMPTS[agentMode]; orchestratorPrompt = ORCHESTRATOR_PROMPTS[effectiveMode];
sendMonitorEvent('agent', `Orchestrator-Modus: ${agentMode}`, { mode: agentMode }); sendMonitorEvent('agent', `Orchestrator-Modus: ${effectiveMode}`, { mode: effectiveMode });
} }
// Nachricht mit Context und Orchestrator kombinieren // Nachricht mit Context und Orchestrator kombinieren
@ -256,23 +378,29 @@ async function sendMessage(message, requestId, model = null, contextOverride = n
queryOptions.sessionId = resumeSessionId; queryOptions.sessionId = resumeSessionId;
} }
// Tool-Filterung je nach Agent-Modus — erzwingt Delegation // Tool-Filterung + Custom Sub-Agents je nach effektivem Modus
// Handlanger: Main darf NUR delegieren (Task) und planen (TodoWrite) // Handlanger: Main darf NUR delegieren (Task) und planen (TodoWrite)
// Sub-Agents laufen auf Haiku (siehe HANDLANGER_AGENTS)
// Experten: Main darf zusätzlich lesen/suchen, aber nicht schreiben // Experten: Main darf zusätzlich lesen/suchen, aber nicht schreiben
if (agentMode === 'handlanger') { // Sub-Agents sind autonome Research/Implement/Test/Review
if (effectiveMode === 'handlanger') {
queryOptions.allowedTools = ['Task', 'TodoWrite']; queryOptions.allowedTools = ['Task', 'TodoWrite'];
sendMonitorEvent('agent', 'Handlanger-Modus: Main darf nur Task+TodoWrite', { queryOptions.agents = HANDLANGER_AGENTS;
mode: agentMode, sendMonitorEvent('agent', 'Handlanger-Modus: Main → Task+TodoWrite, Worker auf Haiku', {
mode: effectiveMode,
allowedTools: queryOptions.allowedTools, allowedTools: queryOptions.allowedTools,
agents: Object.keys(HANDLANGER_AGENTS),
}); });
} else if (agentMode === 'experten') { } else if (effectiveMode === 'experten') {
queryOptions.allowedTools = ['Task', 'TodoWrite', 'Read', 'Grep', 'Glob']; queryOptions.allowedTools = ['Task', 'TodoWrite', 'Read', 'Grep', 'Glob'];
sendMonitorEvent('agent', 'Experten-Modus: Main darf lesen+delegieren', { queryOptions.agents = EXPERTEN_AGENTS;
mode: agentMode, sendMonitorEvent('agent', 'Experten-Modus: 4 autonome Experten verfügbar', {
mode: effectiveMode,
allowedTools: queryOptions.allowedTools, allowedTools: queryOptions.allowedTools,
agents: Object.keys(EXPERTEN_AGENTS),
}); });
} }
// solo + auto: keine Einschränkung // solo: keine Einschränkung
const conversation = query({ const conversation = query({
prompt: fullPrompt, prompt: fullPrompt,

View file

@ -1,7 +1,14 @@
<script lang="ts"> <script lang="ts">
import { agents, selectedAgentId, agentCount, agentTree, type AgentTreeNode } from '$lib/stores/app'; import { agents, selectedAgentId, agentCount, agentTree, agentMode, type AgentTreeNode } from '$lib/stores/app';
import type { Agent } from '$lib/stores/app'; import type { Agent } from '$lib/stores/app';
// Delegations-Badge-Text je nach Agent-Modus
const delegationBadges: Record<string, { label: string; cssClass: string }> = {
handlanger: { label: '👷 Handlanger-Auftrag', cssClass: 'badge-handlanger' },
experten: { label: '🎓 Experten-Auftrag', cssClass: 'badge-experten' },
auto: { label: '🤖 Auto', cssClass: 'badge-auto' },
};
// Status-Icons // Status-Icons
const statusIcons: Record<Agent['status'], string> = { const statusIcons: Record<Agent['status'], string> = {
active: '🟢', active: '🟢',
@ -111,6 +118,12 @@
<span class="agent-tools">🔧 {agent.toolCalls.length}</span> <span class="agent-tools">🔧 {agent.toolCalls.length}</span>
{#if depth > 0} {#if depth > 0}
<span class="agent-depth">Ebene {depth}</span> <span class="agent-depth">Ebene {depth}</span>
{#if $agentMode && $agentMode !== 'solo' && delegationBadges[$agentMode]}
<span class="delegation-badge {delegationBadges[$agentMode].cssClass}"
title="Delegiert im Modus: {$agentMode}">
{delegationBadges[$agentMode].label}
</span>
{/if}
{/if} {/if}
</div> </div>
</div> </div>
@ -383,6 +396,27 @@
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
} }
.delegation-badge {
padding: 1px 6px;
border-radius: var(--radius-sm);
font-weight: 600;
}
.delegation-badge.badge-handlanger {
color: #f59e0b;
background: rgba(245, 158, 11, 0.15);
}
.delegation-badge.badge-experten {
color: #a855f7;
background: rgba(168, 85, 247, 0.15);
}
.delegation-badge.badge-auto {
color: #06b6d4;
background: rgba(6, 182, 212, 0.15);
}
.agent-children { .agent-children {
margin-top: var(--spacing-xs); margin-top: var(--spacing-xs);
} }