Aller au contenu principal
Version: 1.0.0

Décision agentique gouvernée

Une décision agentique Touba est un choix effectué dans un périmètre déclaré. Le runtime ne demande pas à l’hôte de décider à sa place, mais il ne donne pas non plus à l’agent une liberté non bornée.

Structure
user objective
-> Touba agent
-> controlled model input
-> capabilities authorized by AIR
-> configured decision provider
-> structured selection
-> runtime verification
-> execution or refusal
-> trace

Ce que le runtime fait​

Quand l’exécution atteint un agent, le runtime :

  1. lit les capacités déclarées dans uses ;
  2. construit une entrée modèle structurée ;
  3. sépare instruction développeur, données utilisateur, contenus externes et interface de ressources ;
  4. indique qu’un catalogue de capacités est disponible ;
  5. envoie le catalogue complet seulement si le provider le demande ;
  6. peut accepter une réponse directe si aucune capacité n’est nécessaire ;
  7. reçoit une cible target_ref et, si nécessaire, des arguments ;
  8. vérifie que la cible appartient bien à uses ;
  9. vérifie callable_by si la cible est un autre agent ;
  10. vérifie que les arguments correspondent à la signature de la cible ;
  11. exécute la capacité, retourne la réponse directe ou refuse avant tout handler ;
  12. remet le résultat intermédiaire au modèle comme observation pour la décision suivante ;
  13. trace la décision.

Cette boucle réduit la charge côté développeur : l’hôte n’a plus à reconstruire manuellement le catalogue, extraire un choix, vérifier le périmètre puis réinjecter la décision dans Touba.

Deux représentations provider, une seule autorité runtime​

Le SDK peut représenter le choix du modèle de deux façons :

InterfaceReprésentation fournisseur
structuredobjet de décision produit depuis un schéma ; comportement par défaut
nativeappel de fonction natif pendant la phase catalogue ; choix explicite de l’hôte

Cette différence ne modifie ni la syntaxe .tb, ni l’AIR, ni le protocole touba-agent-decision-v1. En interface native, le SDK ne donne pas d’exécuteur au modèle : il normalise sa proposition, puis le runtime applique les mêmes contrôles et réalise seul l’exécution.

Le tutoriel Utiliser les appels natifs sous autorité Touba montre la configuration et le cycle complet.

Catalogue à la demande​

Le runtime ne transmet pas forcément tous les contrats à chaque décision.

Premier échange :

JSON
{
"protocol": "touba-agent-decision-v1",
"mode": "summary",
"model_input": {
"protocol": "touba-agent-model-input-v1",
"mode": "orientation",
"developer_instruction": {
"source": "air_agent_responsibility",
"text": "Find and summarize public datasets."
},
"content_boundary": {
"developer_instruction_authority": "instruction",
"user_input_authority": "domain_data_only",
"external_content_authority": "untrusted_content"
},
"user_input": {
"category": "domain_data",
"keys": ["request"]
},
"resources_hint": {
"capabilities_available": true,
"capability_count": 2,
"catalog_available_on_request": true
}
},
"agent_ref": "agent:examples.research/Researcher",
"capability_count": 2,
"capability_refs": [
"skill:examples.research/SearchDatasetOnly",
"skill:examples.research/BuildDatasetBrief"
],
"input_keys": ["request"]
}

Pour une entrée simple comme une salutation, le provider peut répondre sans demander le catalogue :

JSON
{
"action": "answer_directly",
"source": "ai_sdk_structured_output",
"reason": "No Touba resource is required.",
"result": "Hello."
}

Si le provider a besoin du détail, il répond :

JSON
{
"action": "request_capabilities",
"source": "ai_sdk_structured_output",
"reason": "I need to compare the available contracts."
}

Le runtime envoie alors le catalogue autorisé : kind, signatures, champs de types locaux, type de sortie, grants requis, handles de secrets, accès mémoire et sous-capacités. Une capacité peut être une function, un tool, une skill, un agent ou une strategy si elle est déclarée dans uses. Chaque capacité exposée au provider doit avoir une description source explicite ; sinon le runtime refuse avant l’appel modèle. Cette règle donne au provider un signal sémantique stable sans affaiblir le contrôle runtime.

Pour un agent exposé à un autre agent, le catalogue peut inclure sa responsabilité, ses sous-capacités résumées et ses règles callable_by. Cela permet de traiter la délégation multi-agents comme une capacité gouvernée, pas comme un appel libre.

Boucle séquentielle​

Un agent peut consommer plusieurs ressources pendant une même exécution. Après chaque ressource autorisée, le runtime renvoie une observation au modèle :

JSON
{
"agent_state": {
"step_index": 1,
"observation_count": 1,
"observations": [
{
"target_ref": "skill:examples.research/SearchDatasetOnly",
"result": {
"datasets_count": 3
}
}
]
}
}

L’observation sert à décider de la suite : répondre, demander le catalogue, appeler une autre capacité autorisée ou demander un review humain. Les traces indiquent qu’un résultat est disponible, mais elles n’écrivent pas l’observation brute.

Sélection avec arguments​

Le provider peut choisir une capacité et renseigner ses entrées :

JSON
{
"action": "select_capability",
"target_ref": "skill:examples.research/BuildDatasetBrief",
"source": "openai_structured_output",
"reason": "The request requires search followed by summarization.",
"arguments": {
"request": {
"query": "firefighter",
"rows": 1,
"dry_run": true,
"llm_model": "gpt-4.1-nano",
"goal": "Find a public dataset and produce a short summary in English."
}
}
}

Le runtime vérifie que BuildDatasetBrief est bien dans uses. Il vérifie aussi que request est un input déclaré par la capacité. Une entrée inconnue ou manquante provoque un refus avant exécution.

Review humain demandé par l’agent​

Le modèle peut demander un review humain en mode catalogue :

JSON
{
"action": "request_human_review",
"target_ref": "human_review",
"source": "openai_structured_output",
"reason": "The result should be confirmed before continuing.",
"review_prompt": "Validate the selected dataset before synthesis."
}

Ce mécanisme est différent de human.approve. human.approve est une barrière imposée par le programme. request_human_review est une possibilité que l’agent peut demander ; le runtime suspend si aucune décision humaine n’est disponible, puis reprend seulement avec une décision explicite.

Provider JavaScript​

@touba/sdk fournit un adaptateur pour l’AI SDK :

decision-provider.mjs
import { createAiSdkDecisionProvider } from "@touba/sdk";
import { model } from "./model-provider.mjs";

export const decideAgentCapability = createAiSdkDecisionProvider({
model,
});

export const provider_metadata = {
provider_kind: "sdk_ai",
provider_name: "researcher-provider",
provider_version: "1.0.0",
model_family: "openai",
prompt_template_id: "researcher-v1",
decision_schema_version: "touba-agent-decision-v1",
};

Le choix du fournisseur reste côté projet. Touba conserve son propre protocole et le runtime revalide la décision. Le scénario Données Québec utilise le helper OpenAI du SDK pour démontrer un chemin d’exécution réel avec un fournisseur configuré explicitement.

Le runtime trace un digest de requête rédigée, les metadata provider non secrètes, les appels provider tentés, les retries bornés et les refus de budget max_provider_calls. Ces traces n’exposent pas les valeurs brutes envoyées au modèle.

Décision et concurrence​

Chaque agent enchaîne ses décisions séquentiellement. Une capacité choisie peut être une stratégie ou une skill contenant un groupe parallel ; une stratégie peut aussi distribuer des entrées sur un agent typé. Les branches isolent leurs observations et partagent les budgets du run, sans élargir uses ni callable_by. Une même capacité reste réutilisable tant qu'elle est autorisée.

Les interfaces SDK structured et native changent la représentation présentée au modèle, pas cette autorité runtime. Le guide SDK explique leur configuration et le tutoriel multi-agent montre la composition et la reprise.

Les transferts libres de session, l'ordonnancement distribué et les plafonds monétaires stricts ne font pas partie de ce mécanisme.