Référence : le fichier de configuration
- Version du format : 1
- Issue : #4 — Spécifier le format du fichier de configuration YAML
- Schéma : schema/config.schema.json (JSON Schema 2020-12), vérifié par
go test ./schema - Exemple : examples/test-agents.yaml
Un fichier YAML décrit les agents avec lesquels Sidekicks peut converser, les channels créés au démarrage et les préférences. Les conversations, les messages et les sessions ACP n'y figurent pas (voir Architecture).
L'application le lit avec le package Go internal/config (milestone M1) : validation, valeurs par défaut, chemins, fichier par défaut, rechargement à chaque enregistrement.
Emplacement
Le fichier est cherché dans cet ordre ; la première source applicable l'emporte :
| # | Source | Exemple |
|---|---|---|
| 1 | option de ligne de commande --config <chemin> |
sidekicks --config ~/agents/equipe.yaml |
| 2 | variable d'environnement SIDEKICKS_CONFIG |
SIDEKICKS_CONFIG=~/agents/equipe.yaml |
| 3 | le dernier fichier ouvert depuis l'application (Settings → Open… ou Recent…), conservé dans <dossier de config utilisateur>/sidekicks/preferences.json |
— |
| 4 | l'emplacement par défaut : <dossier de config utilisateur>/sidekicks/config.yaml |
macOS : ~/Library/Application Support/sidekicks/config.yaml, Linux : ~/.config/sidekicks/config.yaml |
<dossier de config utilisateur> est celui de os.UserConfigDir() en Go. Si le fichier par défaut n'existe pas, Sidekicks le crée avec des commentaires qui expliquent chaque clé (issue #9).
Chemins
- Un chemin relatif est résolu par rapport au dossier du fichier de configuration, jamais par rapport au dossier courant. Un dossier qui contient une configuration et ses agents peut donc être déplacé ou versionné avec git d'un seul tenant.
~en début de chemin désigne le dossier personnel de l'utilisateur.command: un nom seul (mm,docker) est cherché dans lePATH; tout ce qui contient/est un chemin, résolu comme ci-dessus.argsest transmis tel quel, sans réécriture : le processus de l'agent démarre dans sonworkspace, donc les arguments relatifs au workspace fonctionnent.
Clés
Racine
| Clé | Type | Obligatoire | Défaut | Signification |
|---|---|---|---|---|
version |
entier | oui | — | Version du format ; seule 1 existe. Un format ultérieur l'incrémente, pour que Sidekicks puisse migrer ou refuser explicitement un ancien fichier. |
ui |
objet | non | Préférences d'interface. | |
limits |
objet | non | Limites de ressources. | |
agents |
liste d'agents | oui | Les agents disponibles avec @nom. Peut être vide. |
|
channels |
liste de channels | non | [] |
Channels créés au démarrage s'ils n'existent pas encore. |
Les clés inconnues sont des erreurs, à tous les niveaux : une faute de frappe comme comand: doit être signalée, pas ignorée en silence.
ui
| Clé | Valeurs | Défaut | Signification |
|---|---|---|---|
theme |
system, light, dark |
system |
Thème de couleurs ; system suit le système d'exploitation. |
language |
en, fr |
en |
Langue de l'interface : ses libellés et les messages d'erreur de la configuration. |
limits
| Clé | Type | Défaut | Signification |
|---|---|---|---|
maxRunningAgents |
entier ≥ 1 | 2 |
Agents actifs en même temps. Chaque agent local garde un modèle en mémoire ; la valeur par défaut convient à un portable de 32 Go avec de petits modèles. |
stopIdleAgentsAfter |
durée Go (30s, 10m, 1h30m), ou 0 (nombre ou texte) |
10m |
Arrête un agent inutilisé depuis ce délai pour libérer sa mémoire. 0 ne l'arrête jamais. |
Un agent
| Clé | Type | Obligatoire | Défaut | Signification |
|---|---|---|---|---|
name |
identifiant | oui | Minuscules, chiffres, -, _ ; commence par une lettre ; 32 caractères au plus. Sert dans @nom et /nom:commande. Unique. |
|
title |
texte | non | name |
Nom affiché dans l'interface. |
icon |
texte (un emoji ou une lettre) | non | Affiché à côté de l'agent. Un emoji est affiché tel quel ; sinon sa première lettre est affichée dans un rond coloré (la couleur dépend de name). Sans icon, le rond contient la première lettre de title. |
|
description |
texte | non | Une phrase affichée dans la liste @. |
|
command |
texte | oui | Programme qui sert ACP sur stdio. | |
args |
liste de textes | non | [] |
Ses arguments. |
env |
dictionnaire texte → texte | non | Variables d'environnement supplémentaires. | |
afterStop |
liste de textes, au moins un | non | Commande lancée à chaque fin du processus de l'agent — arrêt, crash, arrêt pour faire de la place, ou fermeture de Sidekicks : le programme (un nom seul est cherché dans le PATH, un chemin est relatif à ce fichier), puis ses arguments. Elle tourne dans workspace avec env, 30 s au plus ; sa sortie va dans le journal de l'agent ; Sidekicks l'attend avant de se fermer. Un programme introuvable est un avertissement. Exemple : [../scripts/agents.sh, unload, alice] pour décharger le modèle. |
|
workspace |
chemin | non | le dossier de la configuration | Le dossier de l'agent : le processus y démarre et c'est le cwd de ses sessions ACP. mm y lit AGENTS.md et skills/. |
protect |
liste de textes | non | Fichiers du dossier de l'agent que l'interface (onglet Files) ne peut ni modifier ni supprimer : chemins relatifs au dossier, ou motifs où * et ? remplacent des caractères d'un nom et ** un nombre quelconque de dossiers ([AGENTS.md, "skills/**"]). Un dossier qui contient un fichier protégé ne peut pas être supprimé. Toujours protégés, s'ils sont dans son dossier : AGENTS.md, skills/**, le fichier de configuration de l'agent (l'argument qui suit --config, -config ou serve acp dans args), et les fichiers à partir desquels runtime.lifecycle construit le conteneur ou la sandbox — le fichier Compose (après -f/--file, ou compose.yaml… sans lui), le Dockerfile du dossier des commandes pour un conteneur, le fichier d'environnement sbx (sbxenv.yaml ou celui nommé). Seule la configuration lève une protection ; l'agent lui-même, le terminal ou le Finder n'y sont pas soumis. |
|
runtime |
objet | non | {type: local} |
Où tourne l'agent (voir ci-dessous). |
runtime
Le runtime indique à Sidekicks comment atteindre les fichiers et le terminal de l'agent (panel Agents, issue #28). Il ne change pas la façon de démarrer l'agent : c'est le rôle de command et args.
type |
Clés supplémentaires | Signification |
|---|---|---|
local |
aucune | L'agent tourne sur cet ordinateur ; workspace est un dossier local. |
container |
container (obligatoire), workspacePath, lifecycle |
L'agent tourne dans un conteneur Docker ; fichiers et terminal passent par docker exec. Un conteneur arrêté est démarré avant l'agent. |
sbx |
sandbox (obligatoire), workspacePath, lifecycle |
L'agent tourne dans une sandbox Docker (sbx) ; fichiers et terminal passent par sbx exec. |
workspacePath est un chemin absolu dans le conteneur ou la sandbox ; par défaut, celui de workspace (le même chemin, comme avec un dossier monté). Comportement de chaque runtime : workspaces.
runtime.lifecycle (conteneur et sbx)
Commandes facultatives qui gèrent le conteneur ou la sandbox de l'agent (issues #47 et #48). Chaque commande est une liste : le programme (un nom seul est cherché dans le PATH, un chemin est relatif à ce fichier), puis ses arguments.
| Clé | Type | Par défaut | Signification |
|---|---|---|---|
folder |
texte | workspace |
Dossier où les commandes sont lancées. Relatif à ce fichier ; ~ est le dossier personnel. |
create |
liste de textes, au moins un | Crée le conteneur ou la sandbox. Avant de démarrer l'agent, Sidekicks vérifie qu'il existe (docker container inspect, sbx ls -q) ; sinon, il lance cette commande, puis vérifie à nouveau. |
|
stop |
liste de textes, au moins un | L'arrête. Proposé par ■ Arrêter le conteneur / ■ Arrêter la sandbox dans le panel Agents ; l'agent est arrêté d'abord. | |
remove |
liste de textes, au moins un | Le supprime. Proposé par 🗑 Supprimer le conteneur / 🗑 Supprimer la sandbox dans le panel Agents, après confirmation ; l'agent est arrêté d'abord. |
Une sandbox arrêtée n'a besoin de rien : sbx exec la démarre. Un conteneur arrêté est démarré par docker start, même sans lifecycle. Les commandes ne reçoivent aucune entrée (une commande qui pose une question échoue), tournent avec l'env de l'agent, et ce qu'elles affichent va dans le journal de l'agent, préfixé par sandbox: . Un create qui échoue met l'agent en état error avec la raison.
runtime:
type: sbx
sandbox: milo-sbx # le name: du sbxenv.yaml
lifecycle:
folder: /Users/moi/agents/milo # là où est sbxenv.yaml
create: [sbx, env, create, --force]
stop: [sbx, stop, milo-sbx]
remove: [sbx, env, rm, --force]
Avec un fichier d'environnement qui ne s'appelle pas sbxenv.yaml, nommez-le : [sbx, env, create, dev.yaml, --force], [sbx, env, rm, dev.yaml, --force]. Sans fichier d'environnement, utilisez les commandes simples, par exemple remove: [sbx, rm, milo-sbx, --force].
Un conteneur d'un service Docker Compose (ce qu'écrit l'assistant quand un compose.yaml est déposé) :
runtime:
type: container
container: team-scout-1 # container_name, ou <projet>-<service>-1
lifecycle:
folder: /Users/moi/agents/team # là où est compose.yaml
create: [docker, compose, -f, compose.yaml, up, -d, --wait, scout]
stop: [docker, compose, -f, compose.yaml, stop, scout]
remove: [docker, compose, -f, compose.yaml, rm, --stop, --force, scout]
up --wait rend la main une fois le service démarré (en bonne santé, s'il a un healthcheck) ; rm --stop --force scout supprime seulement le conteneur de ce service, pas les autres services comme le ferait down. Sans Compose : create: [docker, run, -d, --name, scout-box, -v, "/Users/moi/agents/scout:/Users/moi/agents/scout", mon-image].
Un channel
| Clé | Type | Obligatoire | Signification |
|---|---|---|---|
name |
texte, 1 à 64 caractères | oui | Affiché #nom. Unique. Accents et espaces autorisés. |
description |
texte | non | Affichée au survol du nom du channel, et dans un channel vide. |
agents |
liste de noms d'agents | non | Membres du channel. Un agent de la liste qui n'est pas encore membre est ajouté au démarrage et au rechargement du fichier ; le retirer de la liste ne retire rien. Sans doublon. |
Un channel déclaré ici est créé au démarrage, ou au rechargement du fichier, si aucun channel ne porte encore ce nom (sans tenir compte de la casse) ; il vit ensuite dans l'application comme n'importe quel channel, et peut y être renommé ou supprimé. Le retirer du fichier ne le supprime pas (supprimer un historique doit être une action explicite de l'utilisateur). Chaque fichier de configuration a ses propres channels et son propre historique (où il est gardé).
Ce qu'écrit l'assistant « Ajouter un agent »
L'assistant ajoute une entrée à la fin de agents ; le reste du fichier, commentaires compris, est gardé. Rien n'est écrit si le résultat ne serait pas valide.
| Champ de l'assistant | Écrit comme |
|---|---|
| Nom utilisé avec @, Nom affiché, Icône, Ce qu'il fait | name, title, icon, description (champs vides omis) |
| Dossier de l'agent | workspace, tel que saisi (~ et chemins relatifs résolus comme tout workspace) |
| Sur cet ordinateur | command: <programme>, args: [<arguments>] |
| Dans un conteneur Docker | command: docker, args: [exec, -i, <conteneur>, <programme>, <arguments>], runtime: {type: container, container: <conteneur>} |
| Dans une sandbox sbx | command: sbx, args: [exec, -i, <sandbox>, <programme>, <arguments>], runtime: {type: sbx, sandbox: <sandbox>} |
| Dossier où les commandes sont lancées, Commande qui crée / arrête / supprime la sandbox (sbx uniquement) | runtime.lifecycle: {folder, create, stop, remove}, chaque commande découpée comme les arguments ; omis si aucune commande n'est donnée |
Les arguments sont découpés comme le ferait un shell dans les cas simples : les espaces séparent, les guillemets simples ou doubles regroupent. Le programme est découpé de la même façon, sauf si c'est un chemin (il commence par / ou ~) : docker agent donne command: docker et agent comme premier argument.
Quand le fichier de configuration de l'agent est indiqué (déposé ou choisi, où que tourne l'agent : une sandbox sbx partage les dossiers de l'hôte au même chemin, et un conteneur doit monter le dossier du fichier au même chemin), le dossier de l'agent est celui du fichier, et les arguments utilisent le chemin absolu du fichier :
| Programme | Arguments |
|---|---|
mm |
--acp --config <fichier> |
docker-agent |
serve acp <fichier> |
docker agent |
serve acp <fichier> (écrit command: docker, args: [agent, serve, acp, <fichier>]) |
| tout autre | inchangés : tapés par l'utilisateur |
Règles vérifiées par le chargeur, pas par le schéma
JSON Schema ne sait pas les exprimer ; le chargeur de configuration (issue #9) les vérifie et les signale comme les erreurs de schéma :
- les noms d'agents sont uniques ;
- les noms de channels sont uniques ;
- chaque nom de la liste
agentsd'un channel est le nom d'un agent ; commandexiste (dans lePATH, ou comme fichier) — signalé comme avertissement, car un agent peut être installé plus tard.
Messages d'erreur
Chaque erreur indique la ligne et la clé, dans la langue de l'interface, et dit comment corriger. Exemples avec l'interface en français (language: fr) :
| Problème | Message |
|---|---|
name: Alice Smith |
ligne 12 — agents[0].name : « Alice Smith » n'est pas un nom valide : minuscules, chiffres, « - » ou « _ », sans espace, en commençant par une lettre (ex. « alice ») |
comand: mm |
ligne 14 — agents[0].comand : clé inconnue « comand » ; vouliez-vous dire « command » ? |
command absente |
ligne 3 — agents[0] : il manque la clé « command » |
Exemple complet
version: 1
ui:
theme: system
language: fr
limits:
maxRunningAgents: 2
stopIdleAgentsAfter: 10m
agents:
- name: alice
title: Alice (assistante)
icon: "👩"
description: Questions simples, sans outils
command: mm
args: ["-acp", "-config", "agent.yaml"]
workspace: ./agents/alice
- name: garfield
title: Garfield (traducteur)
icon: "🐮"
command: mm
args: ["-acp", "-config", "agent.yaml"]
workspace: ./agents/garfield
- name: translator-sbx
title: Traducteur (sandbox)
command: sbx
args: ["exec", "-i", "mm-translator", "mm", "-acp"]
workspace: ./agents/translator/workspace
runtime:
type: sbx
sandbox: mm-translator
channels:
- name: général
agents: [alice]
- name: traductions
agents: [garfield]
sbx exec -i <sandbox> <programme> lance l'agent dans la sandbox ; sbx monte le dossier de l'hôte au même chemin, donc workspace est aussi le dossier vu à l'intérieur. Cet exemple est aussi un cas de test (schema/testdata/valid/spec-example.yaml).
Package Go schema
git.rickub.com/bots-garden/sidekicks/schema embarque le JSON Schema et valide des documents avec lui.
| Identifiant | Signature | Description |
|---|---|---|
ConfigSchemaURL |
const string |
Le $id du schéma : https://git.rickub.com/bots-garden/sidekicks/schema/config.schema.json. |
ConfigSchema |
func() []byte |
Une copie du document JSON Schema. |
ValidateConfig |
func(document []byte) error |
nil si le document YAML respecte le schéma ; une erreur de syntaxe YAML s'il ne peut pas être lu ; sinon une *jsonschema.ValidationError qui liste toutes les violations. |
if err := schema.ValidateConfig(content); err != nil {
fmt.Println("configuration invalide :", err)
}
Une violation telle que la renvoie ValidateConfig :
jsonschema validation failed with 'https://git.rickub.com/bots-garden/sidekicks/schema/config.schema.json#'
- at '/agents/0': additional properties 'comand' not allowed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
|