EN

D0 — Fondamentaux de l'API

Voici les prérequis que le guide d'examen suppose acquis. Rien ici n'est un task statement à part entière : le guide teste ce que vous construisez par-dessus. À lire une fois, puis passer à D1.

Chaque section s'arrête là où commence un task statement. Quand une notion appartient à un autre domaine, vous en avez la définition en une phrase et un renvoi, jamais un lien nu.

Le guide décide aussi de ce qui n'est pas ici. Son hors-périmètre écarte l'architecture interne de Claude, les spécificités de la tokenisation, les modèles d'embedding, le streaming et l'authentification à l'API — le cycle de vie d'une requête s'arrête donc à la forme de l'appel et n'entre jamais dans le modèle. Ce que le guide laisse de côté, le corpus le consigne avec son motif dans courses/out-of-scope.md.

Table des matières
  1. Anatomie d'une requête Messages API
  2. Rôles, tours de parole et API sans état
  3. Les blocs de contenu
  4. Le champ stop_reason
  5. Les system prompts
  6. La fenêtre de contexte
  7. Questions d'auto-évaluation

1. Anatomie d'une requête Messages API

Un seul appel porte tout : client.messages.create(). Il n'y a pas de session à ouvrir ni quoi que ce soit à fermer.

Champ Obligatoire Rôle
model oui Le modèle Claude qui répond à la requête
messages oui L'historique de conversation que vous envoyez, du plus ancien au plus récent
max_tokens oui Plafond du nombre de tokens que la réponse peut contenir
system non Instructions permanentes, hors de la conversation
tools non Les schémas des outils que le modèle peut appeler — conçus en D2.1
tool_choice non Décide si le modèle peut répondre en prose ou doit appeler un outil — développé en D4.3
temperature non Le degré d'aléatoire dans la sélection des tokens, de 0 à 1

Deux d'entre eux sont assez souvent mal compris pour mériter d'être énoncés clairement.

max_tokens est une limite de sécurité, pas une cible. Réglez-le à 1000 et Claude s'arrête après 1000 tokens même s'il avait encore quelque chose à dire ; il ne cherche jamais à atteindre ce nombre. Il borne la sortie, pas la requête que vous envoyez.

system est un voisin de messages, pas l'un d'eux. Tous les autres champs de cette liste sont des voisins aussi : tools et tool_choice se placent au premier niveau du corps de la requête, jamais à l'intérieur d'un message.

{
  "model": "claude-sonnet-5",
  "max_tokens": 1024,
  "system": "Tu es un assistant spécialisé en analyse financière. Réponds de manière concise.",
  "messages": [
    { "role": "user", "content": "Quel est le chiffre d'affaires de l'entreprise X au T3 ?" }
  ]
}

system se place à côté de messages, jamais dedans. Glisser les instructions permanentes en premier message user est l'erreur de forme la plus courante sur ce point d'entrée, et elle change le poids que le modèle leur accorde.

Les identifiants exacts de modèles ne sont pas matière d'examen. temperature non plus. Le guide ne la nomme jamais et aucun task statement n'en dépend ; la ligne est là pour que vous reconnaissiez le champ dans un corps de requête qu'on vous présente, pas pour l'apprendre par cœur.

À tester — les questions d'auto-évaluation de cette page.

2. Rôles, tours de parole et API sans état

messages est une liste de dictionnaires, chacun avec un role et un content. Il y a deux rôles :

Rôle Qui l'écrit
user Vous — ce que vous envoyez à Claude
assistant Claude — ce qu'il a généré

Une conversation alterne entre les deux : tour user, tour assistant, tour user.

L'API ne stocke rien. Chaque requête est indépendante et ne garde aucune mémoire des précédentes. Demandez « Qu'est-ce que l'informatique quantique ? », obtenez une réponse, puis envoyez « Écris une autre phrase » sans rien d'autre : le modèle n'a aucune idée de ce qu'on lui demande de prolonger, donc il écrit une phrase sur tout autre chose.

La conversation multi-tours est donc un travail que vous faites, pas un service que l'API rend : envoyer le premier message user, ajouter la réponse de Claude à votre liste comme message assistant, ajouter la relance comme message user, et renvoyer la liste entière.

"messages": [
  { "role": "user",      "content": "Définis l'informatique quantique en une phrase" },
  { "role": "assistant", "content": "L'informatique quantique exploite des états quantiques pour traiter l'information." },
  { "role": "user",      "content": "Écris une autre phrase" }
]

C'est uniquement parce que les deux premiers tours sont encore dans le tableau que « Écris une autre phrase » veut dire quelque chose au troisième.

Tout ce qui doit encore être visible au cinquième tour doit se trouver dans le tableau que vous envoyez au cinquième tour. C'est la règle derrière la plupart des bugs « le modèle a oublié », et elle vaut pour les résultats d'outils exactement comme pour le texte. C'est la même règle qui impose de passer explicitement son contexte à un subagent lancé, puisqu'il n'hérite de rien.

N'envoyer que le dernier message en s'attendant à ce que les tours précédents soient encore là. Rien n'expire côté serveur, parce que rien n'y est stocké ; reconstruire l'historique est le travail de l'appelant, à chaque requête.

Teste-toi sur cette section

Q3 A stateless API and a vanished tool_result

Scenario: A build pipeline drives Claude across several requests. From one request to the next, a tool_result produced earlier is no longer visible to the model.

Question: What is the most likely cause?

A) The API keeps no state, and the caller did not resend the earlier tool_result blocks.

B) A tool_result block expires server-side soon after it is submitted, so later requests miss it.

C) The max_tokens value is too low to hold the tool_result, so the oldest blocks drop first.

D) A session_id parameter is missing, so the server cannot attach this request to the earlier turn.


Answer: the API is stateless and the history was not resent

Why: nothing carries over between requests. Every call must ship the complete messages array, tool results included; rebuilding that history is the caller's job. The same rule is what forces you to pass context explicitly to a spawned subagent.

Why the others are wrong:

  • Nothing expires server-side, because nothing is stored there.
  • That budget bounds the output length, not the size of the history you send; and no block is dropped for you, because none is kept for you.
  • The Messages API has no such parameter.

Toutes les questions de la banque sur 1.3

3. Les blocs de contenu

Le content d'une réponse n'est jamais une simple chaîne mais une liste de blocs, chacun avec son type. Lire une réponse comme du texte ne marche que parce que vous avez indexé cette liste : message.content[0].text est le texte du premier bloc, pas celui du message. Les deux sens ne sont pas symétriques : une requête accepte l'une ou l'autre forme, une chaîne simple ou une liste de blocs.

Type de bloc Sens Contenu
text dans les deux sens De la prose, à lire par l'utilisateur
tool_use de l'assistant Le nom de l'outil et les arguments choisis par le modèle
tool_result de vous, dans un message user La sortie de l'outil que vous avez exécuté

Une seule réponse d'assistant porte couramment plusieurs blocs à la fois, par exemple un bloc texte qui explique ce que le modèle s'apprête à faire plus un bloc tool_use qui le demande. Un bloc tool_result porte trois champs : tool_use_id, qui correspond à l'id du bloc tool_use auquel il répond ; content, la sortie de la fonction sérialisée en chaîne ; et is_error, un booléen. Il repart dans un message user, accompagné de l'historique complet.

{ "role": "assistant", "content": [
    { "type": "text", "text": "Je consulte la commande." },
    { "type": "tool_use", "id": "toolu_01X", "name": "lookup_order",
      "input": { "order_id": "ORD-67890" } }
]},
{ "role": "user", "content": [
    { "type": "tool_result", "tool_use_id": "toolu_01X",
      "content": "{ \"status\": \"shipped\", \"total\": 42.90 }",
      "is_error": false }
]}

Entre ces deux messages, c'est votre code qui a exécuté lookup_order. Le modèle n'exécute jamais rien ; il émet une demande structurée et attend.

N'ajouter que le texte affiché et laisser tomber le bloc tool_use. C'est l'appariement avec tool_result dont dépend la requête suivante : l'historique devient impossible à traiter. Ajoutez tout response.content, et gardez les schémas d'outils d'origine sur la requête de suivi même si aucun autre appel n'est attendu.

Un outil se déclare en JSON Schema, en trois parties : name, description — ce que fait l'outil, quand l'utiliser, ce qu'il retourne — et input_schema pour les arguments. Voilà l'anatomie, et elle s'arrête là. Savoir quelle formulation fait choisir au modèle le bon outil parmi plusieurs voisins relève de la conception d'outils, développée en D2.1 ; se servir d'un schéma pour forcer une charge utile conforme est la sortie structurée, développée en D4.3.

Toutes les questions de la banque sur 2.1

4. Le champ stop_reason

Quand le modèle s'arrête, la réponse dit pourquoi dans stop_reason, et c'est ce champ, pas la présence d'un bloc texte, qui vous dit si une réponse est terminée.

Valeur Ce qui a mis fin à la génération
end_turn Le modèle est arrivé à une fin naturelle et n'avait rien à ajouter
max_tokens Le budget de sortie que vous avez fixé s'est épuisé en cours de génération
stop_sequence L'une de vos chaînes stop_sequences est apparue
tool_use Le modèle appelle l'un de vos outils et attend que vous l'exécutiez
pause_turn Une boucle d'outil serveur a atteint sa limite d'itérations, 10 par requête par défaut
refusal Le modèle a refusé pour des raisons de politique de sécurité
model_context_window_exceeded La réponse a rempli la fenêtre de contexte du modèle

stop_details vaut null pour toutes les valeurs sauf refusal, où il porte la catégorie de politique concernée. model_context_window_exceeded est la plus récente : Sonnet 4.5 et les modèles plus récents la renvoient sans en-tête beta, et les modèles antérieurs ont besoin de l'en-tête model-context-window-exceeded-2025-08-26 pour l'activer.

{
  "id": "msg_01ABC",
  "role": "assistant",
  "content": [
    { "type": "text", "text": "Je consulte la commande." },
    { "type": "tool_use", "id": "toolu_01X", "name": "lookup_order",
      "input": { "order_id": "ORD-67890" } }
  ],
  "stop_reason": "tool_use",
  "stop_details": null
}

Cette réponse porte du texte et une demande d'outil, et c'est précisément pourquoi la présence de texte ne peut pas servir de signal de fin.

end_turn est la seule valeur qui signifie terminé. Une réponse avec stop_reason: "max_tokens" porte un bloc texte comme n'importe quelle autre, mais elle a été coupée en pleine phrase. Un code d'affichage qui teste la présence de texte au lieu de lire stop_reason présentera un brouillon tronqué comme un texte fini. C'est le distracteur classique sur ce champ.

Deux valeurs méritent d'être distinguées même si une seule paire est testée. Une réponse qui attend votre outil dit toujours tool_use, et vous la poursuivez en envoyant des blocs tool_result. pause_turn concerne un outil serveur à court d'itérations, et vous la poursuivez en renvoyant le contenu de l'assistant tel quel.

Le guide ne vous demande jamais que de distinguer tool_use de end_turn. C'est cette paire qui pilote la boucle, et c'est tout ce que teste TS 1.1. Transformer cette vérification en boucle — appeler, inspecter stop_reason, exécuter, ajouter, rappeler — est la boucle agentique, développée en D1.1. D0 s'arrête à nommer le signal.

Teste-toi sur cette section

Q1 A stop_reason your display code ignores

Scenario: A drafting agent produces long documents. Your display code shows the API response to the user whenever content holds a text block. On one long document the response cuts off mid-sentence, yet the code still presents it as the finished draft. Inspecting the response, stop_reason is "max_tokens".

Question: What does that value mean, and what should the display code check before treating a response as final?

A) The response is complete; "max_tokens" caps the size of the request being sent, not the length of the output.

B) The token budget ran out mid-generation; only "end_turn" means the response is complete.

C) The model refused to continue for safety reasons, so nothing should be shown and the attempt should be escalated for human review instead.

D) A server-side tool call was interrupted mid-turn, so resending the same request unchanged lets the paused turn pick up where it left off.


Answer: "max_tokens" means truncated output, not completion

Why: stop_reason distinguishes several reasons generation stopped, and only "end_turn" marks a natural, complete stopping point. "max_tokens" means the output budget ran out mid-generation — the presence of a text block in content says nothing about whether that text is the whole answer. Scope note: among stop reasons, the exam guide names only the pair that drives the agentic loop, and that loop is what the task this sheet prepares tests. "max_tokens", "refusal" and "pause_turn" come from the API reference — D0 prerequisite material, not extra exam surface.

Why the others are wrong:

  • Reverses cause and effect: the output token budget is exactly why this value was returned.
  • Describes "refusal", a distinct value with a distinct cause. Nothing was refused here, so withholding the draft and escalating would stall a run that only needs continuing.
  • Describes "pause_turn", which concerns an interrupted server tool, not an exhausted token budget. Nothing is paused waiting to resume, so an identical resend would simply regenerate the same truncated draft.

Toutes les questions de la banque sur 1.1

5. Les system prompts

Le paramètre system est une simple chaîne passée à côté de messages, et il se place hors de la conversation : ce n'est pas un tour, il n'a pas de rôle, et ce n'est pas quelque chose à quoi le modèle répond. Il façonne comment Claude répond, pas *ce qu'*il répond.

Prenez l'exemple d'un tuteur de maths. Sans system prompt, « Comment résoudre 5x + 2 = 3 pour x ? » donne aussitôt une solution complète pas à pas, ce qui est correct et inutile pour enseigner. Avec :

Tu es un tuteur de maths patient.
Ne réponds pas directement aux questions de l'élève.
Guide-le vers la solution, étape par étape.

la même question revient en « Quelle serait selon toi une bonne première étape pour isoler x ? ». Même modèle, même tour user ; c'est l'instruction permanente qui a changé le comportement.

Voilà à quoi sert un system prompt : assigner un rôle, et le modèle répond comme quelqu'un dans ce rôle le ferait ; énoncer des contraintes durables, et elles tiennent à tous les tours sans être répétées. Elles tiennent parce que vous les renvoyez à chaque requête, pas parce que l'API s'en souvient, et vous les payez à chaque fois.

Mettre le system prompt en premier message user. Il se lit alors comme du contexte conversationnel plutôt que comme une instruction permanente, et il entre en concurrence avec les tours qui l'entourent au lieu de les surplomber.

Une instruction system porte plus loin que n'importe quelle formulation à l'échelle d'un tour, assez loin pour qu'un seul mot-clé absolu prenne le pas sur des descriptions d'outils par ailleurs bien écrites. « Vérifie toujours l'identité du client » fera appeler l'outil le plus proche sémantiquement à chaque tour. Comment cette instruction prend le pas, et comment la formuler autrement, est développé en D2.1.

Une note pratique : l'API n'accepte pas system=None, donc une fonction de chat réutilisable ne doit ajouter la clé que si un prompt a réellement été fourni.

Toutes les questions de la banque sur 2.1

6. La fenêtre de contexte

La fenêtre de contexte est le budget de tokens fini dans lequel chaque requête doit tenir, et les deux faits précédents le retournent contre vous : l'API ne garde aucun état, donc chaque requête embarque l'historique entier. L'historique n'est donc pas gratuit. C'est un coût récurrent qui croît de façon monotone avec la conversation, sauf si vous y faites quelque chose.

Ce qui s'accumule, à chaque requête :

Ce que vous renvoyez Pourquoi c'est là
Le prompt system Il tient d'un tour à l'autre parce que vous le renvoyez, pas parce qu'il est stocké
Chaque tour user et assistant passé Rien n'est stocké côté serveur
Chaque bloc tool_use et tool_result Les enlever casse l'appariement
Les schémas d'outils complets Obligatoires à chaque requête, même quand aucun appel ne suit

Les résultats d'outils sont la part qu'on sous-estime. Un outil qui retourne un gros enregistrement met cet enregistrement dans l'historique pour tout le reste de l'exécution, et vous le payez à chaque tour suivant, pas une seule fois.

lookup_order → 42 champs retournés, 5 utiles pour l'éligibilité au retour
  order_id, status, total, items, return_eligible          ← utiles
  warehouse_route, carrier_scac, pick_wave, audit_flags,
  promo_ledger, tax_jurisdiction, … (37 autres)            ← poids mort ici

3 commandes consultées = 126 champs renvoyés à chaque tour suivant, 15 le méritent.

Le guide nomme trois modes de défaillance d'une fenêtre pleine, et D0 va exactement aussi loin que les nommer : lost-in-the-middle, où un élément enfoui au milieu d'un long contexte passe inaperçu alors que le début et la fin sont lus de façon fiable ; l'accumulation, la croissance montrée ci-dessus ; et la progressive summarization, où comprimer l'historique pour faire de la place sacrifie d'abord les nombres, les dates et les détails précis.

Reconnaissez ici les trois modes de défaillance ; les remèdes ne sont pas ceux de D0. Élaguer les sorties d'outils verbeuses, extraire des faits structurés et ordonner l'entrée selon la position sont développés en D5.1. Le retrieval et le chunking ne sont pas la réponse attendue par le guide. Il les met hors périmètre, et ce corpus aussi.

Toutes les questions de la banque sur 5.1

7. Questions d'auto-évaluation

Q2 Which part of a tool definition decides the routing

Scenario: An HR assistant exposes search_policy_doc ("Retrieves policy content") and search_payroll_record ("Retrieves payroll data"). Both accept employee identifiers of a similar shape, and the model routinely picks the wrong one.

Question: Which part of a tool definition drives that choice?

A) The position of each tool in the request's tools array.

B) The tool name, which outranks the rest of the definition.

C) The description, which is the primary selection mechanism.

D) The size of the input_schema: the model prefers the simplest one.


Answer: the description

Why: the model selects a tool by reading the definitions, and the description is where the meaning lives. Two one-line descriptions give it nothing to tell the tools apart, so misrouting becomes structural. The fix is to state input formats, example requests, edge cases and the boundary with neighboring tools.

Why the others are wrong:

  • Declaration order is not a selection criterion.
  • The name helps, but it cannot carry input formats, edge cases or usage boundaries.
  • The schema describes the arguments once a tool has been chosen; it does not decide which tool to choose.
Q4 A standing rule that drags a tool onto every turn

Scenario: A greenhouse operations assistant opens its system prompt with "Every answer must reflect the current sensor readings." Logs show read_sensors firing on each turn, including when a grower asks how a cultivar name should be spelled in the planting log. Each tool definition spells out its inputs and where its job ends.

Question: What stops the needless calls?

A) Add few-shot examples of clerical turns answered without any sensor call, so the assistant can copy the pattern on the next spelling question.

B) Have the client drop read_sensors from the tools array whenever it judges the incoming question clerical.

C) Name the conditions that call for a reading, and retire the absolute sentence.

D) Cache the last reading for ten minutes so repeat turns reuse it instead of calling out again.


Answer: state when a reading is required, and drop the blanket rule

Why: "every answer" reads as a permanent trigger, and the model binds it to whichever tool the wording resembles most. A rule phrased with no exceptions outranks the tool definitions, however careful they are — which is why the scenario tells you those definitions are sound. Spelling out the situations that genuinely need a reading removes the trigger while keeping the check where it earns its cost.

Why the others are wrong:

  • Examples cannot outvote a rule that still admits no exception; the model treats them as odd cases rather than as the boundary.
  • Moves the decision to the caller, which must now classify a question before the model has read it, and leaves the misleading rule in place.
  • Cheaper calls, identical behavior: a spelling question still travels through the sensor path, and a stale value is the wrong answer where readings matter.
Q5 A triage loop that never writes its answer

Scenario: A ticket-triage client runs its own loop: send the request, run whatever tool comes back, append the result, send again. To stop the assistant from chatting while work remains, the client sets tool_choice to the value that guarantees a call — and it sets it on every request of the loop. Runs now end only when the client's iteration cap trips, and no written answer ever arrives.

Question: Why does the run never reach one?

A) That value binds the first request alone; the later ones revert to the automatic setting, so the assistant keeps reaching for lookup_account long after the answer is available.

B) Each tool result is appended as a user turn, and a request whose last turn came from the user can only be answered by another call.

C) Repeating that value on every request removes the assistant's only way of finishing, which is a turn that ends in text; the client should guarantee the opening call and leave the remaining requests on the automatic setting.

D) The iteration cap sits below the number of declared tools, so the client cuts the run short before classify_ticket and its neighbours have all been tried.


Answer: the setting also forbids the text-only turn a run has to end on

Why: tool_choice: "any" promises exactly one thing, on every request that carries it: a tool will be called. Sent once, that pins the opening step. Sent on every request, it also outlaws the closing one, since a turn answering in prose is no longer permitted. Handing the later requests back to tool_choice: "auto" restores the choice between calling again and answering.

Why the others are wrong:

  • The field is read afresh on each request; it neither expires nor decays, and the loop here restates it every time.
  • A user turn carrying a tool result can be answered in prose just as readily as with another call — that is precisely what the automatic setting permits.
  • The cap is what halts a run that would otherwise not halt at all; raising it buys further calls, never a written answer.
Q6 A mandatory field the source cannot fill

Scenario: An invoice extraction tool lists discount_pct among its required properties, yet plenty of invoices grant no discount. Reviewers keep finding discount figures that appear nowhere on the invoice.

Question: What is happening, and what removes the cause?

A) The API validates the payload against the schema and rejects the call as invalid, so nothing reaches the pipeline.

B) The model invents a figure to satisfy the constraint; make the property nullable and no longer mandatory.

C) The model leaves the property empty, and the pipeline should read an empty value as absent.

D) The model skips the tool call whenever a mandatory property has no source value.


Answer: the model invents a figure, so make the property nullable and optional

Why: a mandatory property leaves the model choosing between breaking the schema and making something up, and it makes something up. Declaring it "type": ["number", "null"] and taking it out of required gives the model an honest way to report absence.

Why the others are wrong:

  • Validation covers schema conformance, never truthfulness: an invented number conforms perfectly.
  • Nothing empties the property while the schema still demands a value.
  • The tool does get called; it is the payload that is wrong.

Toutes les questions de la banque sur 2.3

Toutes les questions de la banque sur 4.3


CCA Révision — D0 — Fondamentaux de l'API · 2026

↑