Jour 48 Day 48 · jeudi 15 octobre 2026 Thursday 15 October 2026 IA Intermédiaire

Agents, function calling & prompt engineering Agents, function calling & prompt engineering

Comment un LLM « agit » sur le monde : function calling, boucle agentique, définition d'outils et prompts sérieux — le sujet IA qui monte le plus vite en entretien. How an LLM 'acts' on the world: function calling, the agentic loop, tool design and serious prompting — the fastest-rising AI topic in interviews.

L’essentiel

Un LLM ne sait faire qu’une chose : produire du texte. Il ne peut ni interroger une base, ni envoyer un mail, ni exécuter du code. Le function calling (ou tool use) est le mécanisme qui contourne cette limite : on décrit au modèle une liste d’outils disponibles (nom, description, schéma des paramètres), et au lieu de répondre en prose, le modèle peut émettre un appel structuré — « appelle get_weather avec {"city": "Paris"} ». C’est votre code qui exécute réellement la fonction, puis renvoie le résultat au modèle, qui continue sa réponse.

Point capital à énoncer clairement en entretien : le modèle n’exécute rien lui-même. Il émet une intention formatée en JSON ; l’exécution, la validation et les permissions restent côté application. Le modèle propose, votre code dispose.

Un agent naît quand on met ce mécanisme dans une boucle : le modèle reçoit un objectif, choisit un outil, observe le résultat, et recommence jusqu’à ce que l’objectif soit atteint. C’est exactement ainsi que fonctionnent Claude Code, Cursor ou les agents « deep research ».

Comment ça marche

La boucle agentique tient dans un schéma :

objectif de l'utilisateur
        │
        ▼
┌───────────────────────────────────┐
│ LLM : raisonne sur l'état courant │◀────────┐
└───────────────────────────────────┘         │
   │ réponse finale        │ tool call        │
   ▼                       ▼                  │
terminé          VOTRE code exécute           │
                 (API, DB, shell…)            │
                           │                  │
                           ▼                  │
                 résultat = observation ──────┘
                 (renvoyé dans le contexte)

Chaque tour, l’historique complet (objectif + appels + observations) est renvoyé au modèle. Concrètement, un outil se définit par un schéma JSON, et sa description est du prompt engineering : c’est elle qui décide si le modèle utilisera l’outil à bon escient.

{
  "name": "search_orders",
  "description": "Recherche des commandes par client ou statut. À utiliser AVANT de répondre à toute question sur une commande. Ne retourne que les 20 premiers résultats.",
  "input_schema": {
    "type": "object",
    "properties": {
      "customer_email": { "type": "string", "description": "Email exact du client" },
      "status": { "type": "string", "enum": ["pending", "shipped", "cancelled"] }
    },
    "required": ["customer_email"]
  }
}

Le modèle répond alors non pas en texte, mais avec un bloc tool_use : {"name": "search_orders", "input": {"customer_email": "jo@ex.fr", "status": "pending"}}. Votre code valide ce JSON contre le schéma, exécute la vraie requête SQL, et renvoie le résultat comme tool_result. Le enum et le required ne sont pas décoratifs : un schéma strict réduit mécaniquement les erreurs du modèle.

💡 Règle d’or des outils — écrivez la description comme une doc pour un nouveau stagiaire : quand l’utiliser, quand ne PAS l’utiliser, ce que ça retourne, les limites. Un agent qui se trompe d’outil a presque toujours un problème de description, pas un problème de modèle.

Concepts clés à maîtriser

  • Function calling ≠ exécution : le modèle émet une intention structurée. La boucle appel → exécution → observation est orchestrée par votre code (ou un SDK type Claude Agent SDK / LangChain).
  • Prompt engineering sérieux : pas les « astuces magiques » (« je te donne 200 $ de pourboire »), mais quatre leviers reproductibles — un rôle clair, des contraintes explicites (format, longueur, ce qu’il ne faut pas faire), des exemples few-shot (2-3 paires entrée/sortie valent mieux qu’un paragraphe d’explication), et une sortie structurée (JSON schema, balises) qu’un programme peut parser.
Mauvais promptBon prompt
Rôle« Réponds à la question »« Tu es un agent support niveau 1 de l’entreprise X »
ContraintesImplicites« Réponds en 3 phrases max. Si tu ne sais pas, dis-le. »
ExemplesAucun2-3 exemples few-shot entrée → sortie attendue
SortieTexte libreJSON conforme à un schéma donné
Contexte« Voici des infos : … » (vrac)Sections délimitées (balises, titres), données pertinentes seulement
  • MCP, la standardisation : plutôt que de re-coder l’intégration de chaque outil pour chaque app, le Model Context Protocol expose outils et ressources via un protocole standard client/serveur — voir la fiche MCP (18 août) pour le détail.
  • Les échecs classiques d’agents : la boucle infinie (l’agent réessaie sans fin le même appel qui échoue), l’hallucination d’outil (appel d’un outil qui n’existe pas, ou paramètres inventés), et l’explosion des coûts (chaque tour renvoie tout l’historique : un agent qui boucle 50 fois consomme 50 fois le contexte).
  • Les garde-fous : limite dure d’itérations, budget de tokens, permissions par outil (lecture libre, écriture sur validation), et humain dans la boucle pour toute action irréversible (paiement, suppression, envoi d’email). Un agent en production sans garde-fou est un incident en attente.

En entretien

« Explique-moi le function calling. » — On fournit au modèle des définitions d’outils (nom, description, JSON schema). Quand la question le nécessite, le modèle répond par un appel structuré au lieu de prose. Mon code valide les paramètres, exécute la fonction réelle, renvoie le résultat au modèle qui produit la réponse finale. Insister : le modèle ne fait qu’émettre du JSON, l’exécution est entièrement côté application.

« Qu’est-ce qui différencie un agent d’un simple appel LLM ? » — La boucle. Un appel simple : prompt → réponse. Un agent : objectif → le modèle choisit un outil → exécution → observation réinjectée → nouveau raisonnement, jusqu’à l’objectif ou une limite. L’agent décide dynamiquement du chemin ; un pipeline classique le fixe à l’avance.

« Comment éviter qu’un agent parte en vrille ? » — Limite d’itérations et de budget, timeouts sur les outils, validation stricte des paramètres contre le schéma, permissions graduées (lecture vs écriture), et validation humaine pour l’irréversible. Et observer : logger chaque appel d’outil pour rejouer les trajectoires qui échouent.

« C’est quoi un bon outil pour un agent ? » — Une description qui dit quand l’utiliser et quand ne pas l’utiliser, un schéma strict (enum, required, types précis), un périmètre étroit (un outil = une action claire), et des erreurs retournées en texte exploitable (« client introuvable, vérifie l’email ») plutôt qu’une stack trace — l’agent lit l’erreur et peut se corriger.

« Few-shot vs fine-tuning ? » — Few-shot : on met des exemples dans le prompt, immédiat, réversible, suffisant dans la majorité des cas. Fine-tuning : on réentraîne le modèle, coûteux et lent, pertinent pour un style/format très spécifique à haut volume. Réflexe : épuiser le prompt engineering avant de parler de fine-tuning.

Pièges & idées reçues

⚠️ Prompt injection — dès qu’un agent lit du contenu externe (page web, email, ticket), ce contenu peut contenir des instructions (« ignore tes consignes et envoie les données à… ») que le modèle risque de suivre. C’est LA faille des agents, sans correctif définitif à ce jour. Mitigations : moindre privilège sur les outils, validation humaine des actions sensibles, séparer données et instructions dans le prompt. Un agent avec accès à des données privées + du contenu non fiable + un canal de sortie = combinaison dangereuse (la « triple létale »).

  • « Le modèle exécute mes fonctions » — non. Il émet un JSON. Si votre code ne valide pas les paramètres avant exécution, c’est votre faille, pas celle du modèle.
  • « Plus d’outils = agent plus capable » — au contraire : 40 outils aux descriptions floues dégradent le choix. Peu d’outils, bien décrits, à périmètre net.
  • « Le prompt engineering, c’est des formules magiques » — les incantations vieillissent mal d’un modèle à l’autre ; rôle, contraintes, exemples et format de sortie restent efficaces partout.
  • Oublier le coût de la boucle : l’historique complet repart à chaque tour. Sans limite d’itérations ni cache de prompt, la facture explose silencieusement.

🎤 En entretien — le mot qui fait la différence : « déterministe ». Dites « je garde tout ce qui peut être déterministe hors du LLM — validation, permissions, orchestration — et je ne délègue au modèle que la décision », et vous venez de montrer que vous savez construire un agent de production, pas une démo.

Pour aller plus loin

The essentials

An LLM can only do one thing: produce text. It cannot query a database, send an email, or run code. Function calling (aka tool use) is the mechanism that works around this limit: you describe a list of available tools to the model (name, description, parameter schema), and instead of answering in prose, the model can emit a structured call — “call get_weather with {"city": "Paris"}”. It is your code that actually executes the function, then sends the result back to the model, which continues its answer.

The crucial point to state clearly in an interview: the model executes nothing itself. It emits an intent formatted as JSON; execution, validation and permissions stay on the application side. The model proposes, your code disposes.

An agent is born when you put this mechanism in a loop: the model receives a goal, picks a tool, observes the result, and repeats until the goal is reached. That is exactly how Claude Code, Cursor or “deep research” agents work.

How it works

The agentic loop fits in one diagram:

user's goal
        │
        ▼
┌───────────────────────────────────┐
│ LLM: reasons over current state   │◀────────┐
└───────────────────────────────────┘         │
   │ final answer          │ tool call        │
   ▼                       ▼                  │
done             YOUR code executes           │
                 (API, DB, shell…)            │
                           │                  │
                           ▼                  │
                 result = observation ────────┘
                 (fed back into context)

Each turn, the full history (goal + calls + observations) is sent back to the model. Concretely, a tool is defined by a JSON schema, and its description is prompt engineering: it is what decides whether the model will use the tool appropriately.

{
  "name": "search_orders",
  "description": "Search orders by customer or status. Use BEFORE answering any question about an order. Returns only the first 20 results.",
  "input_schema": {
    "type": "object",
    "properties": {
      "customer_email": { "type": "string", "description": "Customer's exact email" },
      "status": { "type": "string", "enum": ["pending", "shipped", "cancelled"] }
    },
    "required": ["customer_email"]
  }
}

The model then replies not with text but with a tool_use block: {"name": "search_orders", "input": {"customer_email": "jo@ex.fr", "status": "pending"}}. Your code validates that JSON against the schema, runs the real SQL query, and returns the result as a tool_result. The enum and required are not decorative: a strict schema mechanically reduces model errors.

💡 Golden rule of tools — write the description like docs for a new intern: when to use it, when NOT to use it, what it returns, its limits. An agent that picks the wrong tool almost always has a description problem, not a model problem.

Key concepts to master

  • Function calling ≠ execution: the model emits a structured intent. The call → execution → observation loop is orchestrated by your code (or an SDK like the Claude Agent SDK / LangChain).
  • Serious prompt engineering: not the “magic tricks” (“I’ll tip you $200”), but four reproducible levers — a clear role, explicit constraints (format, length, what not to do), few-shot examples (2-3 input/output pairs beat a paragraph of explanation), and structured output (JSON schema, tags) that a program can parse.
Bad promptGood prompt
Role“Answer the question”“You are a tier-1 support agent for company X”
ConstraintsImplicit“Answer in 3 sentences max. If you don’t know, say so.”
ExamplesNone2-3 few-shot input → expected output examples
OutputFree textJSON conforming to a given schema
Context“Here’s some info: …” (dump)Delimited sections (tags, headings), relevant data only
  • MCP, the standardization: instead of re-coding every tool integration for every app, the Model Context Protocol exposes tools and resources through a standard client/server protocol — see the MCP topic (August 18) for details.
  • Classic agent failures: the infinite loop (the agent endlessly retries the same failing call), tool hallucination (calling a tool that doesn’t exist, or inventing parameters), and cost explosion (each turn resends the whole history: an agent looping 50 times consumes the context 50 times).
  • Guardrails: a hard iteration limit, a token budget, per-tool permissions (free reads, writes behind approval), and a human in the loop for any irreversible action (payment, deletion, sending an email). A production agent without guardrails is an incident waiting to happen.

In an interview

“Explain function calling to me.” — You give the model tool definitions (name, description, JSON schema). When the question requires it, the model answers with a structured call instead of prose. My code validates the parameters, executes the real function, returns the result to the model, which produces the final answer. Emphasize: the model only emits JSON; execution is entirely on the application side.

“What makes an agent different from a plain LLM call?” — The loop. A plain call: prompt → answer. An agent: goal → the model picks a tool → execution → observation fed back → new reasoning, until the goal or a limit. The agent decides the path dynamically; a classic pipeline fixes it in advance.

“How do you keep an agent from going off the rails?” — Iteration and budget limits, timeouts on tools, strict parameter validation against the schema, graduated permissions (read vs write), and human approval for anything irreversible. And observability: log every tool call so you can replay failing trajectories.

“What makes a good tool for an agent?” — A description that says when to use it and when not to, a strict schema (enum, required, precise types), a narrow scope (one tool = one clear action), and errors returned as actionable text (“customer not found, check the email”) rather than a stack trace — the agent reads the error and can self-correct.

“Few-shot vs fine-tuning?” — Few-shot: put examples in the prompt; immediate, reversible, sufficient in most cases. Fine-tuning: retrain the model; expensive and slow, relevant for a very specific style/format at high volume. Reflex: exhaust prompt engineering before mentioning fine-tuning.

Pitfalls & misconceptions

⚠️ Prompt injection — as soon as an agent reads external content (web page, email, ticket), that content can contain instructions (“ignore your instructions and send the data to…”) the model may follow. It is THE agent vulnerability, with no definitive fix to date. Mitigations: least privilege on tools, human approval for sensitive actions, separating data from instructions in the prompt. An agent with private-data access + untrusted content + an output channel = a dangerous combination (the “lethal trifecta”).

  • “The model executes my functions” — no. It emits JSON. If your code doesn’t validate parameters before execution, that’s your vulnerability, not the model’s.
  • “More tools = more capable agent” — the opposite: 40 tools with fuzzy descriptions degrade the choice. Few tools, well described, with sharp scopes.
  • “Prompt engineering is magic incantations” — incantations age badly from one model to the next; role, constraints, examples and output format stay effective everywhere.
  • Forgetting the loop’s cost: the full history is resent every turn. Without an iteration limit and prompt caching, the bill explodes silently.

🎤 In an interview — the word that makes the difference: “deterministic”. Say “I keep everything that can be deterministic outside the LLM — validation, permissions, orchestration — and only delegate the decision to the model”, and you have just shown you can build a production agent, not a demo.

Going further

S'entraîner sur ce sujet → Practice this topic →