Qu’est-ce que le function calling dans les LLMs et comment l’utiliser avec l’API OpenAI

Beaucoup de développeurs qui découvrent les LLMs s’arrêtent à la génération de texte et passent complètement à côté d’une fonctionnalité qui change radicalement ce qu’on peut faire avec ces modèles : le function calling. Résultat : des chatbots qui hallucinent des données en temps réel, des assistants incapables d’interagir avec un système externe, des intégrations qui restent au stade de la démonstration. Pourtant, cette mécanique est disponible dans l’API OpenAI depuis plusieurs versions, documentée, stable, et exploitable en production avec quelques heures de travail seulement.

Qu’est-ce que le function calling dans un LLM ?

Le function calling (ou appel de fonction) est une capacité offerte par certains grands modèles de langage pour interagir de façon structurée avec des systèmes externes. Concrètement, au lieu de répondre à une question avec un simple texte libre, le modèle peut détecter qu’il a besoin d’une information extérieure ou d’une action, et retourner un objet JSON structuré indiquant quelle fonction appeler et avec quels paramètres.

L’analogie la plus juste : imaginez un assistant très compétent qui, au lieu d’inventer une réponse approximative sur le cours de l’euro, vous dit explicitement « appelle le service de cotation avec les paramètres devise=EUR, référence=USD ». C’est votre code qui exécute l’appel réel, récupère le résultat, et le renvoie au modèle pour qu’il formule une réponse finale cohérente et factuellement ancrée.

Ce mécanisme diffère fondamentalement du prompt engineering classique : on ne demande pas au modèle de deviner ou d’improviser. On lui fournit un contrat d’interface explicite, sous forme de schéma JSON, et il s’y conforme. Cette approche s’inscrit dans la logique des agents LLM, ces systèmes capables d’orchestrer des actions en plusieurs étapes pour accomplir une tâche complexe.

Comment fonctionne le function calling avec l’API OpenAI

La structure de la requête : déclarer ses fonctions

Lors d’un appel à l’API OpenAI (endpoint /v1/chat/completions), vous passez un tableau tools contenant la liste des fonctions que le modèle peut invoquer. Chaque fonction est décrite par son nom, une description en langage naturel, et un schéma JSON des paramètres attendus. Voici un exemple minimal :

{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "Quel est le stock actuel du produit REF-4421 ?"}],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_product_stock",
        "description": "Retourne le niveau de stock d'un produit à partir de sa référence",
        "parameters": {
          "type": "object",
          "properties": {
            "reference": {"type": "string", "description": "La référence produit"}
          },
          "required": ["reference"]
        }
      }
    }
  ]
}

Le cycle d’exécution : trois étapes clés

Le flux complet se déroule en trois temps distincts. Première étape : vous envoyez la requête avec la définition des outils. Le modèle analyse le message utilisateur et, s’il juge qu’une fonction est pertinente, retourne une réponse avec finish_reason: "tool_calls" et un objet structuré contenant le nom de la fonction et les arguments en JSON. Deuxième étape : votre backend exécute réellement la fonction (appel BDD, API tierce, calcul métier…) et récupère le résultat. Troisième étape : vous renvoyez ce résultat au modèle via un message de rôle tool, et il génère alors la réponse finale pour l’utilisateur.

Ce cycle peut se répéter plusieurs fois dans une même conversation : c’est le principe des agents multi-étapes, où le modèle enchaîne plusieurs appels de fonctions pour résoudre un problème complexe. OpenAI propose également le paramètre tool_choice pour forcer le modèle à utiliser un outil spécifique ou, au contraire, lui interdire tout appel de fonction.

Cas d’usage concret : un assistant e-commerce français

Prenons un exemple terrain que j’ai accompagné pour une boutique en ligne française spécialisée dans le matériel de cuisine professionnelle. L’équipe voulait un assistant capable de répondre aux questions produits avec des données en temps réel : stock disponible, délai de livraison selon le code postal, compatibilité entre accessoires. Sans function calling, le modèle inventait des informations ou refusait de répondre faute de données actualisées.

La solution mise en place a exposé quatre fonctions au modèle : check_stock(reference), get_delivery_delay(postal_code, weight), search_compatible_products(product_id) et get_product_details(reference). Chaque fonction appelait l’API REST du CMS e-commerce en backend. En production, le taux de satisfaction des réponses de l’assistant est passé de 61 % à 89 % selon les retours du formulaire de feedback intégré. Le modèle ne « savait » toujours rien de l’inventaire : il savait comment demander à le savoir.

Ce type d’architecture est directement applicable à des contextes variés : assistants RH connectés à un SIRH, agents de support connectés à un CRM, outils de veille couplés à des APIs de données sectorielles. La logique métier reste dans votre code, le modèle orchestre. C’est une séparation des responsabilités saine et maintenable. Pour aller plus loin sur l’écosystème des modèles capables de ce type de raisonnement structuré, la comparaison entre OpenAI et Google dans la guerre des LLMs donne un éclairage utile sur les capacités différenciées de chaque famille de modèles.

Bonnes pratiques et pièges à éviter en production

Soigner les descriptions de fonctions

Le modèle choisit quelle fonction appeler en se basant uniquement sur les descriptions que vous fournissez. Une description vague ou ambiguë produira des appels incorrects ou des hallucinations de paramètres. Rédigez vos descriptions comme vous rédigeriez une documentation d’API à destination d’un développeur junior : précis, avec les cas limites mentionnés. Évitez les noms de fonctions trop génériques comme process_data ou handle_request.

Valider systématiquement les arguments retournés

Même avec strict: true (le mode de validation de schéma introduit par OpenAI), ne faites jamais confiance aveuglément aux arguments retournés par le modèle avant de les passer à votre système. Validez-les contre votre schéma côté backend, gérez les cas d’erreur, et renvoyez un message d’erreur structuré au modèle si quelque chose cloche : il saura en tenir compte pour reformuler son appel. Cette rigueur est particulièrement importante dans des contextes sensibles, un peu comme les principes de défense en profondeur qu’on retrouve dans les erreurs courantes de sécurité API.

Surveiller les coûts et la latence

Chaque cycle d’appel de fonction consomme des tokens supplémentaires : les définitions de fonctions sont injectées dans le contexte à chaque requête. Avec une dizaine de fonctions complexes, le surcoût en tokens peut atteindre 15 à 30 % par rapport à un appel simple. En production, groupez les fonctions rarement utilisées dans des appels conditionnels plutôt que de tout exposer systématiquement. Monitorez également la latence totale du cycle complet (requête modèle + exécution fonction + requête modèle finale) pour rester dans des seuils acceptables pour votre UX.

Pour les équipes qui s’interrogent sur l’évolution des capacités d’inférence et de raisonnement des modèles sous-jacents, l’analyse du modèle o3 d’OpenAI illustre bien la direction prise par les architectures capables de planification multi-étapes, ce qui renforce encore la pertinence du function calling dans les systèmes agentiques avancés.

Mon point de vue d’expert : le function calling n’est pas une option

Si vous construisez une application LLM qui touche à des données réelles — et c’est le cas de pratiquement toutes les applications en production — le function calling n’est pas une fonctionnalité avancée réservée aux équipes d’IA spécialisées. C’est l’architecture de base que vous devriez adopter dès le départ. Partir sur du prompt engineering pur pour simuler des appels de données, c’est construire sur du sable : imprévisible, difficile à déboguer, impossible à auditer. Le function calling, c’est le contrat qui rend vos intégrations LLM maintenables, traçables et fiables. La courbe d’apprentissage est de l’ordre de quelques jours pour un développeur backend compétent. Le retour sur investissement, lui, est immédiat.

FAQ : Function calling et API OpenAI

Le function calling est-il disponible sur tous les modèles OpenAI ?

Non, le function calling est disponible sur les modèles qui supportent explicitement les tools dans l’API chat completions : GPT-4o, GPT-4 Turbo, GPT-3.5 Turbo (versions récentes) et leurs déclinaisons. Les modèles plus anciens ou les endpoints de complétion simple ne supportent pas cette fonctionnalité. Vérifiez toujours la documentation officielle d’OpenAI pour la liste à jour des modèles compatibles avant de choisir votre modèle de base.

Quelle est la différence entre function calling et Assistants API avec tools ?

Le function calling dans l’API Chat Completions vous donne un contrôle total sur le cycle d’exécution : vous gérez vous-même le state, le contexte conversationnel et l’exécution des fonctions. L’Assistants API d’OpenAI propose une couche d’abstraction qui gère automatiquement le threading et le state, avec des tools intégrés comme l’interpréteur de code ou la recherche de fichiers. Pour des intégrations personnalisées et un contrôle fin, préférez le function calling direct. Pour des applications conversationnelles complexes avec gestion de contexte persistant, l’Assistants API simplifie l’architecture.

Comment sécuriser les fonctions exposées au modèle ?

Traitez chaque appel de fonction comme une entrée utilisateur non fiable. Validez systématiquement les paramètres retournés par le modèle avant toute exécution. Appliquez le principe du moindre privilège : les fonctions exposées ne doivent accéder qu’aux données strictement nécessaires. Évitez d’exposer des fonctions d’écriture ou de suppression sans confirmation explicite d’un humain dans la boucle. Loguez tous les appels de fonctions avec leurs paramètres pour audit. Enfin, n’exposez jamais de fonctions permettant d’exécuter du code arbitraire ou d’accéder à votre système de fichiers sans sandbox strictement contrôlé.