CodeGym /Cours /ChatGPT Apps /Comment GPT décide d’appeler un outil : modèle de to...

Comment GPT décide d’appeler un outil : modèle de tool-call et rôle des descriptions

ChatGPT Apps
Niveau 4 , Leçon 0
Disponible

1. Pourquoi s’intéresser au tool-call

Pour simplifier, une application web classique suit le schéma « l’utilisateur clique sur un bouton — nous appelons une fonction ». Dans le monde des ChatGPT Apps, c’est différent : l’utilisateur dit quelque chose, le modèle réfléchit et, s’il le juge pertinent, produit un appel d’outil structuré (tool-call).

Autrement dit, vous n’écrivez pas :

onClick={() => callSuggestGiftsApi(formData)}

mais plutôt :

  1. Vous décrivez l’outil suggest_gifts (nom, description, schéma des arguments).
  2. Vous expliquez au modèle dans le system-prompt en quoi cet outil est utile.
  3. Vous laissez le contrôle au modèle : il décide lui-même quand et comment l’appeler.

Deux choses sont donc à comprendre très tôt :

  1. GPT ne voit pas votre code backend. Il ne voit que « l’en-tête » de l’outil : nom, description et schéma des paramètres.
  2. La façon dont le modèle utilisera votre App « intelligemment » dépend presque directement de la qualité de vos descriptions. De bonnes descriptions sont votre « prompt d’outil ».

La leçon d’aujourd’hui porte justement sur ce « cerveau » entre l’utilisateur et votre serveur.

2. Modèle mental du tool-call : que se passe‑t‑il exactement

Commençons par la vue d’ensemble. Scénario typique pour GiftGenius :

  1. Utilisateur : « Trouve un cadeau pour un ami de 30 ans, budget 100 dollars, il aime les jeux vidéo ».
  2. GPT lit ce message et regarde quels outils sont disponibles. Dans notre App, par exemple, il y a suggest_gifts.
  3. GPT décide : « Pour bien répondre, je dois appeler cet outil ».
  4. Au lieu d’une réponse textuelle ordinaire, il génère une structure : nom de l’outil + arguments JSON.
  5. Le client ChatGPT détecte : « Ah, c’est un tool-call », et l’envoie à votre MCP/serveur.
  6. Votre serveur exécute la logique métier et renvoie un résultat structuré.
  7. GPT reçoit le résultat, le lit, puis, sur cette base, formule une réponse compréhensible pour l’utilisateur et/ou met à jour le widget.

Du point de vue de l’OpenAI API, c’est le même mécanisme que le LLM-function-calling : dans la réponse du modèle, au lieu d’un texte, apparaît un objet avec le name de l’outil et les arguments, et le finish_reason est marqué tool_calls. Le modèle n’exécute pas le code lui-même — il ne fait que proposer quel outil appeler, et l’appel réel est effectué par le client (ChatGPT/Apps SDK).

Voici à quoi cela ressemble (séquence simplifiée) :

sequenceDiagram
    participant U as Utilisateur
    participant G as GPT (modèle)
    participant C as Client ChatGPT
    participant S as Votre MCP/Backend

    U->>G: "Choisis un cadeau pour un ami..."
    G->>C: tool-call: { name: "suggest_gifts", args: {...} }
    C->>S: HTTP /mcp tools/call (suggest_gifts, args)
    S-->>C: Résultat (JSON avec la liste des cadeaux)
    C-->>G: tool result
    G-->>U: Réponse + widget mis à jour

Conclusion principale : vous n’écrivez pas if (userAskedAboutGifts) callSuggestGifts(). Vous créez l’outil et sa description, et c’est le modèle qui décide.

3. Ce que voit le modèle : system prompt + liste des outils

Pour comprendre comment GPT décide quoi faire, il faut savoir clairement de quelles informations il dispose au moment du choix.

De façon simplifiée, le modèle voit :

  • le system‑prompt de votre App (nous le détaillerons dans le module 5) ;
  • l’historique du dialogue : messages de l’utilisateur, ses propres réponses, résultats des tool‑calls précédents ;
  • la liste des outils disponibles (tools) avec leurs noms, descriptions et schémas de paramètres ;
  • des annotations supplémentaires sur les outils (readOnly/destructive, etc.).

Il ne voit pas :

  • l’implémentation des fonctions ;
  • les requêtes SQL ;
  • la structure de vos tables ;
  • le contenu d’un dépôt privé contenant votre service.

Nous parlerons de MCP plus en détail un peu plus tard. Pour l’instant, retenez qu’au niveau MCP les outils sont déclarés sous forme de descripteurs : chacun a un name, une description et un inputSchema (JSON Schema). Lors du handshake, ChatGPT demande au serveur MCP la liste des outils et commence à les considérer comme des « actions » disponibles.

Exemple de descripteur pour GiftGenius (JSON simplifié) :

{
  "name": "suggest_gifts",
  "description": "Propose des idées de cadeaux selon l’âge, les centres d’intérêt et le budget",
  "inputSchema": {
    "type": "object",
    "properties": {
      "age": { "type": "integer" },
      "budget": { "type": "number" }
    },
    "required": ["age", "budget"]
  }
}

Le modèle ne « lit » ici que le texte et la structure : ce que sont age, budget, et ce que fait l’outil en général. La prochaine leçon portera justement sur la façon de bien décrire inputSchema. Pour l’instant, voyons comment cette description conduit à la décision « et si j’appelais suggest_gifts » ?

4. À quoi ressemble un tool-call côté API

ChatGPT appelle les outils (tools) de votre serveur MCP à peu près comme un Agent OpenAI appelle des fonctions sur votre backend. Dans l’Apps SDK, c’est un peu plus encapsulé, mais la mécanique de base est identique.

Imaginons que, sur notre backend, nous effectuons une requête standard vers l’OpenAI API, tout en transmettant l’outil suggest_gifts que le modèle peut appeler dans sa réponse :

const response = await openai.responses.create({
  model: 'gpt-5-mini',
  messages: [
    {
      role: 'user',
      content: 'Besoin d\'un cadeau pour un ami de 30 ans, budget 100 dollars'
    }
  ],
  tools: [ // ici, nous passons la liste des fonctions que le LLM peut "appeler"
    {
      name: 'suggest_gifts',
      description: 'Propose des cadeaux selon l’âge, le budget et les centres d’intérêt',
      parameters: {
        type: 'object',
        properties: {
          age: { type: 'integer' },
          budget: { type: 'number' }
        },
        required: ['age', 'budget']
      }
    }
  ]
});

Si le modèle décide d’appeler l’outil, vous recevrez en réponse non pas du texte, mais un message assistant avec quelque chose comme :

{
  "role": "assistant",
  "tool_calls": [
    {
      "id": "call_1",
      "name": "suggest_gifts",
      "arguments": "{\"age\":30,\"budget\":100}"
    }
  ],
  "content": []
}

De cette façon, le LLM indique à votre backend qu’il a besoin d’appeler la fonction suggest_gifts(30,100).

Trois points importants ici :

  1. Le nom de l’outil (name) — le modèle y met réellement la chaîne que vous avez indiquée dans la description des tools lors de la première requête.
  2. Les arguments (arguments) — une chaîne JSON construite à partir de parameters/inputSchema.
  3. L’absence de réponse textuelle classique (pour l’instant) — à la place, vous recevez une structure pour appeler l’outil.

Dans un ChatGPT App, c’est pareil : le modèle renvoie « je veux appeler suggest_gifts avec ces paramètres », et le client (ChatGPT) effectue une requête HTTP vers votre MCP/serveur : tools/call avec le nom de l’outil et les arguments.

5. Comment le modèle décide concrètement : outil ou texte

La question la plus intéressante maintenant : quand GPT pense‑t‑il à vos outils ?

La mécanique, en simplifié :

  1. Le modèle voit le nouveau message de l’utilisateur et le contexte courant.
  2. En interne, il dispose d’un « volet » qui génère le prochain message de l’assistant, mais au lieu de toujours produire du texte, il peut choisir un mode de terminaison parmi :
    • une réponse textuelle classique (finish_reason : "stop") ;
    • un ou plusieurs tool-calls (finish_reason : "tool_calls") ;
    • parfois d’autres variantes (par exemple, « il faut un message utilisateur supplémentaire »).
  3. Ce choix est influencé par :
    • le degré de similarité entre la demande utilisateur et les tâches décrites par vos outils ;
    • le fait que la description de l’outil dise explicitement « utilise‑moi dans tel cas » ;
    • les données du system prompt de l’app, définies dans la configuration de l’Apps SDK.

Pour le dire simplement, le modèle « essaie » votre outil sur la demande en cours. Si la description dit : « Propose des cadeaux selon l’âge et les centres d’intérêt », et que l’utilisateur demande « analyser le budget de l’État », le modèle n’essaiera même pas de l’appeler. Si la description est trop vague — « fait des trucs géniaux » — le modèle ne comprendra pas sur quels types de demandes l’utiliser.

Subtilité intéressante : le modèle n’est pas obligé d’appeler l’outil, même si vous l’avez décrit. GPT peut décider : « Ici, c’est clair, je réponds moi-même, sans tool‑call ». C’est pourquoi, plus loin dans le cours, nous allons nous entraîner activement à écrire des descriptions qui rendent l’utilisation de l’outil la plus évidente et avantageuse possible pour le modèle.

6. Nom de l’outil : pourquoi tool1 est une mauvaise idée

Le nom de l’outil est, en substance, l’identifiant que le modèle utilisera dans ses appels. On pourrait croire que c’est purement technique, mais en pratique le nom influence fortement le comportement du modèle.

Si vous nommez l’outil tool1, le modèle n’en déduira rien. Pour lui, ce n’est qu’une suite de caractères. Si vous le nommez suggest_gifts, search_products ou fetch_user_orders, le nom donne déjà un signal fort sur la fonction de l’outil.

Pensez à votre propre lecture d’un code inconnu. En voyant une fonction calculateCartTotal, vous imaginez ce qu’elle fait. Le modèle a besoin du même « ancrage sémantique ».

Pour GiftGenius, des noms d’outils logiques seraient :

suggest_gifts
search_products
get_product_details
create_order

Un bon nom est :

  • court mais explicite ;
  • dans un style homogène (snake_case, latin, verbe_nom) ;
  • reflétant une action unique et précise.

Mauvaise idée : mélanger des actions différentes dans un seul outil, du type do_all_gift_stuff. Le modèle comprend moins bien quand l’utiliser, et, dans les prochaines leçons, nous verrons comment cela détériore le schéma des arguments et complique le débogage.

7. Description de l’outil : votre prompt pour le modèle

Si le nom est le titre, alors la description est une mini‑documentation, non pas pour un développeur humain, mais pour GPT. Le développeur lira le code ; le modèle, non. Il s’appuie sur le texte de la description pour décider quand appeler l’outil et quels arguments y passer.

Il est important d’écrire la description comme une « notice d’utilisation » :

  • quand utiliser l’outil ;
  • quelles sont ses limites ;
  • ce qu’il ne doit pas faire.

Prenons suggest_gifts. Voici trois variantes de description.

Trop large :

"Propose des cadeaux."

Le modèle ne comprend pas pour quelle occasion, pour qui, avec quels paramètres. Cet outil peut « entrer en concurrence » dans la tête du modèle avec ses connaissances générales sur les cadeaux, et il choisira souvent de répondre en texte.

Trop étroite :

"Propose des cadeaux uniquement pour les petits frères à l’anniversaire."

Ici, on interdit quasiment l’outil dans la plupart des cas. Tout autre scénario — mère, collègue, anniversaire de mariage — « ne convient pas », et le modèle évitera l’appel.

Optimale :

"Utilise cet outil quand il faut proposer des cadeaux à une personne en fonction de son âge, du type de relation (ami, partenaire, collègue, etc.), du budget et des centres d’intérêt.
Ne l’utilise pas pour des questions non liées aux cadeaux (par exemple, politique ou météo)."

Ici, c’est clairement décrit : ce que fait l’outil, quels paramètres il exploite et quand l’appeler, avec en plus une condition négative — pour quels types de demandes il vaut mieux l’éviter.

Le modèle « aime » ces cadres clairs. Plus vous indiquez précisément pour quelles formulations (intents) l’outil est pertinent, plus le comportement de l’App sera prévisible.

Mini‑exercice

Prenez tout de suite votre futur App (pas forcément sur les cadeaux) et imaginez, pour l’un de ses outils, trois descriptions : très large, très étroite et équilibrée. Puis testez comment GPT se comporte avec les différentes versions.

8. Schéma des arguments : comment il aide à décider

Nous parlerons en détail de JSON Schema dans la prochaine leçon, mais pour comprendre les tool-calls, il faut au moins une intuition de haut niveau.

Quand le modèle décide d’appeler un outil, il doit :

  1. Comprendre quels arguments l’outil attend.
  2. Extraire ces valeurs du texte utilisateur (ou du contexte).
  3. Former un JSON avec ces arguments.

Pour cela, la description de l’outil inclut un schéma des paramètres (inputSchema) qui indique au modèle :

  • quels champs existent (age, budget, relationship_type, interests, etc.) ;
  • quels champs sont obligatoires (required) ;
  • quels sont les types (integer, number, string, tableaux, etc.) ;
  • parfois — quelles valeurs sont autorisées (enum) et des explications pour les champs (description).

L’interface TypeScript la plus simple pour les paramètres de suggest_gifts peut ressembler à ceci :

interface SuggestGiftsParams {
  age: number;
  relationship_type: 'friend' | 'partner' | 'colleague';
  budget: number;
  interests?: string[];
}

Au niveau du modèle, cela devient un JSON Schema, et le modèle, via le nom et la description de chaque champ, déduit que :

  • age se récupère dans « 30 ans », « pour un adolescent », etc. ;
  • budget dans « budget 100 dollars », « jusqu’à 50 euros » ;
  • relationship_type dans « ami », « collègue » ;
  • interests — dans « aime les jeux vidéo ».

Si vous fournissez un schéma sans descriptions et avec des noms de champs abstraits (a, b, c), le modèle se trompera bien plus souvent en remplissant les arguments. Nous y reviendrons dans le module sur la localisation et les aides UX. L’idée clé est simple : le schéma n’est pas qu’une validation côté backend, c’est d’abord une indication pour le modèle sur « quoi mettre où ».

Nous avons vu comment le schéma aide le modèle à assembler correctement les arguments. Mais au‑delà de « quoi et comment appeler », il y a « peut‑on l’appeler maintenant et est‑ce sûr ? ». C’est là qu’entrent en jeu les permissions et la méta‑information des outils.

9. Permissions et contexte : chaque outil n’est pas toujours disponible

Au‑delà du nom, de la description et du schéma d’arguments, les outils ont une autre dimension essentielle : la sécurité et l’accès. Les outils d’une App réelle varient beaucoup en « niveau de risque ». Ce n’est pas la même chose de rechercher des cadeaux dans un catalogue public et de débiter la carte d’un utilisateur.

L’Apps SDK et MCP permettent de refléter cela dans les descriptions et annotations — par exemple, en les marquant read-only ou destructive.

Le principe :

  • Les outils qui ne font que lire des données publiques (search_products, get_weather) peuvent être appelés sans confirmations supplémentaires.
  • Les outils qui modifient quelque chose (create_order, cancel_order, charge_user) sont marqués comme « destructifs ». L’UI de ChatGPT peut demander une confirmation supplémentaire (« Voulez‑vous vraiment passer la commande ? »), et le modèle proposera plus rarement de les appeler sans demande explicite.

Dans les modules à venir, lors de la configuration de MCP, vous verrez comment ces annotations (_meta, destructiveHint, readOnlyHint) apparaissent dans les descripteurs JSON réels, comment elles influencent l’UX et la façon dont ChatGPT forme les dialogues « Are you sure? » avant l’appel. Pour l’instant, retenez :

  • GPT tient compte non seulement du texte de la description, mais aussi de la méta‑information de sécurité.
  • Un outil nécessitant une authentification ne sera pas utilisé tant que l’utilisateur n’est pas connecté (ou tant que l’app n’a pas reçu le jeton requis).

C’est un autre facteur qui influence la décision « lancer un tool ou non » : même si l’outil est pertinent, il peut être indisponible selon les permissions, et le modèle choisira une autre voie.

10. D’où viennent les outils dans ChatGPT

Architecturalement, un outil peut arriver au modèle par deux voies principales.

Premièrement, depuis la configuration de votre ChatGPT App. Lorsque vous enregistrez une App, vous indiquez quels serveurs MCP (et leurs outils) y sont liés, ou quels tools intégrés sont présents dans l’application. Au démarrage de la session, ChatGPT récupère cette configuration et comprend quels outils sont disponibles.

Deuxièmement, directement depuis MCP. MCP (Model Context Protocol) définit une façon standard pour qu’un client (ici ChatGPT/Apps SDK) découvre ce que sait faire votre serveur : il effectue une requête tools/list, reçoit un JSON avec les descriptions d’outils et les conserve comme capabilities. Nous détaillerons la mécanique dans un module dédié à MCP ; pour l’instant, gardez l’idée générale.

Schématiquement :

flowchart LR
  A[Client ChatGPT] -->|handshake| B[Serveur MCP]
  B -->|tools/list| A
  A -->|transmet la liste| G[Modèle GPT]

Ensuite, la liste des outils devient une partie du contexte pour le modèle. Si vous modifiez le schéma ou la description d’un outil côté serveur et redémarrez l’app, le nouveau descripteur arrivera dans ChatGPT au prochain handshake, et le modèle prendra désormais ses décisions d’appel différemment.

Point pratique important : quand vous ne modifiez que le backend (l’implémentation de l’outil), le modèle ne le sait pas. Mais quand vous changez name/description/schema, vous changez réellement le « cerveau » de l’App. Il est parfois plus utile d’ajuster une ligne dans la description que d’écrire 200 lignes de code d’heuristiques.

11. Application à GiftGenius : créer un outil que le modèle voudra appeler

Relions maintenant tout cela à notre application d’apprentissage GiftGenius. Imaginons que nous avons déjà un serveur MCP ou une couche backend où nous enregistrons les outils. Enregistrons l’outil suggest_gifts avec server.registerTool(...).

Ébauche minimaliste en TypeScript (sans logique réelle pour l’instant) :

// pseudo-mcp-server/tools/suggestGifts.ts
server.registerTool(
  'suggest_gifts', // nom de l'outil
  {
    title: 'Sélection de cadeaux',
    description:
      'Utilise cet outil pour proposer des idées de cadeaux en fonction de l’âge, ' +
      'du type de relation et du budget. N\'utilise pas cet outil pour des questions non liées aux cadeaux.',
    inputSchema: { // description des paramètres de l'outil
      type: 'object',
      properties: {
        age: { type: 'integer', description: 'Âge du destinataire en années' },
        relationship_type: {
          type: 'string',
          description: 'Type de relation : friend, partner, colleague'
        },
        budget: {
          type: 'number',
          description: 'Budget maximum du cadeau dans la devise de l\'utilisateur'
        }
      },
      required: ['age', 'budget']
    }
  },
  async ({ age, relationship_type, budget }) => { // code de la fonction/outil
    // La logique réelle viendra plus tard
    return { suggestions: [] };
  }
);

Remarquez les détails que nous avons déjà soignés, même si la logique est encore un « bouchon » :

  • Nom : suggest_gifts, et non tool1.
  • Description : explique explicitement quand appeler l’outil et quand ne pas l’appeler.
  • Descriptions de champs : aident le modèle à faire le mapping entre le texte utilisateur et les arguments.

En résultat, quand l’utilisateur écrira « Choisis un cadeau pour un collègue à 50 dollars », le modèle verra que :

  • il existe un outil nommé suggest_gifts avec une description sur la sélection de cadeaux ;
  • il possède les champs age, relationship_type, budget ;
  • budget — « budget maximum pour le cadeau », relationship_type — « type de relation : friend, partner, colleague ».

Même si les utilisateurs s’expriment de façon imprécise (« jusqu’à cinquante », « pour un partenaire de projet »), le modèle aura assez de contexte pour essayer d’assembler correctement le JSON d’arguments.

Quand notre outil fonctionnera réellement (dans le module backend et MCP), vous serez déjà à l’aise avec le sujet : GPT l’appellera de manière prévisible, simplement parce que nous avons bien conçu l’interface et la description.

12. Un peu de pratique pour vous

Pour éviter que le sujet reste théorique, je vous propose une petite expérience juste après la leçon.

Commencez par prendre l’un de vos scénarios GiftGenius ou imaginez une nouvelle App. Notez sur papier ou dans un éditeur une fonction que vous souhaitez clairement confier au modèle — quelque chose comme search_products, find_hotels, calculate_shipping.

Ensuite, proposez pour ce même outil trois paires « nom + description » :

  1. Nom et description très abstraits.
  2. Trop spécifiques (presque un cas particulier).
  3. Nom + description bien équilibrés, qui indiquent clairement quand appeler l’outil et ce qu’il ne doit pas faire.

Ensuite — si vous le souhaitez — vous pouvez, en utilisant un OpenAI SDK standard, faire une simple requête avec ces variantes et observer comment le comportement du modèle change : l’outil est‑il appelé, comment les arguments sont‑ils remplis ? Dans la recherche sur ce sujet, on propose justement un exercice de ce type pour suggest_gifts.

13. Erreurs fréquentes lors de la conception des tool-call et des descriptions

Erreur n° 1 : nommer les outils tool1, handler, doStuff.
Ce naming est totalement inutile pour le modèle. GPT ne devine pas « les intentions du développeur » à partir du nom de fichier ; il lui faut un nom sémantiquement explicite. Si vous fournissez un lot tool1, tool2, tool3 sans descriptions, l’outil sera quasiment jamais appelé : le modèle ne comprendra tout simplement pas ce que fait chacun, et soit il les ignorera, soit il choisira au hasard.

Erreur n° 2 : considérer la description comme un commentaire pour humains.
Beaucoup écrivent une formule creuse du type « Fonction de sélection de cadeaux », en pensant que les détails se trouvent de toute façon dans le code. Mais le modèle ne voit pas le code, il ne voit que le texte de la description et le schéma des arguments. Une description floue devient une source d’hallucinations : GPT tentera soit de répondre lui‑même alors qu’il fallait appeler l’outil, soit d’appeler l’outil dans des situations étranges.

Erreur n° 3 : faire une description trop large ou trop étroite.
Si vous écrivez « Fait des trucs géniaux », le modèle ne comprend pas le périmètre d’usage. Si vous écrivez « Propose des cadeaux uniquement pour le petit frère pour ses 18 ans », vous interdisez pratiquement l’outil la plupart du temps. La description optimale définit un périmètre clair (proposition de cadeaux selon plusieurs paramètres), la liste des paramètres clés (âge, relation, budget, centres d’intérêt) et précise pour quels types de questions il ne faut pas utiliser l’outil.

Erreur n° 4 : ignorer le schéma des arguments comme partie du « prompt ».
Certains développeurs ne voient dans JSON Schema qu’un moyen de valider côté serveur. En réalité, le modèle analyse activement les noms de champs, leurs types et descriptions pour comprendre quelles données extraire du texte utilisateur. Si vous nommez un champ x sans description et le rendez optionnel, GPT commencera à le remplir de manière chaotique ou pas du tout. Un schéma correct, avec des noms clairs et de brèves descriptions, réduit fortement le nombre de tool-calls invalides.

Erreur n° 5 : s’attendre à ce que le modèle « doive » appeler l’outil.
Les développeurs s’étonnent parfois : « Pourquoi GPT n’a‑t‑il pas appelé mon outil alors qu’il existe ? ». La réponse est presque toujours : ni la description ni le system‑prompt n’indiquent que l’outil est nécessaire pour ce type de demande, ou bien la demande se situe dans une zone où le modèle estime qu’il est plus simple de répondre lui‑même.

Erreur n° 6 : mélanger plusieurs actions hétérogènes dans un seul outil.
On a parfois envie de créer un manage_orders universel qui cherche des commandes, en crée de nouvelles et annule les anciennes. Pour un humain, c’est encore explicable, mais pour le modèle, c’est un outil flou sans frontières nettes. GPT comprend moins bien quand l’appeler et remplit plus difficilement les arguments — car on se retrouve avec une foule de champs optionnels. Il vaut mieux scinder en plusieurs outils ciblés (get_order, create_order, cancel_order) avec des descriptions et schémas clairs.

Erreur n° 7 : négliger permissions et sécurité dans le design du tool.
Si vous décrivez un outil capable d’actions destructrices (débit, suppression de données) sans le marquer comme destructive et sans en restreindre l’usage dans la description, vous créez un risque. L’UI de ChatGPT ne demandera pas de confirmation supplémentaire, et le modèle pourra décider d’appeler l’outil même dans des scénarios « limites ». Les bonnes annotations et une description prudente (« à utiliser seulement après le consentement explicite de l’utilisateur ») réduisent ces risques dès le niveau du tool‑call.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION