All guides
IntermediateSelf-pacedFree GuideSection 73/95

Agents — Tool use et function calling

Practise development foundations: programming, web, APIs, data and AI tools. Work through sections and exercises to build your first projects.

The full lessons for this course are currently available in French. Use the section menu to navigate the French course.

💡

Free content, available without an account. Tools and models change: use the current model guide to check their versions. Models and sources

Section 11.4.14 : Agents — Tool use et function calling

🎯 Objectif pédagogique

Maîtriser le function calling (tool use) d'OpenAI pour créer des agents qui appellent des fonctions Python réelles. Vous serez capable de connecter un LLM à des APIs, bases de données, et services externes.


Function Calling — Le LLM qui appelle vos fonctions

Jusqu'ici, nos outils étaient des mocks. Le function calling d'OpenAI permet au modèle de demander explicitement l'exécution de fonctions Python que VOUS définissez. Le LLM décide quoi appeler, avec quels paramètres — votre code l'exécute et renvoie le résultat.

Définir des outils (tools)

from openai import OpenAI
import json

client = OpenAI()

# Définition des outils au format OpenAI
tools = [
    \{
        "type": "function",
        "function": \{
            "name": "search_job_offers",
            "description": "Recherche des offres d'emploi sur les sites carrière. Utilise cette fonction quand l'utilisateur demande de trouver des offres.",
            "parameters": \{
                "type": "object",
                "properties": \{
                    "query": \{
                        "type": "string",
                        "description": "Termes de recherche (ex: 'Data Analyst Python')"
                    \},
                    "location": \{
                        "type": "string",
                        "description": "Ville ou région (ex: 'Paris', 'Remote')"
                    \},
                    "salary_min": \{
                        "type": "number",
                        "description": "Salaire minimum en K€"
                    \}
                \},
                "required": ["query"]
            \}
        \}
    \},
    \{
        "type": "function",
        "function": \{
            "name": "analyze_cv_match",
            "description": "Analyse la compatibilité entre un CV et une offre d'emploi.",
            "parameters": \{
                "type": "object",
                "properties": \{
                    "cv_summary": \{
                        "type": "string",
                        "description": "Résumé du CV du candidat"
                    \},
                    "job_description": \{
                        "type": "string",
                        "description": "Description de l'offre d'emploi"
                    \}
                \},
                "required": ["cv_summary", "job_description"]
            \}
        \}
    \},
    \{
        "type": "function",
        "function": \{
            "name": "send_application_email",
            "description": "Prépare et envoie un email de candidature.",
            "parameters": \{
                "type": "object",
                "properties": \{
                    "company": \{"type": "string", "description": "Nom de l'entreprise"\},
                    "position": \{"type": "string", "description": "Intitulé du poste"\},
                    "cover_letter": \{"type": "string", "description": "Lettre de motivation"\}
                \},
                "required": ["company", "position", "cover_letter"]
            \}
        \}
    \}
]

Implémentation des fonctions réelles

def search_job_offers(query, location=None, salary_min=None):
    """Recherche d'offres (simulation — en vrai, appeler Indeed/LinkedIn API)."""
    # En production : requests.get("https://api.indeed.com/...", params=\{...\})
    offers = [
        \{"title": "Data Analyst", "company": "TechCorp", "location": "Paris", 
         "salary": "48-55k€", "skills": ["Python", "SQL", "Tableau"]\},
        \{"title": "Business Data Analyst", "company": "FinanceAI", "location": "Paris",
         "salary": "50-60k€", "skills": ["Python", "SQL", "Excel", "Finance"]\},
    ]
    
    if salary_min:
        offers = [o for o in offers if int(o["salary"].split("-")[0]) >= salary_min]
    
    return json.dumps(offers, ensure_ascii=False)

def analyze_cv_match(cv_summary, job_description):
    """Analyse CV vs offre (utilise le LLM en interne)."""
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[\{
            "role": "user",
            "content": f"Compare ce CV avec cette offre. Score de 1-10.\nCV: \{cv_summary\}\nOffre: \{job_description\}"
        \}],
        max_tokens=300
    )
    return response.choices[0].message.content

def send_application_email(company, position, cover_letter):
    """Simule l'envoi d'un email (en production : SMTP ou API email)."""
    return json.dumps(\{
        "status": "sent",
        "to": f"recrutement@\{company.lower().replace(' ', '')\}.com",
        "subject": f"Candidature - \{position\}",
        "preview": cover_letter[:200]
    \})

# Mapping nom → fonction
FUNCTION_MAP = \{
    "search_job_offers": search_job_offers,
    "analyze_cv_match": analyze_cv_match,
    "send_application_email": send_application_email,
\}

Boucle d'agent avec function calling

def run_agent_with_tools(user_message):
    """Agent complet avec function calling OpenAI."""
    
    messages = [
        \{"role": "system", "content": """Tu es un agent de recherche d'emploi.
Tu as accès à des outils pour chercher des offres, analyser des CV, et envoyer des candidatures.
Utilise les outils quand c'est pertinent. Tu peux appeler plusieurs outils si nécessaire."""\},
        \{"role": "user", "content": user_message\}
    ]
    
    while True:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto"  # Le modèle décide s'il utilise un outil
        )
        
        message = response.choices[0].message
        messages.append(message)
        
        # Si le modèle ne veut pas utiliser d'outil → réponse finale
        if not message.tool_calls:
            return message.content
        
        # Exécuter chaque outil demandé
        for tool_call in message.tool_calls:
            func_name = tool_call.function.name
            func_args = json.loads(tool_call.function.arguments)
            
            print(f"🔧 Appel: \{func_name\}(\{func_args\})")
            
            # Exécuter la fonction
            func = FUNCTION_MAP[func_name]
            result = func(**func_args)
            
            print(f"📋 Résultat: \{result[:150]\}...")
            
            # Renvoyer le résultat au modèle
            messages.append(\{
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result
            \})

# Test
response = run_agent_with_tools(
    "Cherche des offres Data Analyst à Paris avec minimum 45k, "
    "puis analyse la meilleure par rapport à mon profil (8 ans finance, Python, SQL)."
)
print("\n🤖 Réponse finale:", response)

Parallel function calling

# OpenAI peut appeler PLUSIEURS fonctions en parallèle !
# Exemple : "Cherche des offres à Paris ET à Lyon"
# → Le modèle retourne 2 tool_calls simultanés :
#   - search_job_offers(query="Data Analyst", location="Paris")
#   - search_job_offers(query="Data Analyst", location="Lyon")
# → Votre code les exécute tous les deux
# → Les résultats sont renvoyés ensemble

# Le code ci-dessus gère déjà ce cas grâce à la boucle :
# for tool_call in message.tool_calls:  ← itère sur TOUS les appels

tool_choice : auto vs required vs none

auto : le modèle décide (recommandé). required : le modèle DOIT utiliser un outil (utile pour forcer une action). none : le modèle ne peut PAS utiliser d'outil (pour la réponse finale). \{"type": "function", "function": {"name": "search_job_offers"\}} : force un outil spécifique.

🏋️ Exercice pratique (30 minutes)

  1. →Définissez 3 outils pour votre agent (un de recherche, un d'analyse, un d'action)
  2. →Implémentez les fonctions Python correspondantes
  3. →Construisez la boucle agent avec function calling
  4. →Testez avec des requêtes nécessitant 1, 2, et 3 outils
  5. →Observez la trace : quels outils sont appelés et dans quel ordre ?
Quick Check

Quel est l'avantage du function calling vs parser manuellement la réponse du LLM ?

Quick Check

Que se passe-t-il quand le modèle décide qu'il n'a pas besoin d'outil ?

Your progress

Progress is self-reported and stored in your browser. The final completion record is not a qualification or an independent assessment.

View progress and completion record

Learn AI, from prompts to agents

15 free guidesQuizzes, diagrams and workshopsNo account needed

One practical AI workflow in your inbox

Methods, resources and new exercises. Free, unsubscribe at any time.