Aperçu des agents
Ongrid est un système ReAct multi-agent. L'utilisateur parle toujours au coordinator — la persona racine sur la surface de chat. Quand une tâche correspond à un domaine spécialisé (investigation de cause racine profonde, revue d'action mutante, plongée réseau profonde), le coordinator dispatche vers un sous-agent (un « worker ») via l'AgentTool. Chaque worker exécute le même graph kernel contre un sac d'outils filtré et renvoie une réponse finale que le coordinator tisse dans sa réponse.
Cette page est la carte. Les pages par persona expliquent chaque agent en détail.
Personas, pas threads de chat
Une persona est un fichier sur disque décrivant ce que fait un agent. Le layout canonique — même forme que le format d'agent de Claude Code avec des clés snake_case :
---
name: specialist-disk
description: 文件系统 / 磁盘容量专家 — du / find / stat / inode / 挂载 / 大文件
when_to_use: |
When the task is about disk / filesystem health:
- Disk full / utilization climbing
- Hunt for large files / large directories
- inode exhaustion / mount point inspection
tools:
- query_knowledge
- host_find_large_files
- host_du_summary
- host_stat_file
- host_bash
- query_promql
- get_host_load
permission_mode: read-only
max_turns: 15
---
[markdown body — this becomes the system prompt]Le corps sous le frontmatter est le SystemPrompt. Deux fichiers de persona avec le même name entrent en collision et le loader logge un warning. Voir la référence du format de persona pour chaque champ.
Les personas vivent sous ./agents/ dans l'image manager (/app/agents/ à l'intérieur du conteneur). Ongrid livre des personas intégrées dans l'image et lit aussi les personas créées par l'utilisateur depuis un répertoire monté — voir Agents personnalisés.
Coordinator vs worker
| Aspect | Coordinator | Worker |
|---|---|---|
| Parle à l'utilisateur | Oui (via surface de chat ou IM) | Jamais — la sortie du worker va au coordinator |
| Sac d'outils | Large : query_*, AgentTool, redirect stubs | Étroit : whitelist tools: de la persona |
| Nom de persona | default (ou override par organisation) | specialist-*, incident-investigator, reviewer |
| Spawné par | Runtime (un par session de chat) | AgentTool ou décorateur review_gate |
| Peut spawner | Oui (des workers) | Non (les workers ne peuvent pas s'imbriquer par design) |
| Session | Longue durée, persistée | Nouvelle session par spawn, scopée à un tour |
Le job du coordinator est dispatch + triage + synthèse. Les outils de plongée profonde vivent sur les workers. Le coordinator porte des slots RedirectStub pour les outils que le LLM est connu pour halluciner (host_bash, get_host_load, …) ; appeler l'un d'eux renvoie un message de redirection qui pousse le modèle à ré-invoquer via AgentTool.
AgentTool
La primitive de dispatch du coordinator. Nom de fil AgentTool (PascalCase pour s'aligner sur le catalogue d'outils de Claude Code). Le schéma visible par le LLM :
{
"type": "object",
"properties": {
"description": {"type": "string"},
"subagent_type": {"type": "string"},
"prompt": {"type": "string"}
},
"required": ["description", "subagent_type", "prompt"]
}description— résumé de tâche en une ligne utilisé par la tile SPA.subagent_type—namede persona. Le catalogue injecté dans le system prompt du coordinator liste les valeurs valides (le registre de personas, moinsrevieweretdefault).prompt— brief complet de la tâche. Le worker ne peut pas voir le contexte du coordinator — empaquetez chaque détail nécessaire (incident_id, device_id, formulation exacte).
L'appel est synchrone du point de vue du coordinator. Il bloque jusqu'à ce que le worker atteigne completed / failed / killed. Une révision précédente avait un flag background: true async ; les modèles faibles le prenaient, répondaient à l'utilisateur avec le task_id en attente, et ne donnaient jamais suite. Le flag a disparu aujourd'hui (voir agent_tool.go pour le commentaire post-mortem). Le seul chemin async est le reviewer — et il est piloté par le décorateur, pas par le LLM.
Le dédoublonnage est intégré
Un LRU de 120s clé par sha256(subagent_type + canonical(prompt)) court-circuite le second de deux appels AgentTool identiques. Le LLM voit le résultat précédent avec un hint explicite « vous avez déjà dispatché ceci ». Réduit les explosions de boucle du coordinator (l'éval E2E D1 a vu 122 appels d'outils en 240s sans dédoublonnage).
Comment un system prompt est composé
ComposeSystemPrompt assemble le prompt reçu par le LLM, dans l'ordre :
basePrompt— le préambule universel du runtime. Peut être vide.agentProfile.SystemPrompt— le corps markdown de la persona. Le coordinator peut en porter un (la plupart le font) ; les workers en portent toujours un.agentProfile.CriticalReminder— emballé dans<critical-reminder>...</critical-reminder>. C'est la constante au niveau persona ; la couche de graphe ré-injecte aussi ce rappel par tour comme<system-reminder>pour qu'il survive à la dérive d'attention en longue session.- Pour chaque skill actif : un en-tête
[能力: <name>]+ lePromptBodydu skill.
Le coordinator reçoit un bloc supplémentaire avant la liste des skills : le catalogue d'agents (buildAgentCatalog) — une liste à puces markdown des « specialists disponibles » avec la description et la première ligne de when_to_use. Le catalogue exclut délibérément reviewer (seul le décorateur ReviewGate peut le spawner) et default (la persona racine virtuelle — la lister comme sous-agent spawnable laisserait le coordinator se spawner récursivement lui-même).
Le registre d'agents
L'AgentRegistry garde les personas parsées en mémoire. Chargement unique au démarrage ; Reload() sous un seul sync.RWMutex swap pour qu'un tour de coordinator en vol n'observe jamais un registre à moitié chargé.
| Méthode | Quand |
|---|---|
Load(root) | Démarrage. Parcourt <root>/**/*.md récursivement. |
Reload(root, ...) | Installation/désinstallation de marketplace. Swap atomique. |
ByName(name) | Lookup au moment du spawn. Renvoie (nil, false) en miss. |
Replace(ag) | Édition de user-agent. Upsert en place — registre vivant, pas de redémarrage. |
Remove(name) | Suppression de user-agent. |
Les erreurs de parse par fichier atterrissent en warnings plutôt que d'avorter la marche (même politique que le registre de skills). Les racines d'agent inexistantes ne sont pas une erreur — vous obtenez un registre vide, pas un échec de démarrage.
Reviewer et le review gate
Le reviewer est spécial : le coordinator ne peut pas le spawner. Il est gaté par le décorateur ReviewGate, qui intercepte tout outil dont la Class est "write" ou "destructive". Le décorateur :
- Construit un payload de proposition (
action,target,reason,blast_radius,operator). - Spawne le worker
reviewer(sync du point de vue de l'outil interne) avec son propre timeout de 60s, indépendant des 15s de l'outil interne. - Si le reviewer renvoie
Decision: approve, l'appel retombe vers l'outil interne. Sinon le décorateur renvoieErrReviewRejectedenveloppant la raison du reviewer.
C'est pourquoi le catalogue d'agents lâche reviewer : seul le décorateur a le droit de l'invoquer. Le mettre dans le catalogue laisserait le coordinator dispatcher des « reviews » ad-hoc qui ne gatent rien.
Voir Reviewer pour la machine à états complète.
Cycle de vie du worker
Machine à états de Runtime.SpawnWorker :
pending → running → completed
↘ failed
↘ killed (StopWorker called while running)- Une ligne
chat_sessionsest créée en amont pour que l'audit + les requêtes d'arbre parent → worker se résolvent même pendant que le worker tourne encore. - Les spawns en arrière-plan dérivent du contexte de runtime longue durée pour qu'une requête HTTP qui se termine ne puisse pas démolir le worker en plein run ; les spawns sync héritent du ctx de l'appelant.
- La ligne de session est fermée (
closed_atposé) sur chaque chemin terminal, y compris les paniques — sans ça, des lignes orphelines s'accumulent (l'environnement de test a atteint 161 avant que le correctif n'atterrisse).
Les workers ne peuvent pas spawner de workers. SpawnWorker n'est exposé que sur le Runtime, et le filtre disabledForWorker retire AgentTool du sac d'outils de tout worker. Un coordinator, N workers parallèles, pas d'imbrication plus profonde.
La suite
- Coordinator — la persona par défaut, ses trois outils de contrôle, et quand dispatcher vs répondre directement.
- Incident investigator — cause racine jusqu'au « patient zéro », budget de 18 outils, et l'éval F1.
- Specialists — compute / disk / network / ops / sre, ce que possède chacun, comment le coordinator choisit.
- Reviewer — le gate de double signature SOP sur les outils mutants.
- Agents personnalisés — écrivez votre propre persona, hot-reload, debug.