Construire un Agent IA avec Claude API & Agent SDK — Guide Complet Pour Développeurs 2026

Les agents IA ne sont plus réservés aux équipes de 50 ingénieurs. Avec Claude API et l'Anthropic SDK, un développeur solo peut builder un produit shippable en moins d'une semaine. Voici exactement comment — avec le code complet.

Pourquoi Claude API pour votre premier agent IA ?

En 2026, le paysage des agent frameworks s'est considérablement densifié : Vercel AI SDK, LangChain, LlamaIndex, AutoGen… Mais au cœur de chacun de ces outils se trouve toujours la même mécanique — un LLM qui prend des décisions, exécute des fonctions, et boucle jusqu'à résolution.

Comprendre ce mécanisme à travers Claude API directement vous donne un avantage décisif. Vous n'êtes plus dépendant d'une abstraction opaque. Vous pouvez débugger, optimiser les coûts, et adapter le comportement avec une précision chirurgicale.

Claude se distingue dans ce contexte pour trois raisons concrètes :

  • Tool use natif et robuste : Claude a été entraîné spécifiquement pour le function calling. Le taux de précision sur les appels tools est mesurablement supérieur à la concurrence sur les tâches complexes multi-steps.
  • Fenêtre contextuelle de 200k tokens : indispensable pour les agents qui accumulent un historique long (conversations, résultats tools, documents).
  • Pricing favorable : Claude 3.5 Sonnet à $3/MTok input vs $5/MTok pour GPT-4o. Sur des volumes agents (beaucoup d'input, historique long), la différence est significative.

Prérequis pour suivre ce guide : Python 3.9+, notion de base async/await, API REST. Tout le code est fonctionnel et testé.

Architecture complète d'un agent IA Claude API — boucle LLM, tool use, et boucle de feedback

Architecture d'un agent IA avec Claude API : du message utilisateur à la réponse finale via la boucle tool use

Qu'est-ce qu'un Agent IA ? (Rappel Technique)

Avant d'écrire une ligne de code, clarifions ce qui distingue un agent IA d'un simple chatbot. La confusion est fréquente, et elle entraîne souvent des choix architecturaux coûteux à corriger plus tard.

Chatbot vs Agent : la différence fondamentale

Un chatbot répond. Un agent agit.

Si vous demandez à un chatbot "réserve un rendez-vous avec mon médecin jeudi matin", il vous répondra : "Voici comment vous pouvez réserver un rendez-vous avec votre médecin…" et vous donnera des instructions.

Un agent, lui, va :

  1. Analyser la demande et identifier l'intention
  2. Appeler un outil pour vérifier les disponibilités du médecin
  3. Sélectionner le créneau optimal selon votre préférence
  4. Appeler un second outil pour créer le rendez-vous
  5. Vous confirmer : "C'est fait. Rendez-vous avec Dr Martin jeudi 9h."

La différence : l'agent prend des décisions autonomes et exécute des actions concrètes dans des systèmes réels.

L'architecture en 5 couches

Tout agent IA, quelle que soit la technologie sous-jacente, fonctionne selon cette architecture :

Boucle Complète d'un Agent IA — du Input au Output
👤 User
Input
Texte / Voice / Image
🧠 LLM
Reasoning
(Claude)
Analyse + Décision
◆ Tool
Needed?
stop_reason check
⚙️ Tool
Execution
API / DB / Fonction
✅ Final
Output
Réponse utilisateur
↺ Feedback loop : résultat tool → LLM → nouvelle décision (jusqu'à end_turn)
LLM Reasoning (Claude)
Décision / Boucle
Tool Execution
I/O utilisateur

Cette architecture s'applique que vous construisiez un agent de prise de rendez-vous, de qualification de leads, de support client ou de veille concurrentielle. La boucle est toujours la même. Seuls les tools changent.

Claude API — Les Fondations

Avant d'aborder le tool use, maîtrisez les bases de l'API. Ces fondations sont identiques que vous fassiez un simple chatbot ou un agent complexe.

Installation et authentification

pip install anthropic
export ANTHROPIC_API_KEY="sk-ant-api03-..."

Obtenez votre clé API sur console.anthropic.com. Ne la commitez jamais en clair — utilisez un fichier .env avec python-dotenv ou les variables d'environnement de votre plateforme de déploiement.

Premier appel : Messages API

from anthropic import Anthropic

client = Anthropic()

response = client.messages.create(
    model="claude-opus-4-6",  # Le modèle le plus capable
    max_tokens=1024,
    messages=[{"role": "user", "content": "Explique-moi les agents IA en 3 phrases"}]
)

print(response.content[0].text)

Trois paramètres critiques à comprendre dès le début :

  • max_tokens : limite directement votre coût. Ne mettez pas 8192 par défaut — calibrez selon votre cas d'usage.
  • temperature : 0 pour les agents (comportement déterministe, tool calling précis), 0.7-1 pour la génération créative.
  • system : le paramètre le plus puissant pour les agents. C'est ici que vous définissez la personnalité, les règles et les contraintes de votre agent.

Conversation stateful (historique)

Les agents ont besoin de mémoire à court terme. Voici le pattern de base :

from anthropic import Anthropic

client = Anthropic()
conversation_history = []

def chat(user_message: str) -> str:
    conversation_history.append({
        "role": "user",
        "content": user_message
    })

    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=1024,
        system="Tu es un assistant expert en qualification de leads BtoB pour le marché français.",
        messages=conversation_history
    )

    assistant_message = response.content[0].text
    conversation_history.append({
        "role": "assistant",
        "content": assistant_message
    })

    return assistant_message

# Le contexte est conservé entre les tours
print(chat("Bonjour, je cherche un CRM pour ma PME de 15 personnes"))
print(chat("Mon budget est autour de 200€/mois"))  # Claude se souvient du contexte précédent
print(chat("On utilise déjà Outlook et Teams"))

Streaming (essentiel pour l'UX)

Pour les interfaces utilisateur, le streaming évite le "temps de chargement" en affichant la réponse token par token. Critique pour les agents dont les réponses peuvent être longues.

with client.messages.stream(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Analyse ce contrat et liste les clauses problématiques"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)  # Affichage progressif

Tool Use — Le Cœur des Agents

Le tool use (function calling) est ce qui transforme Claude d'un chatbot en agent. Comprendre précisément son fonctionnement est non-négociable pour builder des agents fiables.

Le mécanisme exact

Voici ce qui se passe réellement quand Claude utilise un tool :

  1. Vous envoyez un message utilisateur avec une liste de tools disponibles (JSON Schema)
  2. Claude analyse et décide : "Pour répondre, j'ai besoin d'appeler get_availability(doctor='Dr Martin', date='2026-04-15')"
  3. Claude retourne sa réponse avec stop_reason == "tool_use" et les paramètres de l'appel
  4. C'est vous qui exécutez la fonction — Claude ne peut pas accéder à vos systèmes directement
  5. Vous renvoyez le résultat à Claude
  6. Claude continue son raisonnement avec ce nouveau contexte

Cette architecture par délégation est intentionnelle : vous gardez le contrôle total sur ce qui est exécuté dans vos systèmes.

Définir des tools (JSON Schema)

Chaque tool est défini avec un nom, une description précise (Claude s'en sert pour décider quand l'utiliser), et un schéma d'input :

tools = [
    {
        "name": "get_availability",
        "description": "Récupère les créneaux disponibles pour un médecin à une date donnée. "
                       "Utiliser quand l'utilisateur demande à voir les disponibilités ou avant toute prise de RDV.",
        "input_schema": {
            "type": "object",
            "properties": {
                "doctor_name": {
                    "type": "string",
                    "description": "Nom complet du médecin (ex: 'Dr Martin', 'Dr Dupont')"
                },
                "date": {
                    "type": "string",
                    "description": "Date au format YYYY-MM-DD"
                },
                "time_preference": {
                    "type": "string",
                    "enum": ["matin", "midi", "apres-midi", "soir"],
                    "description": "Préférence horaire du patient"
                }
            },
            "required": ["doctor_name", "date"]
        }
    },
    {
        "name": "book_appointment",
        "description": "Crée et confirme un rendez-vous médical. "
                       "Utiliser UNIQUEMENT après avoir confirmé la disponibilité avec get_availability.",
        "input_schema": {
            "type": "object",
            "properties": {
                "doctor_name": {"type": "string"},
                "patient_name": {"type": "string"},
                "datetime": {
                    "type": "string",
                    "description": "Date et heure exactes au format ISO 8601 (ex: '2026-04-15T09:00:00')"
                },
                "reason": {
                    "type": "string",
                    "description": "Motif de la consultation"
                }
            },
            "required": ["doctor_name", "patient_name", "datetime"]
        }
    }
]

Conseil critique : La qualité de vos descriptions de tools détermine directement la qualité de votre agent. Claude utilise ces descriptions pour décider quand et comment appeler chaque tool. Soyez précis et incluez les contraintes d'utilisation.

Implémentation des fonctions (backend)

def get_availability(doctor_name: str, date: str, time_preference: str = None) -> list:
    """Récupère les disponibilités — à remplacer par votre API réelle"""
    # Mock pour l'exemple
    slots = {
        ("Dr Martin", "2026-04-15"): ["09:00", "10:30", "14:00", "15:30"],
        ("Dr Dupont", "2026-04-15"): ["08:30", "11:00", "16:00"],
    }
    available = slots.get((doctor_name, date), [])

    if time_preference == "matin":
        return [s for s in available if s < "12:00"]
    elif time_preference == "apres-midi":
        return [s for s in available if s >= "14:00"]
    return available

def book_appointment(doctor_name: str, patient_name: str, datetime: str, reason: str = None) -> dict:
    """Crée le rendez-vous dans votre système"""
    # Appel API réel ici
    return {
        "success": True,
        "appointment_id": f"APT-{datetime.replace(':', '').replace('-', '')[:12]}",
        "confirmation": f"RDV confirmé : {patient_name} avec {doctor_name} le {datetime}"
    }

# Mapping nom tool → implémentation
TOOL_FUNCTIONS = {
    "get_availability": get_availability,
    "book_appointment": book_appointment,
}

La boucle agent complète

Voici l'implémentation complète d'une boucle agent avec gestion des tools :

from anthropic import Anthropic
import json

client = Anthropic()

def run_agent(user_input: str, max_iterations: int = 10) -> str:
    """
    Boucle agent principale : pense → agit → pense → sort.

    Args:
        user_input: Message de l'utilisateur
        max_iterations: Limite de sécurité contre les boucles infinies

    Returns:
        Réponse finale de l'agent
    """
    messages = [{"role": "user", "content": user_input}]

    for iteration in range(max_iterations):
        # Étape 1 : Claude réfléchit
        response = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=2048,
            system="""Tu es un assistant de prise de rendez-vous médicaux.
            Tu dois TOUJOURS vérifier les disponibilités avant de prendre un RDV.
            Parle en français, sois cordial et précis.""",
            tools=tools,
            messages=messages
        )

        # Étape 2 : Vérifier si Claude veut appeler un tool
        if response.stop_reason == "tool_use":
            # Extraire tous les appels tools de cette réponse
            tool_calls = [block for block in response.content if block.type == "tool_use"]

            # Exécuter chaque tool et collecter les résultats
            tool_results = []
            for tool_call in tool_calls:
                print(f"  → Tool appelé : {tool_call.name}({json.dumps(tool_call.input, ensure_ascii=False)})")

                try:
                    result = TOOL_FUNCTIONS[tool_call.name](**tool_call.input)
                    result_content = json.dumps(result, ensure_ascii=False)
                except Exception as e:
                    result_content = json.dumps({"error": str(e)})

                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": tool_call.id,  # Crucial : lier le résultat à l'appel
                    "content": result_content
                })

            # Ajouter réponse Claude + résultats tools à l'historique
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})

        else:
            # stop_reason == "end_turn" : l'agent a terminé
            final_response = next(
                (block.text for block in response.content if hasattr(block, 'text')),
                "Aucune réponse générée."
            )
            return final_response

    return "Limite d'itérations atteinte. Veuillez reformuler votre demande."

# Test
result = run_agent("Réserve un rdv avec Dr Martin jeudi matin. Je m'appelle Jean Dupont.")
print(result)

Chatbot Simple vs Agent avec Tools : Comparaison Code

La différence architecturale entre les deux approches est plus simple qu'elle n'y paraît. Voici une comparaison côte-à-côte :

🤖 CHATBOT SIMPLE (sans tools)
from anthropic import Anthropic

client = Anthropic()

def chatbot(user_msg):
    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=512,
        messages=[
            {"role": "user", "content": user_msg}
        ]
    )
    # Retourne toujours du texte
    return response.content[0].text

# Le chatbot GUIDE mais n'agit pas
result = chatbot(
    "Réserve un rdv avec Dr Martin"
)
# Output: "Voici comment réserver un rdv...
# 1. Appelez le cabinet
# 2. Ou utilisez Doctolib..."
⚡ AGENT AVEC TOOLS (actif)
from anthropic import Anthropic

client = Anthropic()

def agent(user_msg):
    messages = [
        {"role": "user", "content": user_msg}
    ]
    # Boucle : continue jusqu'à end_turn
    while True:
        response = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=2048,
            tools=tools,  # ← DIFFÉRENCE CLÉ
            messages=messages
        )
        # ← DIFFÉRENCE CLÉ : vérification stop_reason
        if response.stop_reason == "tool_use":
            results = execute_tools(response)
            messages.append(
                {"role": "assistant", "content": response.content}
            )
            messages.append(
                {"role": "user", "content": results}
            )
        else:
            return response.content[0].text

# L'agent AGIT et confirme
result = agent("Réserve un rdv avec Dr Martin")
# Output: "RDV confirmé : Dr Martin jeudi 9h ✓"

La différence structurelle est minime : une boucle while, la vérification de stop_reason, et l'exécution des tools. Mais l'impact fonctionnel est radical — d'un guide textuel à une action concrète dans vos systèmes.

Cas d'Usage Complet — Agent de Qualification de Leads BtoB

Passons à un exemple production-ready. Ce cas est particulièrement courant en France : une PME BtoB qui reçoit 15-30 leads/jour via son site et veut les qualifier automatiquement avant que les commerciaux interviennent.

Ce que fait l'agent

  • Récupère les informations du lead dans la base de données
  • Pose 3-4 questions BANT de manière naturelle et conversationnelle
  • Score le lead : CHAUD (3/4 critères BANT) / TIÈDE / FROID
  • Envoie un email de remerciement adapté au score
  • Met à jour le CRM avec les informations collectées

Les tools de l'agent

qualification_tools = [
    {
        "name": "get_lead_info",
        "description": "Récupère les informations existantes d'un lead depuis la base de données CRM.",
        "input_schema": {
            "type": "object",
            "properties": {
                "lead_id": {"type": "string", "description": "Identifiant unique du lead"}
            },
            "required": ["lead_id"]
        }
    },
    {
        "name": "score_lead",
        "description": "Enregistre le score BANT final du lead après qualification complète.",
        "input_schema": {
            "type": "object",
            "properties": {
                "lead_id": {"type": "string"},
                "score": {
                    "type": "string",
                    "enum": ["CHAUD", "TIÈDE", "FROID"],
                    "description": "CHAUD si 3/4 critères BANT confirmés, TIÈDE si 2/4, FROID sinon"
                },
                "bant_notes": {
                    "type": "object",
                    "description": "Résumé des 4 critères BANT collectés"
                }
            },
            "required": ["lead_id", "score"]
        }
    },
    {
        "name": "send_followup_email",
        "description": "Envoie un email de suivi au lead après la qualification.",
        "input_schema": {
            "type": "object",
            "properties": {
                "lead_email": {"type": "string"},
                "lead_name": {"type": "string"},
                "score": {"type": "string", "enum": ["CHAUD", "TIÈDE", "FROID"]},
                "next_step": {"type": "string", "description": "Prochaine étape recommandée"}
            },
            "required": ["lead_email", "lead_name", "score", "next_step"]
        }
    },
    {
        "name": "update_crm",
        "description": "Met à jour le CRM (HubSpot/Salesforce) avec toutes les informations de qualification.",
        "input_schema": {
            "type": "object",
            "properties": {
                "lead_id": {"type": "string"},
                "updates": {
                    "type": "object",
                    "description": "Champs à mettre à jour dans le CRM"
                }
            },
            "required": ["lead_id", "updates"]
        }
    }
]

Le system prompt — l'intelligence de l'agent

QUALIFICATION_SYSTEM_PROMPT = """Tu es un agent expert en qualification de leads BtoB SaaS pour le marché français.

MISSION :
1. Accueille chaleureusement le lead par son prénom
2. Pose les questions BANT de façon naturelle (pas comme une checklist)
3. Score le lead selon les critères ci-dessous
4. Envoie un email de remerciement adapté et mets à jour le CRM

CRITÈRES BANT :
- Budget : Budget annuel confirmé > 5 000€ ? (oui = ✓)
- Autorité : La personne peut-elle décider ou influencer l'achat ? (oui = ✓)
- Besoin : Problème métier clair et douloureux identifié ? (oui = ✓)
- Timeline : Projet dans les 3 prochains mois ? (oui = ✓)

SCORING :
- CHAUD : 3 ou 4 critères BANT confirmés → proposer démo immédiate
- TIÈDE : 2 critères → proposer ressources + recontact dans 30 jours
- FROID : 0 ou 1 critère → remercier + newsletter

RÈGLES :
- Toujours en français naturel, pas de jargon corporate
- Maximum 4 questions (ne pas interroger, avoir une conversation)
- Si budget flou → demander indirectement ("Vous avez un ordre de grandeur ?")
- Être empathique si le lead n'est pas qualifié
- Ne jamais mentionner les critères BANT explicitement"""

Le script complet de qualification

def run_lead_qualification(lead_id: str) -> dict:
    """
    Qualifie un lead de bout en bout.
    Retourne le résultat de qualification avec le score et les notes BANT.
    """
    # Simuler la récupération du lead (remplacer par appel DB réel)
    lead = {
        "id": lead_id,
        "name": "Sophie Martin",
        "email": "sophie.martin@acme.fr",
        "company": "ACME Solutions",
        "title": "Directrice Commerciale",
        "industry": "SaaS BtoB",
        "budget_mention": "environ 10k€/an",
        "source": "landing page"
    }

    initial_message = f"""
    Nouveau lead entrant :
    Prénom : {lead['name'].split()[0]}
    Poste : {lead['title']}
    Entreprise : {lead['company']} ({lead['industry']})
    Budget mentionné dans le formulaire : {lead.get('budget_mention', 'Non renseigné')}

    Lance la qualification en saluant Sophie et en posant ta première question BANT.
    """

    messages = [{"role": "user", "content": initial_message}]
    qualification_result = {}

    while True:
        response = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=2048,
            system=QUALIFICATION_SYSTEM_PROMPT,
            tools=qualification_tools,
            messages=messages
        )

        if response.stop_reason == "tool_use":
            tool_results = []
            for block in response.content:
                if block.type == "tool_use":
                    # Exécuter le tool
                    result = execute_qualification_tool(block.name, block.input, lead)

                    # Capturer le score si c'est score_lead
                    if block.name == "score_lead":
                        qualification_result = block.input

                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": json.dumps(result, ensure_ascii=False)
                    })

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

        else:
            # Qualification terminée
            print(f"✅ Qualification terminée : {qualification_result.get('score', 'N/A')}")
            return qualification_result

# Lancer la qualification
result = run_lead_qualification("LEAD-001")
print(f"Score : {result['score']}")

Erreurs Courantes et Comment les Éviter

Ces quatre erreurs coûtent des heures de debugging aux équipes qui débutent avec les agents IA. Les connaître à l'avance vous évite ces pièges.

1. Boucles infinies

L'agent appelle des tools en boucle sans convergence. Causes classiques : tools mal décrits, logique circulaire dans le prompt système, ou cas edge non géré.

Solution : Toujours implémenter max_iterations et logger chaque appel tool pour détecter les patterns répétitifs.

2. Explosion du contexte

Sur des sessions longues (20+ tours), l'historique peut dépasser 200k tokens. Coût exponentiel et dégradation de la qualité des réponses.

def truncate_messages(messages: list, max_tokens: int = 150000) -> list:
    """Sliding window sur l'historique — conserve toujours le premier message."""
    # Estimation grossière : 1 token ≈ 4 caractères
    total_chars = sum(len(str(m)) for m in messages)

    while total_chars > max_tokens * 4 and len(messages) > 2:
        # Supprimer le 2ème message (garder le 1er = contexte initial)
        removed = messages.pop(1)
        total_chars -= len(str(removed))

    return messages

3. Hallucinations de tools

Claude peut parfois tenter d'appeler un tool qui n'existe pas dans votre liste. Toujours valider le nom du tool avant l'exécution :

def safe_execute_tool(tool_name: str, tool_input: dict) -> dict:
    if tool_name not in TOOL_FUNCTIONS:
        return {"error": f"Tool '{tool_name}' inexistant. Tools disponibles : {list(TOOL_FUNCTIONS.keys())}"}

    try:
        return TOOL_FUNCTIONS[tool_name](**tool_input)
    except TypeError as e:
        return {"error": f"Paramètres invalides pour {tool_name}: {e}"}
    except Exception as e:
        return {"error": f"Erreur d'exécution: {e}"}

4. Coûts non anticipés

Un agent qui fait 30 itérations pour une requête simple peut coûter 50x le prix attendu. Monitorez le nombre d'itérations en production.

import time

def run_agent_with_monitoring(user_input: str) -> dict:
    start_time = time.time()
    iteration_count = 0
    total_input_tokens = 0
    total_output_tokens = 0

    messages = [{"role": "user", "content": user_input}]

    while iteration_count < 10:
        response = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=2048,
            tools=tools,
            messages=messages
        )

        iteration_count += 1
        total_input_tokens += response.usage.input_tokens
        total_output_tokens += response.usage.output_tokens

        if response.stop_reason != "tool_use":
            break

        # ... gestion tools ...

    cost_usd = (total_input_tokens / 1_000_000 * 15) + (total_output_tokens / 1_000_000 * 75)

    return {
        "response": response.content[0].text,
        "iterations": iteration_count,
        "total_tokens": total_input_tokens + total_output_tokens,
        "cost_usd": round(cost_usd, 4),
        "duration_s": round(time.time() - start_time, 2)
    }

Déploiement Serverless en Production

Deux options dominent pour les agents Claude en 2026 : Vercel pour les équipes JavaScript/TypeScript, et AWS Lambda pour Python. Les deux fonctionnent avec l'Anthropic SDK.

Vercel (Node.js/TypeScript)

// /api/agent.ts
import Anthropic from "@anthropic-ai/sdk";
import { NextRequest, NextResponse } from "next/server";

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

export async function POST(req: NextRequest) {
  const { message, history = [] } = await req.json();

  const messages = [...history, { role: "user", content: message }];

  const response = await client.messages.create({
    model: "claude-opus-4-6",
    max_tokens: 2048,
    system: "Tu es un agent commercial expert pour le marché français.",
    messages,
  });

  return NextResponse.json({
    response: response.content[0].text,
    usage: response.usage,
  });
}

// Déploiement : vercel deploy
// Variables d'env : ANTHROPIC_API_KEY dans Vercel Dashboard

AWS Lambda (Python)

# handler.py
import json
import os
from anthropic import Anthropic

client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def lambda_handler(event, context):
    body = json.loads(event.get("body", "{}"))
    user_message = body.get("message", "")

    if not user_message:
        return {"statusCode": 400, "body": json.dumps({"error": "message requis"})}

    try:
        response = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=1024,
            messages=[{"role": "user", "content": user_message}]
        )

        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({
                "response": response.content[0].text,
                "input_tokens": response.usage.input_tokens,
                "output_tokens": response.usage.output_tokens
            })
        }
    except Exception as e:
        return {"statusCode": 500, "body": json.dumps({"error": str(e)})}
# serverless.yml
service: claude-agent-api
provider:
  name: aws
  runtime: python3.11
  region: eu-west-3  # Paris
  environment:
    ANTHROPIC_API_KEY: ${env:ANTHROPIC_API_KEY}
functions:
  agent:
    handler: handler.lambda_handler
    events:
      - http:
          path: /agent
          method: post
# Deploy : serverless deploy

Checklist avant de shipper en production

  • ANTHROPIC_API_KEY en variable d'environnement (jamais en dur dans le code)
  • max_iterations configuré (recommandé : 10-15)
  • ✅ Timeout HTTP configuré (recommandé : 30-60s pour les agents)
  • ✅ Logging des coûts par requête en production
  • ✅ Rate limiting côté API (éviter les abus)
  • ✅ Validation des inputs utilisateur avant envoi au LLM
  • ✅ Gestion des erreurs API Anthropic (rate limit, timeout)

Calculateur de Coûts Agent IA — Budget Mensuel

Estimez votre budget mensuel Claude API selon votre volume et votre modèle.

Calculateur Coûts Agent IA
Estimez votre budget mensuel Claude API
500 messages/jour
600 tokens/message
Coût / mois estimé
USD (hors TVA)
Tokens / mois
MTok total
Coût / 1000 messages
USD
Formule : messages/jour × tokens × 30 jours × (prix_input × 0.6 + prix_output × 0.4) / 1 000 000