Skip to content

Resources — Blogs, Papers, Repos, Communities

Curated. Quality over quantity. Read what's here before adding more.

Comment lire cette page (mental model). Une liste de liens n'est pas une ressource — c'est une dette de lecture. Le piège du dev senior qui se reconvertit, c'est le bookmark hoarding : 200 onglets ouverts, zéro chose intégrée. Traite cette page comme un système : (1) un flux quotidien court et borné, (2) une file de lecture profonde (papers + source) avec un budget hebdo fixe, (3) un second brain où tu écris ce que tu apprends (Obsidian/Logseq/un repo notes/ versionné). Si tu ne produis rien à partir d'une ressource (une note, un POC, un test), elle ne compte pas. La règle staff : read to build, not to feel informed.

Le champ AI bouge vite — calibre la demi-vie. Trois couches de durabilité, à pondérer différemment :

  • Fondamentaux (demi-vie : années) — transformers, attention, RAG, eval. Investis lourd. Ça ne périme pas.
  • Patterns d'ingénierie (demi-vie : ~12-18 mois) — agent loops, tool use, MCP, caching. Réapprends à chaque génération de modèle, mais les principes transfèrent.
  • Specifics produit (demi-vie : ~3 mois) — model IDs, prix, syntaxe d'API exacte. Ne mémorise jamais ça : va à la source canonique au moment où tu codes (docs officielles, SDK). Cette page le rappelle là où c'est pertinent.

Daily / Weekly reading

ResourceFrequencyWhy
Anthropic blogWeeklySource of truth for Claude + agents
OpenAI blogWeeklyNew models, Realtime API updates
LangChain blogWeeklyLangGraph patterns, eval, deploys
Latent Space (Swyx)WeeklyThe AI engineering podcast + newsletter
Hacker NewsDailyFilter for AI/LLM stories
Hugging Face daily papersDailyTrack research

Newsletters (subscribe)

  • AI Engineer Newsletter (Swyx + Alessio) — must-read
  • Ben's Bites — daily AI news, 5 min read
  • TLDR AI — daily, business-focused
  • The Batch (Andrew Ng / DeepLearning.AI) — weekly
  • Import AI (Jack Clark) — weekly, deeper analysis
  • Interconnects (Nathan Lambert) — research-focused
  • Pierre's Substack (Pierre Bittner, FR AI) — French perspective

Canonical sources — go here, never memorize

Les specifics produit (model IDs, prix, syntaxe d'API) ont une demi-vie de ~3 mois. Ne les apprends pas par cœur : connais où est la vérité, et vas-y au moment de coder.

Tu cherches…Source de vérité (pas un blog)
Model IDs, context windows, capacitésAPI Models (GET /v1/models, client.models.list()) — données live, pas un tableau caché
Prix par million de tokensAnthropic pricing / OpenAI pricing
Breaking changes lors d'un upgradeMigration guide officiel du provider — lis-le avant de bump un model ID
Syntaxe exacte d'un SDKLe repo du SDK officiel (anthropic-sdk-python, @anthropic-ai/sdk) + ses examples/

Snapshot Anthropic (Anthropic, 2026 — vérifie toujours à la source avant de chiffrer en prod) :

TierModel ID (alias)Prix in / out (USD / 1M tok)Context / Max outUsage type
Flagshipclaude-opus-4-85 / 251M / 128Klong-horizon agentic, raisonnement difficile
Midclaude-sonnet-4-63 / 151M / 64Kmeilleur ratio vitesse/intelligence
Cheapclaude-haiku-4-51 / 5200K / 64Kclassification, extraction, high-volume

Le prix Opus 4.8 (5 / 25) vaut y compris sur les 1M de contexte — pas de premium long-context, contrairement à beaucoup de concurrents qui doublent le tarif au-delà de 200K. C'est un argument d'archi : tu peux pousser un gros contexte sans recalculer ton coût par palier.

⚠️ Pièges de version qui périment vite — à ne plus écrire. Pas de Opus 4.7 ni Opus 4.6 comme flagship, pas de model ID avec un suffixe de date fabriqué (claude-opus-4-8-20260101 n'existe pas — l'alias est l'ID complet). Pour le thinking : la forme thinking: {type: "enabled", budget_tokens: N} est retirée sur les modèles 4.7/4.8 (HTTP 400, comme temperature/top_p/top_k) — utilise le thinking adaptatif (thinking: {type: "adaptive"}) plus output_config.effort (low/medium/high/xhigh/max; xhigh/max sur Opus-tier, pas Sonnet/Haiku). Note que thinking adaptatif est off par défaut sur 4.7/4.8 : un appel sans champ thinking ne réfléchit pas. Pour les sorties structurées : préfère client.messages.parse() avec un schéma Pydantic/zod (ou output_config.format) plutôt que du prompting XML/JSON à la main — l'ancien output_format top-level est déprécié. Les prefills d'assistant (dernier tour role: "assistant") renvoient aussi 400 sur 4.6+. Détails complets dans la skill claude-api et la note provider de la section Embeddings.


Papers to read (in this order)

Foundational :

  1. "Attention Is All You Need" (Vaswani 2017) — transformers
  2. "BERT" (Devlin 2018) — encoders
  3. "GPT-3" (Brown 2020) — in-context learning
  4. "Chain-of-Thought" (Wei 2022) — reasoning
  5. "Retrieval-Augmented Generation" (Lewis 2020) — RAG origin

RAG : 6. "Dense Passage Retrieval" (Karpukhin 2020) 7. "Self-RAG" (Asai 2023) — reflective RAG 8. "Lost in the Middle" (Liu 2023) — context limits 9. "Corrective RAG" (Yan 2024) — eval + correction 10. "GraphRAG" (Microsoft Research 2024)

Agents : 11. "ReAct" (Yao 2022) — reasoning + acting 12. "Toolformer" (Schick 2023) — tool use 13. "Reflexion" (Shinn 2023) — self-reflection 14. "AutoGPT" / "BabyAGI" technical reports 15. "Voyager" (Wang 2023) — open-ended agents 16. "Communicative Agents" (Park 2023) — multi-agent

2026 essential : 17. Anthropic's "Building effective agents" (2024-2025) — pattern catalog 18. Anthropic's MCP whitepaper / spec docs

→ Don't try to read all 18. Start with #1, #5, #11, #17 — the rest as you specialize.

How a staff engineer reads a paper (don't read linearly)

Tu viens du dev : tu n'as pas besoin de prouver les théorèmes, tu as besoin de savoir quoi reproduire et quand l'utiliser. Lis dans cet ordre, pas top-to-bottom :

  1. Abstract → figures → conclusion d'abord. Tu sais en 5 min si le papier mérite plus.
  2. La question : qu'est-ce que ça remplace ? Tout papier est un delta sur un baseline. Si tu ne sais pas dire "avant ce papier, on faisait X et ça cassait à cause de Y", tu n'as pas compris la contribution.
  3. Le tableau d'ablation > les benchmarks. Les benchmarks SOTA périment. L'ablation te dit quelle partie du système porte le gain — c'est ce qui transfère à ton produit.
  4. Lis avec la question prod en tête : "combien ça coûte en latence/tokens, et qu'est-ce qui le fait échouer en prod ?" La plupart des papiers RAG/agents mesurent l'accuracy sur un dataset propre et ignorent la latence p99, le coût par requête, et le comportement adversarial. Ces angles morts sont exactement ce que ton interview de staff va sonder.

Méfiance saine. Un papier "+8 % sur HotpotQA" peut être (a) du dataset contamination, (b) un gain qui disparaît hors-distribution, (c) un setup non reproductible à coût raisonnable. Les bons signaux : code public qui tourne, ablations honnêtes, limitations écrites par les auteurs eux-mêmes. Les listes "awesome-papers" sur GitHub n'ont aucun contrôle qualité — c'est de la curation par popularité, pas par rigueur.


GitHub repos to study

Core libraries (read their source code)

Example apps to fork & learn from

Awesome lists


Tools to know / use

Mental model — les 4 plans d'une app LLM en prod. Quand tu choisis un outil, sache à quel plan il appartient. C'est ce qui distingue un dev qui colle des libs d'un staff qui architecture :

  • Data plane — embeddings, vector DB, retrieval. Le coût scale avec le volume de documents.
  • Inference plane — l'appel modèle lui-même (gateway, caching, retries, streaming). Le coût scale avec le trafic.
  • Eval plane — comment tu sais que ça marche (offline regression, LLM-as-judge, A/B en prod). Sans ça, tu "vibes-check" en prod et tu te fais réveiller la nuit.
  • Observability plane — traces, tokens, latence p50/p95/p99, taux d'erreur par type. C'est le premier truc qu'un VP te demandera ; c'est aussi le premier qu'on oublie de câbler.

Eval

  • Ragas — RAG eval framework (faithfulness, relevancy, context precision/recall)
  • LangSmith — LangChain's eval + observability
  • Phoenix — open source LLM observability (OpenTelemetry-based)
  • TruLens — eval + observability
  • PromptFoo — prompt regression tests (CI-friendly)
  • Braintrust — eval + prompt playground + experiment tracking

Comment un staff raisonne sur l'eval. L'ordre d'investissement, pas l'inverse :

  1. Un golden set de 30-50 exemples annotés à la main bat n'importe quel framework fancy. Sans dataset, l'outil ne sert à rien. Commence par ça.
  2. Metrics déterministes d'abord (exact match, regex, schema-valid JSON, citations présentes) — gratuites, rapides, reproductibles. Réserve le LLM-as-judge aux dimensions subjectives (faithfulness, helpfulness).
  3. LLM-as-judge a un coût et un biais : il est non-déterministe, ~30-50× plus cher qu'un check Python, et tend à préférer ses propres outputs (self-enhancement bias) et les réponses longues (verbosity bias). Pin le modèle juge, fixe effort, demande un score avec justification (le forcer à raisonner réduit le bruit), et calibre le juge contre tes annotations humaines avant de lui faire confiance.
  4. Offline (regression en CI) ≠ online (A/B en prod). L'offline empêche les régressions ; l'online mesure l'impact réel. Tu as besoin des deux. Un score offline qui monte avec un business metric qui ne bouge pas = ton eval mesure la mauvaise chose.

Observability

  • Langfuse — open source LLM tracing/observability, self-hostable (souverain FR)
  • Helicone — proxy-based observability + caching, faible friction
  • Phoenix / Arize — tracing + drift, OTel-natif
  • OpenTelemetry + ton stack existant (Grafana/Datadog) — souvent suffisant : un span par appel LLM, attributs tokens_in/out, cost, model, cache_read_tokens, latency_ms

Le réflexe non-négociable. Logge response.usage sur chaque appel (input/output/cache-read tokens) et dérive le coût. C'est la seule façon de répondre à "pourquoi la facture a triplé ce mois-ci" sans deviner. Un cache hit rate qui s'effondre (vérifie cache_read_input_tokens) ou un agent qui boucle sur des tool calls sont les deux coupables habituels — invisibles sans observability.

Vector DBs

  • pgvector — Postgres extension (default choice FR — une DB de moins à opérer)
  • Qdrant — Rust, fast, sovereign, hybrid + payload filtering
  • Pinecone — managed default
  • Weaviate — hybrid search built-in
  • Chroma — prototyping (ne le mets pas en prod sous charge)

Tradeoff staff. Ne commence pas par une vector DB dédiée. Si tu as déjà Postgres (très probable avec ton stack NestJS), pgvector jusqu'à ~1-5M de vecteurs t'évite un système distribué de plus à opérer, sauvegarder et monitorer — operational simplicity beats theoretical throughput. Passe à Qdrant/Pinecone quand tu mesures un vrai problème : latence de recherche p95 qui dépasse ton SLO, ou besoin de filtering/sharding que pgvector ne tient pas. "On migrera si la latence devient un problème" est une réponse senior ; "j'ai pris Pinecone parce que c'est le standard" ne l'est pas.

LLM Routers / Gateways

Pourquoi une gateway (et quand t'en passer). Une gateway centralise : routing/fallback multi-provider, budget caps, rate-limit handling, caching, et un point unique de logging. Le coût caché : un hop réseau de plus (latence + un SPOF), et tu perds parfois l'accès aux features natives les plus récentes d'un provider (caching avec cache_control, structured outputs natifs, thinking adaptatif) tant que le proxy ne les expose pas. Pour un seul provider, le SDK officiel + un wrapper maison de ~50 lignes (retries typés, timeout par appel, logging de usage) bat souvent une gateway. Prends la gateway quand le multi-provider ou les budget caps cross-équipe deviennent un vrai besoin.

Voice

Embeddings

  • Cohere embed-multilingual-v3 / embed-v4 — strong FR, multilingue
  • OpenAI text-embedding-3-large — default généraliste, dimensions ajustables (MRL)
  • Voyage voyage-3 — souvent en tête du MTEB pour le retrieval
  • BAAI/bge-m3 / intfloat/multilingual-e5-large — open source, self-hostable (souverain), multilingue
  • MTEB Leaderboard — benchmarks (filtre sur ta langue + ta tâche, pas le score global)

Note provider — Claude n'a pas d'API d'embeddings. Anthropic ne sert pas de modèle d'embeddings : pour la couche retrieval, utilise un des providers ci-dessus (Cohere/Voyage/OpenAI ou open source self-hosted), et garde Claude pour la génération (synthèse, reranking par prompt, réponse finale citée). C'est le pattern normal : embeddings d'un provider, generation d'un autre. Choisis l'embedding par MTEB sur ta langue (FR) et ta tâche (retrieval) — un score global élevé sur de l'anglais ne dit rien de tes perfs sur des docs juridiques français.


Communities

CommunityWhereWhy
LangChain Discorddiscord.gg/langchainActive, devs answering each other
Anthropic Builders Discordanthropic.com/discordClaude-focused
OpenAI Devs Forumcommunity.openai.comOpenAI updates + Q&A
HuggingFace Discordhuggingface.coOpen source models
AI Engineer Slacklatent.space / SwyxAI engineers community
r/LangChainreddit.com/r/LangChainPractitioner pulse
r/LocalLLaMAreddit.com/r/LocalLLaMAOpen source / self-hosted
r/MachineLearningreddit.com/r/MachineLearningResearch + industry

French AI community


Conferences / events (juin 2026 → juin 2027)

  • AI Engineer Summit (Q4 2026) — virtual, free
  • NeurIPS (Dec 2026) — research, but interesting for trends
  • VivaTech (Paris, juin 2026) — networking FR (vient de passer — mark juin 2027)
  • AI Paris (annual, ~Mai/Juin) — already past for 2026, mark 2027
  • Apple WWDC (juin 2026) — Apple Intelligence updates (vient de passer — mark juin 2027)
  • OpenAI DevDay (TBD 2026)

→ Pick 1-2/year max. Quality of network > quantity of badges.


Books (optional but useful)

  • Hands-On Large Language Models (Alammar & Grootendorst, 2024) — best book to date
  • Designing Machine Learning Systems (Chip Huyen, 2022) — production ML thinking
  • The Hundred-Page Machine Learning Book (Burkov) — quick ML refresher
  • AI Engineering (Chip Huyen, 2025) — newest, very practical

Anti-resources (waste of time)

  • ❌ YouTube "10 hour LangChain tutorial" — outdated within 3 months
  • ❌ Most Medium articles by random authors — quality control nul
  • ❌ Paid bootcamps (Le Wagon AI etc.) — $5-10k for content available free
  • ❌ "AI Engineer roadmap" YouTube videos — usually 3 years old, recycled
  • ❌ Tout post qui chiffre des prix ou des model IDs sans lien vers la doc officielle — périme en semaines ; va à la source canonique
  • ❌ "Awesome-X" lists comme curation de qualité — c'est de la curation par popularité, zéro contrôle (utile comme index, pas comme filtre)
  • ❌ Threads Twitter/X "10 prompts qui vont changer ta vie" — bruit ; le signal est dans les docs provider et les papers

🏋️ Exercices

Le learner veut du dur. Ces exercices ne sont pas "ajoute un lien" — chacun te force à produire, mesurer, et défendre. Fais-les dans l'ordre : 1→6 construisent un système de veille puis une app instrumentée (chacun s'appuie sur le précédent) ; 7 et 8 sont les bosses — une décision build vs buy à trancher et un agent à durcir puis casser sous charge. L'escalade va d'« implémente X » à « rends-le production-grade, casse-le, et défends le chiffre ».

Exercice 1 — Construis ton système de veille (et borne-le)

Objectif : transformer la liste passive ci-dessus en un pipeline qui converge au lieu de noyer.

Mets en place : un RSS reader (ou un script Python + feedparser) agrégeant 5 sources max de cette page, un budget hebdo écrit (ex. 3 h), et un fichier notes/weekly.md où chaque item lu produit une phrase : "X remplace Y parce que Z." Au bout de 2 semaines, audite : combien d'items lus → combien de notes produites → combien de POCs lancés.

Indice / Solution

Le ratio qui compte est notes produites / items lus. S'il est < 10 %, tu fais du scroll, pas de la veille — coupe des sources. Bonus staff : un cron quotidien qui te DM (Slack/Telegram) les 3 titres HF papers du jour filtrés par mots-clés (agent, RAG, eval) ; tu apprends à filtrer le flux, pas à le subir. La leçon : un système de veille sans output measurable est du bookmark hoarding déguisé.

Exercice 2 — Reproduis un paper, casse-le, puis défends le chiffre

Objectif : passer de "j'ai lu ReAct" à "j'ai un agent ReAct minimal qui tourne et je connais ses modes d'échec".

Implémente un agent ReAct (#11) à la main, sans framework : boucle manuelle messages.create → parse tool_use → exécute → renvoie tool_result, jusqu'à end_turn. Deux outils (un search, un calculator). Puis casse-le délibérément : une question qui le fait boucler à l'infini, une autre qui le fait halluciner un tool call malformé. Logge usage sur chaque tour.

Indice / Solution

Modes d'échec à reproduire : (1) boucle infinie — pas de garde max_iterations, l'agent rappelle le même outil ; fix = compteur + budget. (2) tool call malformé — parse les inputs avec json.loads, jamais en string-matching ; gère is_error: true dans le tool_result. (3) coût qui explose — sans cap, un agent qui boucle 30× sur un contexte de 50k tokens te coûte une fortune ; affiche le coût cumulé par run (dérivé de usage). La vraie leçon : un agent en prod a toujours un max_iterations, un budget de tokens, et un timeout par appel. Pour le modèle, utilise claude-opus-4-8 avec thinking: {type: "adaptive"}pas budget_tokens (retiré, HTTP 400 sur 4.8).

Exercice 3 — Décide pgvector vs vector DB dédiée, avec des chiffres

Objectif : défendre un choix d'infra retrieval comme un staff, pas par mode.

Charge ~100k chunks dans pgvector (sur ton Postgres NestJS) et dans Qdrant. Mesure pour chacun : latence de recherche p50/p95/p99 sous charge concurrente (utilise k6 ou un script async), recall@10 contre un golden set de 30 requêtes annotées, et l'effort opérationnel (backup, monitoring, un système de plus à opérer). Écris une decision record (1 page) : quel choix, à partir de quel seuil tu migrerais, et le coût de se tromper.

Indice / Solution

Le piège : optimiser le throughput théorique au lieu du coût total de possession. À 100k vecteurs, pgvector tient largement et t'épargne un service distribué — la bonne réponse par défaut avec ton stack. Le seuil de migration n'est pas un nombre de vecteurs en absolu, c'est un SLO de latence violé (p95 > ton budget) ou un besoin de filtering/sharding que pgvector ne tient pas. Un index HNSW mal paramétré (m, ef_construction, ef_search) fausse complètement le bench — documente tes params. Decision record attendue : "pgvector jusqu'à ce que p95 dépasse X ms à Y QPS ; sinon le coût opérationnel d'une DB de plus n'est pas justifié."

Exercice 4 — Construis un harness d'eval et calibre ton juge

Objectif : arrêter de "vibe-checker" et savoir prouver qu'un changement améliore (ou casse) ton app.

Sur l'app de l'exo 2 ou 3 : crée un golden set de 30-50 exemples annotés à la main. Implémente d'abord des metrics déterministes (schema-valid JSON, citation présente, exact match si applicable). Puis ajoute un LLM-as-judge pour une dimension subjective (faithfulness). Calibre le juge : fais-lui scorer tes 50 exemples, compare à tes annotations humaines, mesure l'accord (Cohen's kappa ou simple % d'accord). Câble le tout en CI (PromptFoo ou un script) qui fail si le score régresse.

Indice / Solution

Le piège : faire confiance au juge sans le calibrer. Si l'accord juge/humain est < ~80 %, ton eval est du bruit — resserre le prompt du juge, demande un score avec justification (raisonner réduit la variance), et pin le modèle + effort. Biais à neutraliser : verbosity (le juge préfère les réponses longues — normalise ou interdis la longueur comme critère), position bias (en comparaison A/B, randomise l'ordre), self-enhancement (un juge préfère ses propres outputs — idéalement juge ≠ modèle générateur). La leçon staff : deterministic checks first, LLM-judge only for what code can't measure, and never trust an uncalibrated judge. Coût : un check Python est gratuit et instantané ; un appel juge coûte des tokens et de la latence — n'en mets que là où c'est indispensable.

Exercice 5 — Instrumente pour le coût, puis défends la facture

Objectif : répondre à "pourquoi la facture LLM a triplé ?" avec des données, pas des hypothèses.

Ajoute de l'observability à une de tes apps : un span OpenTelemetry par appel LLM avec attributs model, input_tokens, output_tokens, cache_read_input_tokens, cost_usd, latency_ms. Dashboarde-le (Grafana/Langfuse). Puis active le prompt caching (cache_control sur le préfixe stable system+tools) et prouve la baisse de coût via cache_read_input_tokens qui monte. Simule ensuite un incident : un prompt qui invalide le cache à chaque requête, et retrouve-le dans tes traces.

Indice / Solution

Le coupable habituel d'un cache hit rate à zéro : un invalidateur silencieux dans le préfixe — datetime.now() dans le system prompt, un JSON non trié, un set d'outils qui varie par requête. Le caching est un prefix match : un seul octet qui change en amont invalide tout l'aval. Vérifie : si cache_read_input_tokens reste à 0 sur des requêtes au préfixe identique, diff les bytes rendus de deux requêtes. Autres explosions de coût à savoir diagnostiquer dans les traces : un agent qui boucle (tool calls qui montent sans fin), un max_tokens trop haut qui laisse le modèle bavarder, un switch de modèle qui re-écrit le cache à froid. La leçon : input_tokens seul ment (c'est le reste non caché) — le coût réel = input + cache_creation + cache_read. Affiche la somme, pas le champ unique.

Exercice 6 — Défends un choix de modèle en design review

Objectif : simuler la décision la plus fréquente en interview staff et au quotidien.

Prends un cas réel (un de tes exos) et écris la justification du choix Opus vs Sonnet vs Haiku : pour quelle tâche, à quel volume, avec quel SLO de latence et quel budget mensuel. Chiffre le coût mensuel des trois options avec le snapshot de prix ci-dessus et un volume estimé. Défends pourquoi tu ne downgrades pas (ou pourquoi tu le fais).

Indice / Solution

Cadre staff : choisir le modèle est un tradeoff intelligence × latence × coût, route par route — pas un défaut global. Haiku (1/5) pour classification/extraction high-volume où l'erreur est récupérable et le SLO serré ; Sonnet (3/15) pour le gros du trafic équilibré ; Opus (5/25) quand la justesse prime sur le coût (agentic long-horizon, raisonnement difficile). Le piège : downgrader pour économiser sur une tâche intelligence-sensitive et payer en qualité (et en retries, qui re-coûtent). Chiffre : appels/mois × (tokens_in × prix_in + tokens_out × prix_out) / 1e6. Les leviers de coût à activer avant de sacrifier le modèle, dans l'ordre :

  • Prompt caching — lecture cache ≈ 0.1× le prix input, mais l'écriture coûte 1.25× (TTL 5 min) ou (TTL 1 h). Donc le caching n'est rentable qu'à partir d'un certain nombre de hits : ~2 requêtes pour break-even en TTL 5 min, ~3 en TTL 1 h. Citer juste « 0.1× » sans la prime d'écriture est l'erreur de junior.
  • Batch — exactement −50 % sur input et output, mais asynchrone (jusqu'à 24 h). Pour tout ce qui n'est pas latency-sensitive (eval offline, enrichissement de masse), c'est de l'argent gratuit.
  • effort plus bas — sur Opus 4.8, passer de xhigh à high ou medium réduit les tokens de thinking et d'action. Souvent un meilleur premier levier que de downgrader le modèle.

Une bonne réponse défend un nombre et nomme ces leviers ; une mauvaise dit « j'ai pris le plus puissant par sécurité ».

Exercice 7 — Construis vs achète : tranche une gateway/observability

Objectif : défendre une décision build vs buy sur l'inference plane comme un staff, pas par mode ni par peur du NIH.

Pour ton stack NestJS, écris une decision record d'une page tranchant : (a) SDK Anthropic officiel + un wrapper maison de ~50 lignes (retries typés, timeout par appel, logging usage, prompt caching via cache_control), vs (b) une gateway managée (LiteLLM/Portkey/Helicone). Liste explicitement ce que tu perds avec chaque option : avec (b), un hop réseau + un SPOF + le risque de perdre l'accès aux features natives récentes (caching, structured outputs natifs, thinking adaptatif) tant que le proxy ne les expose pas ; avec (a), tu re-construis le multi-provider et les budget caps cross-équipe le jour où tu en as besoin. Pose le seuil de bascule : à partir de quel signal mesuré tu prends la gateway ?

Indice / Solution

Le piège : prendre la gateway « parce que c'est le standard » (achat par mode), ou refuser tout outil tiers par fierté (build par NIH). La réponse staff est conditionnelle. Un seul provider, une seule équipe → SDK + wrapper maison gagne : tu gardes l'accès immédiat aux features natives (le caching cache_control, messages.parse(), le thinking adaptatif ne sont utiles que si le proxy les a déjà exposés — souvent un retard de plusieurs semaines), et tu n'ajoutes ni latence ni SPOF. La gateway devient justifiée quand un vrai besoin apparaît et mesurable : multi-provider avec fallback (Anthropic + un secours), budget caps imposés cross-équipe, ou un point unique de rate-limit/observability que tu ne veux pas dupliquer dans N services. Le coût caché à nommer en entretien : une gateway te met un cran derrière sur l'API du provider — c'est acceptable pour le multi-provider, pas pour une feature dont tu veux le jour-1. Decision record attendue : « wrapper maison jusqu'à ce qu'on ait ≥ 2 providers à router OU des budget caps cross-équipe ; sinon le hop réseau et le retard de features ne sont pas justifiés. » Note staff : le wrapper maison n'est pas « ne rien faire » — c'est ~50 lignes qui logguent usage, posent un timeout par appel, et exposent les exceptions typées (RateLimitError/OverloadedError/APITimeoutError). Sans ça, tu n'as pas d'observability ni de gateway — tu as juste un appel nu.

Exercice 8 (boss) — Durcis un agent pour la prod, puis casse-le sous charge

Objectif : passer d'un agent qui « marche en démo » à un agent qui survit à la prod — la distance exacte que sonde une interview staff.

Reprends l'agent ReAct de l'exo 2 et rends-le production-grade, puis prouve-le adversarialement. Ajoute, dans cet ordre : (1) AsyncAnthropic + asyncio.gather pour paralléliser les tool calls indépendants ; (2) max_retries SDK + gestion des exceptions typées (RateLimitError, OverloadedError, APITimeoutError, APIStatusError) avec backoff ; (3) un timeout par appel et un budget global (max_iterations + plafond de tokens cumulés) ; (4) cache_control sur le préfixe stable system+tools ; (5) un span d'observability par appel loggant usage. Ensuite, casse-le sous contrainte : simule un 429 en rafale, un 529 (overloaded), un tool qui timeout, et un préfixe qui invalide le cache à chaque tour — et vérifie dans tes traces que chaque mode dégrade proprement (pas de crash, pas de boucle infinie, coût borné).

Indice / Solution

Les pièges, un par garde manquante : (1) paralléliser des tool calls dépendantsasyncio.gather n'est correct que pour des appels indépendants ; si l'outil B a besoin du résultat de A, tu corromps l'état. Identifie le DAG de dépendances avant de gather. (2) retry naïf sur un 400 — les 4xx (sauf 429) ne sont pas retryables ; retry un BadRequestError et tu brûles du quota sur une requête qui échouera toujours. Le SDK retry déjà 429/5xx avec backoff (max_retries=2 par défaut) — ne re-implémente pas par-dessus, configure-le. (3) timeout par chunk ≠ timeout wall-clock — un timeout HTTP par défaut se reset à chaque byte reçu ; un stream qui trickle peut bloquer indéfiniment. Pour une vraie deadline, traque time.monotonic() au niveau de la boucle. (4) le cache invalidé silencieusement — un datetime.now() dans le system prompt, un set d'outils qui varie, un JSON non trié : cache_read_input_tokens reste à 0, le coût explose, et rien ne plante (donc invisible sans le span usage). (5) streaming obligatoire au-delà de ~16K max_tokens — sinon timeout HTTP du SDK ; utilise .stream() + .get_final_message(). La leçon staff, en une ligne : un agent prod a toujours un budget (itérations + tokens), des retries typés sur les bons codes, un timeout wall-clock, du caching vérifié, et un span usage par appel — et tu le prouves en le cassant, pas en le démo-ant. Modèle : claude-opus-4-8 avec thinking: {type: "adaptive"} et output_config.effort — jamais budget_tokens (retiré, 400).


🎤 En entretien

Questions que ce sujet (ressources, outillage, choix d'infra) invite en interview staff — avec la réponse senior en une ligne.

  • "Comment tu restes à jour dans un champ qui bouge aussi vite ?" → Je sépare par demi-vie : j'investis lourd sur les fondamentaux (durables), je réapprends les patterns à chaque génération de modèle, et je ne mémorise jamais les specifics produit — je vais à la source canonique au moment de coder.
  • "pgvector ou une vector DB dédiée pour ce projet ?" → pgvector par défaut si on a déjà Postgres et < ~1-5M vecteurs — operational simplicity beats theoretical throughput ; je migre vers Qdrant/Pinecone seulement quand un SLO de latence mesuré est violé ou qu'on a besoin de filtering/sharding que pgvector ne tient pas.
  • "Comment tu sais que ton app LLM ne s'est pas dégradée après un changement ?" → Golden set annoté à la main + metrics déterministes d'abord, LLM-as-judge (calibré contre l'humain) seulement pour le subjectif, le tout en CI offline pour les régressions plus de l'A/B online pour l'impact réel.
  • "La facture LLM a doublé ce mois-ci — par où tu commences ?" → Mes traces : je logge usage par appel, donc je regarde le cache hit rate (cache_read_input_tokens à zéro = invalidateur silencieux dans le préfixe) et les agents qui bouclent ; je dérive le coût de input + cache_creation + cache_read, jamais d'input_tokens seul.
  • "Quel modèle pour cette feature, et pourquoi pas le moins cher ?" → C'est un tradeoff intelligence × latence × coût route par route ; je ne downgrade pas une tâche intelligence-sensitive pour économiser, parce que la perte de qualité revient en retries et en incidents — le downgrade est la décision du produit, pas un réflexe d'ingénieur.
  • "Tu prends une gateway LLM (LiteLLM/Portkey) ou tu wrappes le SDK toi-même ?" → SDK officiel + wrapper maison de ~50 lignes par défaut pour un seul provider — j'ai l'accès jour-1 aux features natives (caching, structured outputs, thinking adaptatif) et zéro hop réseau ; je passe à la gateway quand un besoin mesuré apparaît : multi-provider avec fallback ou budget caps cross-équipe. Le coût caché d'une gateway, c'est d'être un cran derrière l'API du provider.
  • "Comment tu rends un agent fiable en prod ?" → Toujours un budget borné (max_iterations + plafond de tokens) pour tuer les boucles, des retries typés sur les bons codes (429/5xx oui, 4xx non), un timeout wall-clock (pas par-chunk), AsyncAnthropic + asyncio.gather pour les tool calls indépendants seulement, et un span usage par appel — et je le valide en le cassant sous charge (429 en rafale, tool timeout, cache invalidé), pas en démo.
  • "Prompt caching : explique-moi l'économie réelle, pas juste le 0.1×." → La lecture cache vaut ≈0.1× l'input, mais l'écriture coûte 1.25× (TTL 5 min) ou 2× (1 h) — donc le break-even est à ~2-3 requêtes ; en-dessous, le caching coûte plus cher. Et c'est un prefix match : un seul octet volatil en amont (timestamp, JSON non trié, set d'outils variable) met cache_read_input_tokens à 0 sans erreur — invisible sans logger usage.

Mise à jour : 2026-06-16

Bibliothèque tech perso — Achref