SKILL.md — Agha-Akteur-Modell: Entwurf nebenläufiger Agentensysteme
Entscheidungspunkte
Strategie zur Akteurserstellung basierend auf Aufgabentyp
WENN Aufgabe sequentielle Abhängigkeiten hat:
├─ Verwende Kundenmuster: Erstelle Kind-Akteur mit Antwortadresse
├─ Übergib Kundenadresse als Parameter an Kind
└─ Kind sendet Ergebnis direkt an Kunden (nicht an Eltern)
WENN Aufgabe lange Berechnung erfordert:
├─ Erstelle unempfindlichen Akteur für die Berechnung
├─ Leite eingehende Nachrichten an Puffer-Akteur weiter
└─ Setze vom Puffer aus fort, wenn Berechnung abgeschlossen
WENN Aufgabe dynamische Ressourcenzuweisung benötigt:
├─ Erstelle Ressourcenmanager-Akteure bei Bedarf
├─ Übergib Fähigkeiten (Adressen) als Nachrichtendaten
└─ Kein zentrales Register – Adressen fließen durch das System
WENN Aufgabe Anforderungen an Fehlerisolierung hat:
├─ Erstelle überwachte Kind-Akteure für riskante Operationen
├─ Überwacher erkennt Fehler durch fehlende Antworten
└─ Ersetze fehlgeschlagene Akteure, ohne andere zu beeinflussen
WENN bestehende Agentensysteme kombiniert werden:
├─ Überprüfe, ob die Schnittstelle die kausale Struktur bewahrt
├─ Teste Verhalten unter Komposition (nicht nur Isolation)
└─ Verwende Nachrichtenprotokolle als Grenzen (kein gemeinsamer Zustand)
Entscheidungsbaum: Nachricht senden vs. Zustandsersetzung
WENN Koordination mit anderen Akteuren erforderlich:
├─ SENDE Nachrichten (ändere zuerst keinen lokalen Zustand)
├─ Füge Antwortadresse hinzu, wenn Antwort erwartet wird
└─ Nimm niemals Nachrichtenreihenfolge an
WENN lokale Berechnung erforderlich:
├─ SPEZIFIZIERE Ersetzungsverhalten
├─ Kapsele neuen Zustand ein (lege keine Interna offen)
└─ Stelle sicher, dass Nachrichten nacheinander verarbeitet werden
WENN dynamische Skalierung erforderlich:
├─ ERZEUGE neue Akteure mit spezifischen Verhaltensweisen
├─ Übergib notwendige Adressen an neue Akteure
└─ Kein gemeinsamer Initialisierungszustand
Fehlermodi
1. Anti-Pattern: Zentraler Orchestrator
Erkennung: Ein Akteur leitet alle Nachrichten weiter oder hält den gesamten Systemzustand. Symptome: Single Point of Failure, Engpass bei Last, Problem der unendlichen Regression. Behebung: Zerlege in eine Gemeinschaft von Akteuren, die jeweils nur ihren lokalen Kontext kennen. Verwende Fähigkeits-Routing.
2. Trugschluss: Synchrone Blockierung
Erkennung: Akteure warten/blockieren auf Antworten, anstatt Ersetzungsverhalten zu spezifizieren. Symptome: Deadlock unter Last, versteckte Timing-Annahmen, reduzierte Nebenläufigkeit. Behebung: Modelliere als Anfrage-Antwort-Nachrichtenpaare. Verwende das Kundenmuster für Abhängigkeiten. Wende das Muster des unempfindlichen Akteurs an.
3. Verunreinigung durch gemeinsamen Zustand
Erkennung: Mehrere Akteure lesen/schreiben dieselbe Datenstruktur (selbst mit Sperren). Symptome: Wettlaufsituationen, sequentielle Engpässe, versteckter globaler Zustand. Behebung: Kapsele Zustand in einem einzelnen Akteur. Verwende Nachrichtenaustausch für Koordination. Gegenseitiger Ausschluss ist kostenlos.
4. Nur-Ausgabe-Überprüfung
Erkennung: Tests vergleichen nur finale Ausgaben, ohne Interaktionsmuster zu prüfen. Symptome: Brock-Ackerman-Anomalie – identische Ausgaben, aber unterschiedliches Kompositionsverhalten. Behebung: Überprüfe Erhaltung der kausalen Struktur. Teste Verhalten unter Komposition. Verwende Beobachtungsäquivalenz.
5. Annahme statischer Topologie
Erkennung: Kommunikationsgraph ist beim Start festgelegt und kann zur Laufzeit nicht neu konfiguriert werden. Symptome: Offene Systeme nicht handhabbar, keine dynamische Ressourcenverwaltung, spröde bei Änderungen. Behebung: Behandle Adressen als Daten erster Klasse. Implementiere Fähigkeits-Routing. Unterstütze Topologieänderungen zur Laufzeit.
Ausgearbeitete Beispiele
Beispiel 1: Aufgabenzerlegung mit Kundenmuster
Szenario: Ein Agent muss eine komplexe Anfrage verarbeiten, die sequentielle Unteraufgaben A → B → C erfordert, muss aber für andere Nachrichten empfangsbereit bleiben.
Anfänglicher Ansatz:
Anfrage empfangen →
blockieren, während Unteraufgabe A aufgerufen wird
blockieren, während Unteraufgabe B aufgerufen wird
blockieren, während Unteraufgabe C aufgerufen wird
endgültiges Ergebnis senden
Professionelle Anwendung des Akteur-Modells:
Anfrage empfangen →
erstelle Kunden-BC-Akteur mit Adressen für B, C und endgültigen Empfänger
sende Unteraufgaben-Anfrage A an A_Verarbeiter mit Kunden-BC als Antwortadresse
spezifiziere Ersetzungsverhalten: bereit für nächste Anfrage
Kunden-BC empfängt A-Ergebnis →
sende Ergebnis an B_Verarbeiter mit Kunden-C als Antwortadresse
Kunden-C empfängt B-Ergebnis →
sende Ergebnis an C_Verarbeiter mit endgültigem_Empfänger als Antwortadresse
Getroffene Schlüsselentscheidungen:
- Kundenmuster verwendet, um Blockieren zu vermeiden
- Jeder Schritt erstellt nächsten Kunden in der Kette
- Ursprünglicher Agent bleibt durchgängig empfangsbereit
- Fehler in einer Unteraufgabe betrifft nur diese Kette
Beispiel 2: Fehlerbehebung mit Überwachung
Szenario: Ein System muss Agentenfehler behandeln, ohne dass diese auf das gesamte System übergreifen.
Anfänglicher Ansatz: Try-catch um Agentenaufrufe, alles bei Fehler neu starten.
Professionelle Anwendung:
Überwacher erstellt Arbeiter_Akteur →
sendet Aufgabe an Arbeiter mit Antwort-Timeout
spezifziert Ersetzung: "warte_auf_Antwort"
WENN Antwort innerhalb des Timeouts eintrifft →
leite Ergebnis an Kunden weiter
spezifiziere Ersetzung: "bereit"
WENN Timeout abläuft →
erstelle neuen Arbeiter_Akteur (alter ist fehlgeschlagen)
sende Aufgabe erneut an neuen Arbeiter
spezifiziere Ersetzung: "warte_auf_Antwort"
Abgewogene Kompromisse:
- Überwachung ist separates Anliegen von Geschäftslogik
- Fehlgeschlagene Akteure werden isoliert und ersetzt, nicht repariert
- Gleichgewicht zwischen Timeout-Erkennung und garantierter Zustellung
- Kein gemeinsamer Zustand zwischen Überwacher und Arbeitern
Qualitätsprüfpunkte
- Kein Akteur blockiert seine Nachrichtenverarbeitungsschleife (Muster des unempfindlichen Akteurs wo nötig angewandt)
- Alle Koordination verwendet Nachrichtenaustausch (kein veränderbarer gemeinsamer Zustand zwischen Akteuren)
- Nachrichtenzustellung ist garantiert, aber Reihenfolge wird nicht angenommen
- Adressen werden als Daten erster Klasse für Fähigkeits-Routing behandelt
- Jeder Akteur spezifiziert Ersetzungsverhalten für jeden Nachrichtentyp
- Akteurserstellung erfolgt dynamisch basierend auf Berechnungsanforderungen
- Fehlerisolierung verhindert kaskadierende Fehler über Akteurgrenzen hinweg
- Systemtopologie kann zur Laufzeit ohne zentrales Register neu konfiguriert werden
- Kompositionsverhalten wird überprüft, nicht nur isoliertes Komponentenverhalten
- Synchrone Operationen werden als Anfrage-Antwort-Nachrichtenpaare modelliert
NICHT-FÜR-Grenzen
Dieses Skill sollte NICHT verwendet werden für:
- Einfache sequentielle Berechnungen → stattdessen funktionale Programmierung verwenden
- Systeme, bei denen gemeinsamer Speicher physikalisch erforderlich ist → stattdessen Sperr-basierte Nebenläufigkeitsmuster verwenden
- Echtzeitsysteme mit harten Zeitanforderungen → stattdessen synchronen Nachrichtenaustausch mit formaler Zeitanalyse verwenden
- Mathematische Berechnungen ohne Koordination → stattdessen rein funktionale Ansätze verwenden
An andere Skills delegieren, wenn:
- Implementierung spezifischer Akteur-Frameworks → plattformspezifische Implementierungsleitfäden verwenden
- Leistungsoptimierung von Akteur-Systemen → Skill [Leistungsoptimierung] verwenden
- Formale Verifikation von Akteureigenschaften → Skill [Formale Methoden] verwenden
- Datenbankdesign für Akteur-Persistenz → Skill [Datenarchitektur] verwenden
Häufige Missverständnisse über den Umfang:
- Akteure sind nicht nur „Objekte mit asynchronen Methoden“ – sie erfordern die vollständige 3-Tupel-Antwort
- Das Akteur-Modell ist nicht nur für verteilte Systeme gedacht – es gilt für jede nebenläufige Berechnung
- Es ist nicht primär eine Leistungsoptimierung – es ist ein Rahmen für Korrektheit und Kompositionalität