Tu as lu une douzaine d'articles « les agents IA sont là ! » ce mois-ci. Anthropic a lancé Managed Agents le 8 avril. Google a sorti ADK. OpenAI a poussé son Agents SDK. Chaque pitch deck prononce « agents autonomes » comme une formule magique. Mais tu n'as jamais construit la vraie boucle qui les alimente tous — les 50 lignes de Python où un modèle appelle une fonction, lit le résultat, et décide quoi faire ensuite. Sans ça, toutes les démos vendeurs se valent, et tu ne peux pas distinguer une vraie fonctionnalité d'un emballage cadeau hors de prix.

Pourquoi « utiliser une plateforme » ne suffit pas

Le réflexe évident : choisir une plateforme managée et lui confier la cuisine. Sauf que le vrai problème, c'est que tu sous-traites ta compréhension. Anthropic Managed Agents facture $0.08 par heure de session. Le SDK Agents d'OpenAI a ses propres abstractions. Google ADK utilise des workflows en graphe. Chaque plateforme emballe le même schéma de base dans des opinions différentes sur la mémoire, les permissions et la facturation — mais si tu ne connais pas le schéma lui-même, tu ne peux pas évaluer quelles opinions comptent pour TON cas d'usage. Une analyse 2024 du MIT Sloan Management Review des projets IA en entreprise estime le taux de passage pilote-à-production pour l'IA agentique à environ 5 %. Le problème, ce n'est pas le framework. Ce sont les équipes qui ne comprennent pas ce qu'il y a en dessous.

Alors construisons la chose.

La recette : 50 lignes pour une vision à rayons X

Étape 0 : Installer le SDK

Au 27 avril 2026, la dernière version du SDK Python d'Anthropic — une boîte à outils qui permet à ton code Python de communiquer avec le cerveau de Claude — est la v0.97.0. Une seule commande :

pip install anthropic

Configure ta clé API — un mot de passe secret qui identifie ton compte auprès des serveurs d'Anthropic :

export ANTHROPIC_API_KEY="sk-ant-..."

Étape 1 : Définir tes outils

Les outils sont des fonctions que Claude peut te demander d'exécuter. Tu les décris en JSON Schema — un format standardisé pour dire « cette fonction prend ces entrées avec ces formes ». Claude lit ces descriptions comme un menu de restaurant et choisit ce qu'il commande.

Point crucial : les descriptions comptent plus que les noms. Claude décide quand appeler un outil en fonction de ce que dit la description. Description vague = comportement imprévisible.

/faion est le skill parapluie de faion-network — il injecte la méthodologie pertinente issue de 12 domaines spécialisés (dev, produit, marketing, ops, ...) dans la conversation, ancré dans ta session actuelle.

/faion
What's the right way to design parameter schemas for an MCP tool that an
LLM will call autonomously? Focus on description quality, required fields,
and enum constraints.

Voici une vraie définition d'outil — un lookup météo et un créateur d'événements :

tools = [
    {
        "name": "get_weather",
        "description": "Get current weather for a city. Use when the user asks about weather, temperature, or outdoor conditions.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name, e.g. 'New York'"},
                "units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["city"]
        }
    },
    {
        "name": "create_event",
        "description": "Create a calendar event. Use when the user wants to schedule, book, or plan something.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"}
            },
            "required": ["title", "start", "end"]
        }
    }
]

Note bien : required contrôle le comportement. Oublie un champ requis et regarde Claude halluciner des valeurs. Surcharge les champs requis et des appels valides seront bloqués.

Étape 2 : Construire la couche d'exécution

C'est ici que TON code tourne. Claude n'exécute jamais rien lui-même — il envoie une requête polie du genre « lance get_weather avec {city: 'Chicago'} s'il te plaît », et ton code fait le vrai boulot :

def run_tool(name, input_data):
    if name == "get_weather":
        # En production, tu appellerais une API météo ici
        return {"temp": 72, "condition": "sunny", "city": input_data["city"]}
    if name == "create_event":
        return {"event_id": "evt_456", "status": "created", "title": input_data["title"]}
    return {"error": f"Unknown tool: {name}"}

Étape 3 : La boucle — là où naît l'autonomie

C'est la partie que chaque plateforme noie dans des milliers de lignes d'abstraction. La boucle agentique — le cycle où Claude appelle des outils, lit les résultats et décide son prochain coup — fait environ 20 lignes :

import json
import anthropic

client = anthropic.Anthropic()
messages = [{"role": "user", "content": "What's the weather in Chicago? If it's nice, schedule a picnic tomorrow at noon."}]

response = client.messages.create(
    model="claude-sonnet-4-20250514", max_tokens=1024,
    tools=tools, messages=messages
)

while response.stop_reason == "tool_use":
    # Claude peut demander PLUSIEURS outils à la fois — traite-les TOUS
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            result = run_tool(block.name, block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": json.dumps(result)
            })

    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})

    response = client.messages.create(
        model="claude-sonnet-4-20250514", max_tokens=1024,
        tools=tools, messages=messages
    )

print(response.content[0].text)

Ce prompt déclenche DEUX appels d'outils autonomes : d'abord get_weather (pour vérifier Chicago), puis create_event (pour planifier le pique-nique) — et Claude les enchaîne sans que tu lui dises. C'est le moment « eurêka » : le modèle lit le résultat météo, décide qu'il fait beau, et appelle l'outil suivant tout seul.

Chaque plateforme d'agents, c'est cette boucle plus des opinions sur la mémoire, les permissions, la facturation et le déploiement empilées par-dessus.

Étape 4 : Gestion d'erreurs — ne plante pas, enseigne

Quand un outil échoue, ne fais pas planter ta boucle. Renvoie l'erreur avec is_error: True pour que Claude s'adapte — réessayer avec d'autres paramètres, expliquer le problème, ou tenter une autre approche :

/faion
What error handling patterns work best in agentic tool-use loops —
specifically for recoverable errors vs fatal ones? When should the
agent retry vs bail out?
def run_tool_safe(name, input_data):
    try:
        return run_tool(name, input_data), False
    except Exception as e:
        return {"error": str(e)}, True

# Dans la boucle, remplace la construction de tool_results :
result, is_err = run_tool_safe(block.name, block.input)
tool_results.append({
    "type": "tool_result",
    "tool_use_id": block.id,
    "content": json.dumps(result),
    "is_error": is_err
})

Claude lit l'erreur et répond intelligemment : « J'ai essayé de planifier le pique-nique mais le calendrier n'autorise que les événements pendant les heures ouvrées. Tu veux que j'essaie samedi matin à la place ? »

Étape 5 : Ajouter un fusible de sécurité

Une boucle emballée brûle des tokens — de petits morceaux de mots que Claude traite, environ ¾ d'un mot français chacun — jusqu'à ce que tu la tues. Ajoute un compteur :

MAX_ITERATIONS = 10
iteration = 0

while response.stop_reason == "tool_use" and iteration < MAX_ITERATIONS:
    iteration += 1
    # ... même corps de boucle ...

if iteration >= MAX_ITERATIONS:
    print("Loop hit safety limit. Something's probably wrong.")

Aucune plateforme managée ne te dira que c'est la première chose à ajouter. Elles le gèrent en silence — et te facturent le privilège.

Les pièges qui mordent en production

1. Le bug du « premier outil seulement ». Claude peut renvoyer plusieurs blocs tool_use dans une seule réponse — vérifier la météo de trois villes simultanément, par exemple. Si tu ne traites que le premier bloc (classique dans les tutos), le modèle se perd à cause des résultats manquants. Symptôme : Claude répète la même requête en boucle. Solution : itère sur TOUS les blocs, renvoie TOUS les résultats dans un seul message. Le tutoriel officiel appelle ça la progression Ring 2 → Ring 3.

2. Explosion de la fenêtre de contexte. La fenêtre de contexte — la quantité de texte que Claude peut « voir » d'un coup, comme sa mémoire de travail — se remplit vite. Chaque appel d'outil et résultat s'accumule. Une sortie de commande verbeuse peut bouffer des milliers de tokens en un seul tour. Le Agent SDK gère la compaction automatiquement ; le SDK brut, non. Solution : résume les grosses sorties avant de les renvoyer, ou tronque aux parties pertinentes.

3. Pas de sandboxing. Ta fonction run_tool tourne avec TES permissions. Si Claude demande de supprimer un fichier et que ton outil obéit, le fichier disparaît. Selon l'analyse de Momentic, leur équipe l'a appris à ses dépens au fil de 3 mois d'exécutions d'agents autonomes : « le sandboxing n'est pas optionnel... les choses dérapent bien plus vite qu'on ne le pense. »

4. Champs required manquants. Si ton schéma dit required: ["city"] mais que l'utilisateur demande « quel temps fait-il ? », Claude va halluciner une ville au lieu de poser la question. Solution : rends la description explicite — « Si l'utilisateur ne précise pas de ville, demande-lui au lieu de deviner. »

Ce que tu peux faire maintenant

Tu as une boucle agentique qui tourne. Chaque annonce vendeur à partir de maintenant s'y superpose directement. Managed Agents ? C'est ta boucle plus du checkpointing, du monitoring et de la reprise sur crash — pour $0.08/heure de session. Le SDK Agents d'OpenAI vs Google ADK ? Même boucle, opinions différentes sur le handoff et les graphes.

Le prochain pitch plateforme arrive sur ton bureau. Au lieu de gober la démo, tu demandes : quelle couche de MA boucle ça remplace — et est-ce que cette couche est vraiment mon goulot d'étranglement ?