Aller au contenu

Track A — Configuration et vérification

Chaque acteur livre un seul artefact canonique au marketplace : src/kaoohi/config.json. La plateforme le lit dans votre image de conteneur à l’enregistrement, rend depuis lui le formulaire de déploiement du kompanion, et base dessus sa revue de sécurité. Cette page explique d’où il vient, pourquoi vous ne l’éditez jamais à la main, et la boucle qui le garde honnête.

config.json est dérivé. Deux entrées, un émetteur :

src/config.py Settings fields ─┐
(x-kaoohi-* annotations)├─→ src/kaoohi/config_emitter.py ─→ src/kaoohi/config.json
[tool.kaoohi] in pyproject.toml ─┘ (emit + validate) (checked in, derived)

L’émetteur parcourt chaque champ Settings via model_fields Pydantic (y compris ceux hérités du mixin), mappe les types, lit les annotations x-kaoohi-*, et fusionne le résultat avec le bloc marketplace [tool.kaoohi]. La sortie est validée contre le src/kaoohi/schema.json embarqué plus les règles d’accord A–H — celles que vous rencontrerez vraiment :

  • Règle A — un élément requis géré par l’utilisateur ne peut pas être caché : l’utilisateur n’aurait aucun moyen de le fournir.
  • Règle B — un élément géré par la plateforme qui est visible doit porter un creator_value (votre valeur, affichée comme défaut prérempli).
  • Règle C — fed_by_connector doit référencer un connecteur déclaré dans required_connectors / optional_connectors.
  • Règle F — creator_value et fed_by_connector sont mutuellement exclusifs : l’identifiant du compte qui déploie et la valeur de l’auteur de l’acteur ne peuvent pas tous deux revendiquer un champ.
  • Règle G — un élément de type secret ne doit jamais porter de valeur, ni creator_value ni default. Un acteur qui livre une valeur secrète échoue.
  • Règle H — order doit être unique dans une section ; la plateforme trie le formulaire dessus.

Une violation n’est pas un avertissement : le Dockerfile a une étape kaoohi-config dédiée qui rejoue l’émetteur avec --check pendant le build de l’image, donc une configuration mal formée fait échouer le build, avant que quoi que ce soit ne parte. Le même fichier est cuit dans l’image et servi sur GET /api/actor/kaoohi-config.

Le json_schema_extra de chaque champ Settings parle l’espace de noms x-kaoohi-* :

Annotation Rôle
x-kaoohi-section Id de section du formulaire (doit exister dans KAOOHI_SECTIONS)
x-kaoohi-managed-by "user" (l’acheteur le remplit) ou "platform" (l’orchestrateur l’injecte)
x-kaoohi-ui Widget (text, textarea, password, select, radio, slider, switch, number), order, options, step, placeholder, show_if, display
x-kaoohi-fed-by-connector Slug du connecteur dont l’identifiant fournit ce champ au déploiement
x-kaoohi-creator-value Valeur préremplie de l’auteur de l’acteur pour un champ visible géré par la plateforme
x-kaoohi-required Surcharge le caractère requis de Pydantic dans l’élément émis
x-kaoohi-validation Règles min/max/enum/pattern passées au formulaire
x-kaoohi-env-var Surcharge le nom de la variable d’environnement (défaut : nom du champ en majuscules)

Trois concepts font le vrai travail :

  • managed_by décide qui remplit le champ : l’acheteur (user) ou la plateforme (platform). Les champs gérés par la plateforme sont normalement cachés.
  • creator_value, c’est vous, le kreator, qui préremplissez une valeur — un délai par défaut, un ID de template. Apparié avec managed_by: "platform" + visible selon la règle B.
  • fed_by_connector déclare que l’identifiant connecté du compte qui déploie fournit le champ — une URL n8n, un jeton de boîte mail. Le connecteur doit être déclaré (règle C) et ne peut pas concurrencer un creator_value (règle F).

Un widget password correspond au type secret, qui déclenche la règle G — donc les champs secrets sont SecretStr | None = Field(default=None, ...) sans valeur livrée, jamais.

Après chaque changement de configuration ou de code, exécutez la boucle dans cet ordre :

Fenêtre de terminal
# 1. Lint — zero tolerance, the fleet lints clean
ruff check src/
# 2. Emit + freshness check in one target
make kaoohi-config
# = python -m src.kaoohi.config_emitter
# + python -m src.kaoohi.config_emitter --check (fails if stale)
# 3. Tests — unit tests plus the contract tests vendored in every actor
pytest

Utile aussi : make kaoohi-config-check (juste la porte de fraîcheur) et make kaoohi-config-stdout (affiche la configuration sans l’écrire). La suite embarquée inclut les tests qui protègent le contrat :

  • test_contract.py — l’OpenAPI de l’acteur doit satisfaire le contrat inter-acteurs requis (modèles et endpoints de santé compris).
  • test_kaoohi_config_emitter.py — comportement de l’émetteur, application des règles et validation [tool.kaoohi] comprises.
  • test_system_prompt.py — vos PINNED_PHRASES apparaissent toujours dans le prompt.

Enfin, confirmez ce que la plateforme verra réellement :

Fenêtre de terminal
curl http://localhost:8080/api/actor/kaoohi-config | python -m json.tool

Cela sert la ressource cuite dans le paquet — les mêmes octets que le marketplace extrait de votre image. Après émission, committez le src/kaoohi/config.json dérivé aux côtés du changement source qui l’a produit ; un fichier périmé fait échouer le build d’image plus tard, ce qui est le bon mode d’échec.

Quand kaboum publie des correctifs, intégrez-les :

Fenêtre de terminal
cd /path/to/my-actor
copier update --trust

Copier rejoue vos réponses enregistrées dans .copier-answers.yml — framework, intégration et choix marketplace sont conservés, pas remis aux défauts — et applique un merge à 3 voies : la version depuis laquelle vous avez généré, vos modifications, et le nouveau template. Les fichiers que vous n’avez jamais touchés se mettent à jour proprement.

Là où le template a changé un fichier que vous aviez aussi changé, Copier écrit un fichier .rej (un patch rejeté) à côté de la source et laisse votre version en place. Résolvez chacun délibérément :

  1. Ouvrez le fichier .rej pour lire le changement du template.
  2. Appliquez-le à la main au fichier principal, en gardant votre logique de domaine.
  3. Supprimez le fichier .rej.
  4. Exécutez la boucle de vérification ci-dessus avant de continuer.

Les conflits que vous verrez le plus sont exactement ceux que les points d’extension ont été conçus pour éviter : des éditions des prompts possédés par le template au lieu de ROLE_PLAYBOOK, ou des dizaines de champs de domaine dans src/config.py section 4.

Les acteurs très personnalisés accumulent des dizaines de champs Settings — et chaque copier update rend à nouveau src/config.py, donc ces champs entrent en conflit à chaque fois. Le flag mixin les déplace dans un fichier possédé par l’acteur que le template scaffolde une fois et ne réécrit jamais :

# src/config_actor.py (actor-owned — copier update never conflicts here)
from pydantic import Field
from pydantic_settings import BaseSettings
ACTOR_KAOOHI_SECTIONS = [
{"id": "routing", "name": "Routing", "description": "Call routing rules"},
]
class ActorSettingsMixin(BaseSettings):
routing_timeout: int = Field(
default=30,
description="Seconds before an unanswered call is escalated",
json_schema_extra={
"x-kaoohi-section": "routing",
"x-kaoohi-managed-by": "user",
# 200+ range: template orders stop below 100, so you never collide
"x-kaoohi-ui": {"widget": "slider", "order": 200},
},
)

src/config.py importe ActorSettingsMixin et la classe de configuration en hérite ; les champs du mixin se chargent depuis l’environnement et coulent dans le config.json émis exactement comme les champs du template. Vos sections s’ajoutent après celles du template, dédoublonnées par id — vous pouvez ajouter des sections mais jamais redéfinir une section du template.

Activez-le à la génération (include_actor_config_mixin=true) ou quand un conflit de configuration vous a déjà coûté un après-midi. La plupart des acteurs n’en ont jamais besoin : les sept points d’extension plus ROLE_PLAYBOOK existent précisément pour que le chemin courant reste sans conflit.

Avec la configuration vérifiée et les mises à jour apprivoisées, la boucle restante est le build et la publication — couvertes dans les pages de déploiement de Track A et dans la référence de configuration de kaboum pour le catalogue complet des paramètres.