Série · Certification Claude Certified ArchitectÉpisode 03 / 20
Claude Architect, épisode 3 : passer le contexte et gérer les sessions
Un sous-agent démarre amnésique : comment lui transmettre des résultats structurés, garder la trace des sources, remonter les contradictions, et choisir entre reprendre, dupliquer ou repartir de zéro.
Dans l’épisode 2, on a posé une règle : un sous-agent n’hérite de rien, le coordinateur doit lui injecter le contexte. Cet épisode répond à la question suivante, plus difficile : comment le lui transmettre sans rien perdre en route ? Et une fois le travail lancé, comment le reprendre le lendemain, l’explorer dans deux directions, ou repartir proprement quand tout a changé ?
Ce sont deux sujets que l’examen aime opposer à de fausses pistes : un rapport final dont les sources ont disparu, un sous-agent qui tranche seul entre deux affirmations contradictoires, une session reprise alors que le code a été refondu. À la fin de cet épisode, vous saurez trouver la cause de chacun.
Domaine 1 — Architecture agentique et orchestration (27 % de l'examen). Cet épisode couvre deux tâches :
- 1.3 — configurer l'appel d'un sous-agent, côté contexte transmis ;
- 1.7 — gérer l'état d'une session dans le temps.
Objectifs de l’épisode
À la fin, vous saurez :
- expliquer pourquoi un sous-agent « se réveille » sans mémoire, et ce que ça implique ;
- transmettre des résultats sous forme d’objets structurés, et non de prose ;
- séparer le contenu des métadonnées dans un résultat ;
- préserver la provenance grâce aux correspondances affirmation-source ;
- traiter deux sources contradictoires sans en faire disparaître une ;
- choisir entre reprendre, dupliquer ou repartir de zéro une session ;
- présenter un résumé injecté comme des hypothèses, pas comme des faits ;
- reconnaître les cinq anti-patterns que l’examen teste sur ces deux tâches.
Prérequis : l’épisode 2, en particulier l’outil Task, l’AgentDefinition et le champ
prompt comme seul canal de contexte.
1. Le sous-agent se réveille amnésique
Imaginez que vous dirigez un grand projet de recherche avec une équipe d’analystes brillants, chacun expert de son domaine. Vous briefez le premier : il creuse et revient avec dix sources excellentes et des idées remarquables. Vous lui dites : « Parfait, passe tes résultats à l’analyste n° 2. » L’analyste n° 2 vous regarde, perplexe : « Quels résultats ? Je viens d’arriver. »
C’est exactement ce qui se passe avec les sous-agents, par défaut.
prompt de l'appel Task.
Concrètement, votre coordinateur tourne depuis dix minutes. Il a appelé trois outils, lu
quatre documents, accumulé beaucoup de contexte. Puis il lance un sous-agent de synthèse.
Ce sous-agent reçoit une seule chose : le texte du champ prompt.
C’est voulu. Cette page blanche empêche la contamination du contexte : un sous-agent n’est pas parasité par des échanges qui ne le concernent pas. Mais la contrepartie est claire : tout ce dont il a besoin doit être écrit dans son prompt.
Un sous-agent n'hérite ni de l'historique du coordinateur, ni des résultats d'outils précédents, ni des découvertes des autres sous-agents, ni d'aucun état intermédiaire. Un sous-agent qui produit un résultat inventé ou générique a presque toujours reçu une consigne vague du type « synthétise les résultats précédents ».
2. Le mauvais prompt et le bon
Voici ce qu’on écrit naturellement, et pourquoi ça échoue.
- coordinateur → Task
« Voici les notes de recherche des agents précédents. Synthétise-les en un rapport final. » - ce que « pense » le sous-agent
Quelles notes ? Où sont-elles ? Je n'ai rien reçu… Je vais produire un rapport générique, ou en inventer le contenu.
La consigne a l’air raisonnable, et c’est ce qui la rend dangereuse : on suppose que le sous-agent « comprendra ». Il ne peut pas. Seul le coordinateur sait ce qui a été trouvé, parce que chaque sous-agent lui a rendu son résultat. Si le coordinateur ne recopie pas ces résultats dans le prompt, le sous-agent travaille à l’aveugle.
La bonne approche : le coordinateur rassemble les résultats sous forme d’objets structurés, les insère dans le prompt, et fixe des exigences de sortie.
import json
# Résultats rassemblés par le coordinateur, un objet par résultat
research_findings = [
{
"finding": "Claude's tool_use stop_reason requires the full assistant message "
"to be appended before tool results.",
"source_url": "https://docs.anthropic.com/agents/tool-use",
"source_title": "Anthropic Tool Use Documentation",
"page_number": None,
"retrieved_at": "2025-03-15T09:12:00Z",
"confidence": "high",
},
{
"finding": "Using an iteration cap as a primary stop condition is an anti-pattern.",
"source_url": "https://docs.anthropic.com/agents/loops",
"source_title": "Agentic Loop Best Practices",
"page_number": None,
"retrieved_at": "2025-03-15T09:14:00Z",
"confidence": "high",
},
]
# Construire le prompt de synthèse avec tout le contexte nécessaire
synthesis_prompt = f"""
You are a synthesis agent. Your task is to produce a structured research report.
FINDINGS TO SYNTHESIZE:
{json.dumps(research_findings, indent=2)}
Requirements:
- Every claim in the report MUST cite its source_url
- Preserve the retrieved_at date for temporal accuracy
- Flag any conflicting findings with both sources annotated
- Output format: JSON with keys: summary, claims[], conflicts[]
"""
# Le transmettre au sous-agent via l'outil Task
task_call = {
"type": "tool_use",
"name": "Task",
"input": {
"description": "Synthesize research findings into structured report",
"prompt": synthesis_prompt,
},
}Rien de nouveau dans la mécanique : c’est le même appel Task qu’à l’épisode 2. Ce qui change, c’est la qualité du contenu du prompt. Trois choses le rendent solide :
- les résultats y sont réellement présents, pas seulement évoqués ;
- ils sont structurés en JSON, pas résumés en prose ;
- les exigences de sortie imposent de garder les sources, les dates et les conflits.
3. Pourquoi les résumés en prose échouent
Voici le piège le plus subtil, celui qui fait le plus de dégâts en production : la perte d’attribution. Les sources disparaissent en silence au moment du résumé.
Pourquoi est-ce grave ? Parce que vous ne pouvez plus rien vérifier. Une affirmation du rapport vient-elle d’une source sérieuse, d’une source datée, ou d’une hallucination ? Plus personne ne peut le dire. Et une fois les résultats fondus dans de la prose, aucun programme en aval ne peut plus les trier, les router ou les contrôler automatiquement.
Résumer détruit naturellement les métadonnées, sauf si le format de sortie l'interdit explicitement. Mélanger des résultats dans de la prose ordinaire supprime la capacité à les router ou à les vérifier par programme en aval.
4. Règle n° 1 : séparer le contenu des métadonnées
La parade : ne jamais transmettre un résultat sous forme de prose, mais toujours sous forme d’objet typé, en deux parties bien distinctes.
Le contenu sert à raisonner. Les métadonnées servent à tout le reste : citer la
source, router l’information, et surtout la dater. Le champ retrieved_at est
souvent négligé, à tort : une information exacte en mars peut être fausse en octobre, et
seule la date permet de le savoir.
5. Préserver la provenance : les correspondances affirmation-source
Séparer contenu et métadonnées ne suffit pas si, à l’étape suivante, la synthèse refond tout en paragraphe. La solution est de garder à chaque étape un lien explicite entre chaque affirmation et sa source : une correspondance affirmation-source (claim-source mapping).
Au lieu de transmettre un résumé en texte, chaque étape de synthèse produit un objet avec
deux tableaux : les affirmations, chacune portant un source_id, et les sources,
chacune identifiée par ce même source_id.
# Chaque étape de synthèse DOIT produire des paires affirmation-source
intermediate_output = {
"claims": [
{
"claim_id": "c001",
"text": "Subagents do not inherit coordinator conversation history.",
"source_id": "src_001", # renvoie à l'objet source
"confidence": "high",
},
{
"claim_id": "c002",
"text": "Parallel subagents require multiple Task calls in one coordinator response.",
"source_id": "src_002",
"confidence": "high",
},
],
"sources": [
{
"source_id": "src_001",
"url": "https://docs.anthropic.com/multi-agent",
"title": "Multi-Agent Architecture Guide",
"retrieved_at": "2025-03-15T09:12:00Z",
},
{
"source_id": "src_002",
"url": "https://docs.anthropic.com/task-tool",
"title": "Task Tool Reference",
"retrieved_at": "2025-03-15T09:14:00Z",
},
],
"conflicts": [], # si deux sources se contredisent, les deux vont ici
}
# Pour passer au prochain agent, transmettre l'objet ENTIER.
# Ne jamais extraire seulement "claims" en laissant tomber "sources" :
# le prochain agent a besoin des deux pour produire un résultat exact.La règle vaut pour chaque étape du pipeline. Il suffit qu'un seul agent intermédiaire rende de la prose pour que la chaîne de provenance soit rompue, même si tous les autres respectent le format.
6. Quand deux sources se contredisent
En recherche réelle, c’est fréquent : deux sources parlent du même sujet et disent l’inverse. La tentation, pour un sous-agent, est de choisir celle qui lui paraît la plus crédible et d’ignorer l’autre. C’est exactement ce qu’il ne doit pas faire.
Le bon réflexe tient en trois étapes :
- Annoter les deux : créer un objet conflit qui contient les deux affirmations, chacune avec sa source.
- Marquer l’état comme
"unresolved": non résolu. - Remonter le conflit au coordinateur, qui prend la décision finale.
# Quand deux sources se contredisent, ajouter au tableau conflicts
conflict = {
"conflict_id": "conf_001",
"topic": "parallel subagent invocation",
"claim_a": {
"text": "Multiple Task calls in one response run in parallel.",
"source_id": "src_002",
},
"claim_b": {
"text": "Task calls are always sequential regardless of placement.",
"source_id": "src_003",
},
"resolution": "unresolved", # c'est le coordinateur qui décide
}Pensez à une équipe d’analystes et leur responsable. Quand deux analystes trouvent des résultats contradictoires, ils ne tranchent pas eux-mêmes : ils présentent les deux, avec leurs sources, et c’est le responsable qui décide. Le coordinateur joue ce rôle : il a la vision d’ensemble, les autres résultats, et peut lancer une vérification supplémentaire.
Une question porte sur des sources contradictoires dans un pipeline multi-agents ? La bonne réponse est toujours la même : annoter les deux avec leur attribution, marquer « non résolu », remonter au coordinateur. Ne jamais laisser un sous-agent résoudre un conflit en silence.
7. Gérer l’état dans le temps (tâche 1.7)
Changeons d’échelle. Jusqu’ici, on transmettait du contexte entre agents. Maintenant, on le transmet dans le temps : une analyse commencée hier, à reprendre aujourd’hui.
Avec Claude Code, on ne repart pas toujours de zéro. Il existe trois manières de préserver le contexte d’une session, chacune adaptée à une situation précise.
Explorez les trois approches :
Reprendre une session nommée. La plus directe : on donne un nom à la session au démarrage, et on la reprend plus tard.
- claude -n analyse-archi
- claude --resume analyse-archi
Quand ? Le contexte précédent est toujours valide et on continue la même tâche. Condition : dire explicitement à l'agent ce qui a changé depuis (section 8).
Dupliquer une session. Comme une branche Git : on part d'une analyse de référence, longue à construire, et on l'explore dans deux directions sans toucher à l'original.
- claude --resume analyse-archi --fork-session
Quand ? Pour comparer des approches parallèles à partir de la même base. Chaque copie hérite du même contexte, et aucune ne contamine l'autre.
Repartir de zéro, avec un résumé injecté. On abandonne l'ancienne session, et on démarre une session vierge à laquelle on donne un résumé structuré des conclusions précédentes.
- PRIOR ANALYSIS SUMMARY (from 2025-03-13): … treat these as hypotheses to validate
Quand ? Les résultats d'outils sont périmés, ou le contexte s'est tellement allongé qu'il dégrade le raisonnement du modèle.
8. Reprendre une session, et dire ce qui a changé
La commande est simple :
# Démarrer une session avec un nom
claude -n analyse-archi
# La reprendre plus tard, par son nom ou son ID
claude --resume analyse-archi
# Reprendre directement la conversation la plus récente
claude --continueMais reprendre ne suffit pas. Depuis la dernière fois, des fichiers ont peut-être été modifiés, des dépendances mises à jour, des exigences changées. L’agent, lui, se souvient de l’état d’avant. Il ne peut pas détecter seul ce qui a bougé : c’est à vous de le lui dire, au premier message.
# Bonne pratique : informer la session reprise des changements
resume_context = """
Resuming from previous analysis session.
CHANGES SINCE LAST SESSION:
- auth/middleware.py has been modified (new rate limiting added)
- requirements.txt updated (added redis==5.0.1)
- The TODO in payment_service.py line 142 has NOT been addressed yet
Please re-analyze only the changed files and continue from your prior findings.
"""Remarquez la dernière ligne : on demande une réanalyse ciblée, uniquement sur les fichiers modifiés. On garde ainsi tout le travail déjà fait, sans relire ce qui n’a pas changé.
Ne jamais reprendre une session sans indiquer explicitement ce qui a changé. L'agent ne peut pas le détecter automatiquement : il raisonnera sur des fichiers qui n'existent plus sous cette forme.
9. Dupliquer une session pour explorer
Vous avez construit une analyse d’architecture complète. Elle a pris du temps, l’agent connaît bien le code. Vous voulez maintenant comparer deux refontes possibles, sans abîmer cette base.
C’est le principe d’un fork sur GitHub : quand deux personnes dupliquent votre dépôt, chacune travaille sur sa copie, et votre dépôt d’origine reste intact.
import anthropic
client = anthropic.Anthropic()
# Imaginons une session de référence avec l'analyse complète du code
baseline_session_id = "baseline-arch-analysis-001"
# La dupliquer pour explorer deux approches de refonte différentes
fork_a = client.beta.sessions.fork(
session_id=baseline_session_id,
system_prompt_addition="Explore refactoring approach A: extract service layer pattern.",
)
fork_b = client.beta.sessions.fork(
session_id=baseline_session_id,
system_prompt_addition="Explore refactoring approach B: CQRS pattern.",
)
# Faire tourner les deux copies indépendamment :
# fork_a reçoit le même contexte de référence mais explore l'approche A,
# fork_b reçoit le même contexte de référence mais explore l'approche B.
# Aucune ne contamine l'autre.L'extrait ci-dessus illustre le raisonnement : une base commune, deux copies indépendantes. La méthode client.beta.sessions.fork() n'existe pas telle quelle dans le SDK Anthropic. Dans la pratique, on duplique une session ainsi :
- en ligne de commande :
claude --resume <session> --fork-session, qui crée un nouvel ID de session au lieu de réutiliser l'original ; - avec le Claude Agent SDK : les options
resume=<id>etfork_session=True(exemple ci-dessous).
from claude_agent_sdk import query, ClaudeAgentOptions
async def explorer(approche: str, baseline_session_id: str):
# Chaque appel crée une copie de la session de référence
options = ClaudeAgentOptions(resume=baseline_session_id, fork_session=True)
async for message in query(prompt=f"Explore refactoring approach: {approche}", options=options):
print(message)Dupliquer sert à explorer en parallèle, et seulement à ça. Pour prendre en compte quelques fichiers modifiés, on reprend la session en signalant les changements ; on ne la duplique pas.
10. Repartir de zéro, avec un résumé injecté
C’est la question qu’on se pose le plus souvent : quand reprendre, et quand repartir de zéro ? L’instinct pousse à reprendre, pour ne pas jeter le travail. Mais parfois, reprendre est la mauvaise décision.
- On reprend quand le contexte précédent est toujours valide.
- On repart de zéro quand les résultats d’outils sont périmés, ou quand le contexte, trop long, dégrade le raisonnement du modèle.
Quelques fichiers modifiés ? On reprend, en les signalant. Mais si 80 % du code a changé, l’ancien contexte n’est plus une aide : c’est un piège. L’agent raisonnerait sur une base de code qui n’existe plus.
Repartir de zéro ne veut pas dire tout oublier. On démarre une session vierge, et on lui injecte un résumé structuré des conclusions précédentes, présenté comme des hypothèses à vérifier.
# Au lieu de reprendre une session périmée, injecter les conclusions sous forme de résumé
prior_findings_summary = """
PRIOR ANALYSIS SUMMARY (from 2025-03-13):
- Architecture: monolith, Django 4.2, PostgreSQL 14
- Key coupling points: auth and billing share the User model directly
- Identified debt: payment_service.py has 3 untested code paths
- Recommended next steps: extract billing into separate bounded context
NOTE: This summary is from 2 days ago. The codebase has since been updated.
Please treat these as hypotheses to validate, not established facts.
Re-explore the current file structure before acting on these findings.
"""
# Démarrer une session vierge et y injecter le résumé
messages = [
{
"role": "user",
"content": prior_findings_summary
+ "\n\nPlease begin a fresh analysis of the current codebase state.",
}
]Le prompt doit présenter le résumé injecté comme des « hypothèses à vérifier », jamais comme des faits établis. Ce cadrage empêche le modèle d'accepter aveuglément des informations qui ont peut-être changé.
11. Choisir la bonne approche
Tout se résume en un tableau, et en trois questions à se poser dans l’ordre.
| État du contexte | Volatilité du code | Action |
|---|---|---|
| contexte valide, partagé | nulle ou faible | --resume + annoncer explicitement les changements |
| besoin d’explorer en parallèle | base commune | dupliquer la session (--fork-session) |
| résultats d’outils périmés | forte, ou beaucoup de temps écoulé | nouvelle session + hypothèses structurées injectées |
12. Les anti-patterns de l’examen
| ❌ Ne pas faire | ✅ Faire |
|---|---|
| transmettre des résumés en prose entre agents (l’attribution disparaît en silence) | transmettre un contexte structuré via des objets « résultat » |
| laisser un sous-agent résoudre seul un conflit entre sources (la provenance est détruite) | annoter les deux, marquer « non résolu », remonter au coordinateur |
| dupliquer une session pour prendre en compte quelques fichiers modifiés | dupliquer seulement pour explorer en parallèle |
| reprendre une session alors que le code a été fortement modifié | repartir de zéro et injecter des hypothèses |
| reprendre une session sans signaler ce qui a changé | déclarer explicitement la nouvelle réalité |
13. Deux scénarios d’examen
Scénario « recherche multi-agents ».
Le problème : l’attribution des affirmations est perdue, parce que les résultats de
recherche web ont été résumés en prose avant la synthèse.
La correction : exiger des objets structurés, avec des correspondances explicites
claim_id → source_id, et un format de sortie de synthèse qui les préserve.
Scénario « génération de code ».
Le problème : une analyse du code a tourné il y a trois jours ; depuis, le module de
paiement vient d’être refondu.
La correction : reprendre avec --resume, en indiquant précisément les fichiers modifiés
pour déclencher une réanalyse ciblée. On évite ainsi de refaire de zéro tout le travail de
référence.
Changez un détail du second scénario : l'analyse date d'un mois, et quatre ou cinq modules ont changé. La réponse s'inverse : le contexte est périmé, il faut repartir de zéro avec un résumé injecté sous forme d'hypothèses.
Fiche de révision
| Tâche 1.3 : appel de sous-agent | Tâche 1.7 : état de session |
|---|---|
| le contexte est vide par défaut | --resume exige d’annoncer les changements à la main |
| transmettre les résultats en objets structurés | dupliquer (fork) sert uniquement à explorer en parallèle |
exiger source_url, retrieved_at, confidence |
des résultats d’outils périmés imposent une nouvelle session |
| préserver les tableaux de correspondance affirmation-source | un résumé injecté se présente comme des hypothèses |
| un conflit non résolu remonte au coordinateur | l’ordre de décision : fraîcheur, puis parallèle, puis continuité |
Glossaire
| Terme | Définition |
|---|---|
| contamination du contexte | un agent parasité par des échanges qui ne le concernent pas ; la page blanche des sous-agents l’évite |
| objet « résultat » (finding) | un résultat transmis sous forme typée : un contenu, plus ses métadonnées |
| métadonnées | les informations qui permettent de citer, router et dater un résultat |
| perte d’attribution | la disparition des sources lors d’un résumé en prose |
| correspondance affirmation-source | le lien explicite, via source_id, entre chaque affirmation et sa source |
| objet conflit | l’objet qui garde deux affirmations contradictoires avec leurs sources, marqué non résolu |
| reprise de session | continuer une session existante avec --resume, en signalant les changements |
| duplication de session (fork) | copier une session de référence pour explorer une autre piste sans toucher à l’original |
| résultats d’outils périmés | des résultats qui ne reflètent plus l’état actuel du code ou des données |
Quiz d’entraînement
Ces questions sont de moi, écrites dans le style de l’examen. Ce ne sont pas des questions officielles. Choisissez une réponse : la correction s’affiche aussitôt, et le score se calcule en bas. Connecté, votre meilleur score est gardé dans votre compte, et « Recommencer » efface seulement vos réponses à l’écran. Sans compte, rien n’est enregistré.
Pour la suite
On sait maintenant transmettre un contexte complet à un sous-agent, garder la trace de chaque source, remonter les contradictions, et choisir entre reprendre, dupliquer ou repartir de zéro. L’épisode 4 continue le domaine 1 de l’examen.