- Startseite
- Documentation
- Laufzeitwerkzeuge
- Task-Agent-Erkennung und -Auswahl
Task-Agent-Erkennung und -Auswahl
Dieses Dokument beschreibt, wie das Task-Subsystem Agent-Definitionen erkennt, mehrere Quellen zusammenführt und einen angeforderten Agent zur Ausführungszeit auflöst.
Es behandelt das Laufzeitverhalten, wie es heute implementiert ist, einschließlich Vorrangregeln, Behandlung ungültiger Definitionen und Spawn-/Tiefenbeschränkungen, die einen Agent effektiv unerreichbar machen können.
Implementierungsdateien
Abschnitt betitelt „Implementierungsdateien“src/task/discovery.tssrc/task/agents.tssrc/task/types.tssrc/task/index.tssrc/task/commands.tssrc/prompts/agents/task.mdsrc/prompts/tools/task.mdsrc/discovery/helpers.tssrc/config.tssrc/task/executor.ts
Form der Agent-Definition
Abschnitt betitelt „Form der Agent-Definition“Task-Agents werden in AgentDefinition (src/task/types.ts) normalisiert:
name,description,systemPrompt(erforderlich für einen gültig geladenen Agent)- optionale
tools,spawns,model,thinkingLevel,output source:"bundled" | "user" | "project"- optionaler
filePath
Das Parsing erfolgt über Frontmatter mittels parseAgentFields() (src/discovery/helpers.ts):
- fehlender
nameoderdescription=> ungültig (null), Aufrufer behandelt dies als Parse-Fehler toolsakzeptiert CSV oder Array; falls angegeben, wirdsubmit_resultautomatisch hinzugefügtspawnsakzeptiert*, CSV oder Array- Abwärtskompatibilitätsverhalten: falls
spawnsfehlt, abertoolstaskenthält, wirdspawnszu* outputwird als opake Schema-Daten durchgereicht
Mitgelieferte Agents
Abschnitt betitelt „Mitgelieferte Agents“Mitgelieferte Agents werden zur Build-Zeit eingebettet (src/task/agents.ts) mittels Text-Imports.
EMBEDDED_AGENT_DEFS definiert:
explore,plan,designer,revieweraus Prompt-Dateientaskundquick_taskaus dem gemeinsamentask.md-Body plus injiziertem Frontmatter
Ladepfad:
loadBundledAgents()parst eingebettetes Markdown mitparseAgent(..., "bundled", "fatal")- Ergebnisse werden im Speicher gecacht (
bundledAgentsCache) clearBundledAgentsCache()ist ein nur für Tests vorgesehener Cache-Reset
Da das Parsing der mitgelieferten Agents level: "fatal" verwendet, führt fehlerhaftes mitgeliefertes Frontmatter zu einem Throw und kann die Erkennung vollständig fehlschlagen lassen.
Dateisystem- und Plugin-Erkennung
Abschnitt betitelt „Dateisystem- und Plugin-Erkennung“discoverAgents(cwd, home) (src/task/discovery.ts) führt Agents aus mehreren Quellen zusammen, bevor mitgelieferte Definitionen angehängt werden.
Erkennungsquellen
Abschnitt betitelt „Erkennungsquellen“- Benutzer-Konfigurationsverzeichnisse für Agents aus
getConfigDirs("agents", { project: false }) - Nächstgelegene Projekt-Agent-Verzeichnisse aus
findAllNearestProjectConfigDirs("agents", cwd) - Claude-Plugin-Stammverzeichnisse (
listClaudePluginRoots(home)) mitagents/-Unterverzeichnissen - Mitgelieferte Agents (
loadBundledAgents())
Tatsächliche Quellreihenfolge
Abschnitt betitelt „Tatsächliche Quellreihenfolge“Die Reihenfolge der Quellfamilien ergibt sich aus getConfigDirs("", { project: false }), das von priorityList in src/config.ts abgeleitet wird:
.xcsh.claude.codex.gemini
Für jede Quellfamilie ist die Erkennungsreihenfolge:
- Nächstgelegenes Projektverzeichnis für diese Quelle (falls gefunden)
- Benutzerverzeichnis für diese Quelle
Nach allen Quellfamilien-Verzeichnissen werden Plugin-agents/-Verzeichnisse angehängt (zuerst Projekt-Scope-Plugins, dann Benutzer-Scope).
Mitgelieferte Agents werden zuletzt angehängt.
Wichtiger Vorbehalt: veraltete Kommentare vs. aktueller Code
Abschnitt betitelt „Wichtiger Vorbehalt: veraltete Kommentare vs. aktueller Code“Die Header-Kommentare in discovery.ts erwähnen noch .pi und nennen .codex/.gemini nicht. Die tatsächliche Laufzeitreihenfolge wird von src/config.ts gesteuert und verwendet derzeit .xcsh, .claude, .codex, .gemini.
Zusammenführung und Kollisionsregeln
Abschnitt betitelt „Zusammenführung und Kollisionsregeln“Die Erkennung verwendet First-Wins-Deduplizierung nach exaktem agent.name:
- Ein
Set<string>verfolgt bereits gesehene Namen. - Geladene Agents werden in Verzeichnisreihenfolge abgeflacht und nur beibehalten, wenn der Name noch nicht gesehen wurde.
- Mitgelieferte Agents werden gegen dasselbe Set gefiltert und nur hinzugefügt, wenn sie noch nicht gesehen wurden.
Auswirkungen:
- Projekt überschreibt Benutzer für dieselbe Quellfamilie.
- Höher priorisierte Quellfamilie überschreibt niedrigere (
.xcshvor.claude, etc.). - Nicht-mitgelieferte Agents überschreiben mitgelieferte Agents mit demselben Namen.
- Namensabgleich ist case-sensitiv (
Taskundtasksind unterschiedlich). - Innerhalb eines Verzeichnisses werden Markdown-Dateien vor der Deduplizierung in lexikographischer Dateinamen-Reihenfolge gelesen.
Verhalten bei ungültigen/fehlenden Agent-Dateien
Abschnitt betitelt „Verhalten bei ungültigen/fehlenden Agent-Dateien“Pro Verzeichnis (loadAgentsFromDir):
- unlesbar/fehlendes Verzeichnis: wird als leer behandelt (
readdir(...).catch(() => [])) - Dateilesung oder Parse-Fehler: Warnung wird protokolliert, Datei wird übersprungen
- Parse-Pfad verwendet
parseAgent(..., level: "warn")
Verhalten bei Frontmatter-Fehlern stammt von parseFrontmatter:
- Parse-Fehler auf
warn-Level protokolliert eine Warnung - Parser fällt auf einen einfachen
key: value-Zeilenparser zurück - wenn erforderliche Felder weiterhin fehlen, schlägt
parseAgentFieldsfehl, dann wirdAgentParsingErrorgeworfen und vom Aufrufer abgefangen (Datei wird übersprungen)
Nettoeffekt: Eine fehlerhafte benutzerdefinierte Agent-Datei bricht die Erkennung anderer Dateien nicht ab.
Agent-Suche und -Auswahl
Abschnitt betitelt „Agent-Suche und -Auswahl“Die Suche ist eine exakte Namens-Linearsuche:
getAgent(agents, name)=>agents.find(a => a.name === name)
Bei der Task-Ausführung (TaskTool.execute):
- Agents werden zum Aufrufzeitpunkt neu erkannt (
discoverAgents(this.session.cwd)) - angeforderter
params.agentwird übergetAgentaufgelöst - fehlender Agent gibt eine sofortige Tool-Antwort zurück:
Unknown agent "...". Available: ...- kein Subprozess wird gestartet
Beschreibung vs. Erkennung zur Ausführungszeit
Abschnitt betitelt „Beschreibung vs. Erkennung zur Ausführungszeit“TaskTool.create() erstellt die Tool-Beschreibung aus den Erkennungsergebnissen zum Initialisierungszeitpunkt (buildDescription).
execute() erkennt Agents erneut. Daher kann sich die Laufzeitmenge von dem unterscheiden, was in der früheren Tool-Beschreibung aufgelistet war, wenn sich Agent-Dateien während der Sitzung geändert haben.
Structured-Output-Schutzmechanismen und Schema-Vorrang
Abschnitt betitelt „Structured-Output-Schutzmechanismen und Schema-Vorrang“Vorrang des Laufzeit-Ausgabeschemas in TaskTool.execute:
- Agent-Frontmatter
output - Task-Aufruf
params.schema - Eltern-Sitzung
outputSchema
(effectiveOutputSchema = effectiveAgent.output ?? outputSchema ?? this.session.outputSchema)
Der Prompt-Schutzmechanismus-Text in src/prompts/tools/task.md warnt vor Abweichungsverhalten bei Structured-Output-Agents (explore, reviewer): Ausgabeformat-Anweisungen im Prosatext können mit dem eingebauten Schema in Konflikt geraten und null-Ausgaben erzeugen.
Dies ist eine Orientierungshilfe, keine harte Laufzeit-Validierungslogik in discoverAgents.
Interaktion mit der Befehlserkennung
Abschnitt betitelt „Interaktion mit der Befehlserkennung“src/task/commands.ts ist eine parallele Infrastruktur für Workflow-Befehle (keine Agent-Definitionen), folgt aber dem gleichen Gesamtmuster:
- zuerst von Capability-Providern erkennen
- nach Namen mit First-Wins deduplizieren
- mitgelieferte Befehle anhängen, wenn noch nicht gesehen
- exakte Namenssuche über
getCommand
In src/task/index.ts werden Befehls-Hilfsfunktionen zusammen mit Agent-Erkennungs-Hilfsfunktionen re-exportiert. Die Agent-Erkennung selbst hängt zur Laufzeit nicht von der Befehlserkennung ab.
Verfügbarkeitsbeschränkungen jenseits der Erkennung
Abschnitt betitelt „Verfügbarkeitsbeschränkungen jenseits der Erkennung“Ein Agent kann erkennbar, aber dennoch nicht ausführbar sein, aufgrund von Ausführungsschutzmechanismen.
Eltern-Spawn-Richtlinie
Abschnitt betitelt „Eltern-Spawn-Richtlinie“TaskTool.execute prüft session.getSessionSpawns():
"*"=> alle erlauben""=> alle ablehnen- CSV-Liste => nur aufgelistete Namen erlauben
Bei Ablehnung: sofortige Cannot spawn '...'. Allowed: ...-Antwort.
Blockierte Selbstrekursions-Umgebungssperre
Abschnitt betitelt „Blockierte Selbstrekursions-Umgebungssperre“PI_BLOCKED_AGENT wird bei der Tool-Konstruktion gelesen. Wenn die Anfrage übereinstimmt, wird die Ausführung mit einer Rekursionsverhinderungsnachricht abgelehnt.
Rekursionstiefe-Steuerung (Task-Tool-Verfügbarkeit in Kind-Sitzungen)
Abschnitt betitelt „Rekursionstiefe-Steuerung (Task-Tool-Verfügbarkeit in Kind-Sitzungen)“In runSubprocess (src/task/executor.ts):
- Tiefe wird aus
taskDepthberechnet task.maxRecursionDepthsteuert den Grenzwert- bei maximaler Tiefe:
task-Tool wird aus der Kind-Tool-Liste entfernt- Kind-
spawns-Umgebung wird auf leer gesetzt
Tiefere Ebenen können daher keine weiteren Tasks spawnen, selbst wenn die Agent-Definition spawns enthält.
Planmodus-Vorbehalt (aktuelle Implementierung)
Abschnitt betitelt „Planmodus-Vorbehalt (aktuelle Implementierung)“TaskTool.execute berechnet einen effectiveAgent für den Planmodus (stellt Planmodus-Prompt voran, erzwingt schreibgeschützte Tool-Teilmenge, leert Spawns), aber runSubprocess wird mit agent anstelle von effectiveAgent aufgerufen.
Aktuelle Auswirkung:
- Model-Override / Thinking-Level / Ausgabeschema werden von
effectiveAgentabgeleitet - System-Prompt und Tool-/Spawn-Einschränkungen von
effectiveAgentwerden in diesem Aufrufpfad nicht weitergegeben
Dies ist ein Implementierungsvorbehalt, den man kennen sollte, wenn man Erwartungen an das Planmodus-Verhalten liest.