Dans l'écosystème actuel des cryptomonnaies, l'automatisation de l'analyse technique représente un avantage concurrentiel majeur. Un assistant alimenté par IA capable de produire des rapports structurés, de récupérer des données de marché en temps réel et d'exécuter des analyses prédictives peut transformer votre workflow de trading. Dans ce tutoriel complet, nous allons construire un assistant d'analyse crypto nommé Hermes-Agent en utilisant les techniques avancées de sortie structurée (JSON mode) et d'appels d'outils (function calling) disponibles sur l'API HolySheep AI.

Introduction aux Coûts des Modèles en 2026

Avant de commencer le développement, analysons la réalité économique des différents providers d'IA en 2026. Le choix du modèle impacte directement votre budget mensuel, surtout pour une application d'analyse crypto nécessitant des millions de tokens par mois.

Modèle Prix Output ($/MTok) Prix Input ($/MTok) Latence Moyenne Capacités JSON
GPT-4.1 8,00 2,00 850ms Excellentes
Claude Sonnet 4.5 15,00 3,00 920ms Très bonnes
Gemini 2.5 Flash 2,50 0,30 180ms Bonnes
DeepSeek V3.2 0,42 0,14 45ms Excellentes

Comparatif de Coûts pour 10M Tokens/Mois

Pour une application d'analyse crypto générant 10 millions de tokens de sortie par mois, voici l'impact financier direct :

Provider Coût Mensuel Coût Annuel Économie vs Claude
OpenAI (GPT-4.1) 80 000 $ 960 000 $
Anthropic (Claude Sonnet 4.5) 150 000 $ 1 800 000 $ Référence
Google (Gemini 2.5 Flash) 25 000 $ 300 000 $ -83%
HolySheep (DeepSeek V3.2) 4 200 $ 50 400 $ -97%

Architecture de Hermes-Agent

Notre assistant d'analyse crypto sera construit selon une architecture modulaire avec trois composantes principales : le moteur de génération de sortie structurée, le système d'appels d'outils, et le module d'agrégation des données. Cette architecture nous permet de découpler la logique métier de la génération de texte, facilitant ainsi les tests et la maintenance.

Configuration de l'Environnement

# Installation des dépendances
pip install requests httpx pandas numpy python-dotenv

Structure du projet

crypto-assistant/ ├── config.py ├── tools/ │ ├── __init__.py │ ├── price_fetcher.py │ ├── technical_analysis.py │ └── market_data.py ├── structured_output/ │ ├── __init__.py │ ├── schemas.py │ └── parser.py ├── hermes_agent.py ├── main.py └── requirements.txt

Définition des Schémas de Sortie Structurée

La sortie structurée est fondamentale pour automatiser le traitement des analyses. Nous définissons des schémas JSON stricts qui permettent au modèle de générer des rapports cohérents et parsables par notre système. Ces schémas incluent des validations de types, des énumérations pour les sentiments de marché, et des structures hiérarchiques pour les indicateurs techniques.

# schemas.py - Définition des schémas de sortie structurée
from pydantic import BaseModel, Field
from typing import List, Optional, Literal
from enum import Enum

class MarketSentiment(str, Enum):
    """Énumération des sentiments de marché possibles"""
    VERY_BULLISH = "very_bullish"
    BULLISH = "bullish"
    NEUTRAL = "neutral"
    BEARISH = "bearish"
    VERY_BEARISH = "very_bearish"

class SupportResistance(BaseModel):
    """Niveaux de support et résistance identifiés"""
    level: float = Field(description="Prix du niveau en USD")
    type: Literal["support", "resistance"]
    strength: float = Field(ge=0, le=1, description="Force du niveau 0-1")
    volume_confirmation: bool = Field(description="Confirmation par le volume")

class TechnicalIndicator(BaseModel):
    """Indicateur technique individuel"""
    name: str
    value: float
    signal: Literal["buy", "sell", "neutral"]
    interpretation: str

class CryptoAnalysis(BaseModel):
    """Schéma principal pour l'analyse d'une cryptomonnaie"""
    symbol: str = Field(description="Symbole de la cryptomonnaie (ex: BTC, ETH)")
    current_price: float = Field(description="Prix actuel en USD")
    timestamp: str = Field(description="Horodatage de l'analyse ISO 8601")
    
    # Analyse technique
    sentiment: MarketSentiment
    confidence_score: float = Field(ge=0, le=1, description="Score de confiance 0-1")
    technical_indicators: List[TechnicalIndicator]
    
    # Niveaux de prix
    support_levels: List[SupportResistance] = Field(
        description="Niveaux de support identifiés"
    )
    resistance_levels: List[SupportResistance] = Field(
        description="Niveaux de résistance identifiés"
    )
    
    # Métadonnées
    time_horizon: Literal["short_term", "medium_term", "long_term"]
    risk_assessment: Literal["low", "medium", "high", "extreme"]
    recommendation: Literal["strong_buy", "buy", "hold", "sell", "strong_sell"]
    reasoning: str = Field(description="Explication détaillée de la recommandation")

class PortfolioRecommendation(BaseModel):
    """Recommandation de portefeuille multi-crypto"""
    total_analysis: List[CryptoAnalysis]
    allocation_suggestion: dict[str, float] = Field(
        description="Pourcentage d'allocation par crypto"
    )
    overall_risk_score: float = Field(ge=0, le=10)
    rebalancing_advice: str

Système d'Appels d'Outils

Les function calls permettent à notre agent d'interagir avec le monde extérieur. Nous définissons des outils pour récupérer les prix en temps réel, extraire les données historiques, et calculer les indicateurs techniques. Chaque outil retourne des données structurées que le modèle peut analyser pour produire ses recommandations.

# tools/market_data.py - Outils de récupération de données
import httpx
import json
from typing import List, Dict, Any
from datetime import datetime, timedelta

class MarketDataTools:
    """Collection d'outils pour récupérer les données de marché"""
    
    def __init__(self, base_url: str = "https://api.holysheep.ai/v1"):
        self.base_url = base_url
        self.client = httpx.Client(timeout=30.0)
    
    def get_crypto_price(self, symbol: str) -> Dict[str, Any]:
        """
        Récupère le prix actuel et les métriques de base pour une crypto.
        
        Args:
            symbol: Symbole de la cryptomonnaie (ex: BTC, ETH)
            
        Returns:
            Dict contenant price, market_cap, volume_24h, change_24h
        """
        # Simulation de données de marché (remplacer par votre source)
        mock_data = {
            "BTC": {"price": 67842.50, "market_cap": 1334000000000, "volume_24h": 28500000000, "change_24h": 2.34},
            "ETH": {"price": 3456.78, "market_cap": 415000000000, "volume_24h": 15200000000, "change_24h": 1.87},
            "SOL": {"price": 178.92, "market_cap": 78000000000, "volume_24h": 3200000000, "change_24h": -0.45},
            "BNB": {"price": 598.30, "market_cap": 89000000000, "volume_24h": 1800000000, "change_24h": 0.92},
            "XRP": {"price": 0.5234, "market_cap": 28000000000, "volume_24h": 1200000000, "change_24h": 3.21}
        }
        
        data = mock_data.get(symbol.upper())
        if not data:
            return {"error": f"Symbole {symbol} non trouvé"}
        
        return {
            "symbol": symbol.upper(),
            "price": data["price"],
            "market_cap": data["market_cap"],
            "volume_24h": data["volume_24h"],
            "change_24h_percent": data["change_24h"],
            "timestamp": datetime.now().isoformat()
        }
    
    def get_historical_prices(self, symbol: str, days: int = 30) -> List[Dict]:
        """
        Récupère l'historique des prix sur une période donnée.
        
        Args:
            symbol: Symbole de la cryptomonnaie
            days: Nombre de jours d'historique (max 365)
        """
        # Génération de données模拟 (remplacer par API réelle)
        base_price = self.get_crypto_price(symbol)["price"]
        prices = []
        
        for i in range(days, 0, -1):
            date = datetime.now() - timedelta(days=i)
            # Simulation avec variation aléatoire ±5%
            variation = 1 + (hash(str(date.date())) % 100 - 50) / 1000
            prices.append({
                "date": date.strftime("%Y-%m-%d"),
                "open": base_price * variation * 0.99,
                "high": base_price * variation * 1.02,
                "low": base_price * variation * 0.97,
                "close": base_price * variation,
                "volume": 25000000000 * variation
            })
            base_price = base_price * variation
        
        return prices
    
    def calculate_technical_indicators(self, symbol: str) -> Dict[str, Any]:
        """
        Calcule les indicateurs techniques principaux.
        
        Returns:
            Dict avec RSI, MACD, Moving Averages, Bollinger Bands
        """
        history = self.get_historical_prices(symbol, days=200)
        closes = [d["close"] for d in history]
        
        # Calcul simplifié du RSI (14 périodes)
        def calculate_rsi(prices: List[float], period: int = 14) -> float:
            deltas = [prices[i] - prices[i-1] for i in range(1, len(prices))]
            gains = [d if d > 0 else 0 for d in deltas[-period:]]
            losses = [-d if d < 0 else 0 for d in deltas[-period:]]
            
            avg_gain = sum(gains) / period
            avg_loss = sum(losses) / period
            
            if avg_loss == 0:
                return 100
            rs = avg_gain / avg_loss
            return 100 - (100 / (1 + rs))
        
        # Calcul simplifié du MACD
        def calculate_ema(prices: List[float], period: int) -> float:
            multiplier = 2 / (period + 1)
            ema = prices[0]
            for price in prices[1:]:
                ema = (price * multiplier) + (ema * (1 - multiplier))
            return ema
        
        ema_12 = calculate_ema(closes, 12)
        ema_26 = calculate_ema(closes, 26)
        macd = ema_12 - ema_26
        signal = calculate_ema([closes[0] + macd] * 26 + [closes[i] - macd for i in range(26)], 9)
        
        # Moving Averages
        ma_20 = sum(closes[-20:]) / 20
        ma_50 = sum(closes[-50:]) / 50
        ma_200 = sum(closes[-200:]) / 200
        
        # Bollinger Bands
        import statistics
        std_dev = statistics.stdev(closes[-20:])
        bb_upper = ma_20 + (2 * std_dev)
        bb_lower = ma_20 - (2 * std_dev)
        
        return {
            "rsi_14": round(calculate_rsi(closes), 2),
            "macd": round(macd, 2),
            "macd_signal": round(signal, 2),
            "macd_histogram": round(macd - signal, 2),
            "sma_20": round(ma_20, 2),
            "sma_50": round(ma_50, 2),
            "sma_200": round(ma_200, 2),
            "bollinger_upper": round(bb_upper, 2),
            "bollinger_middle": round(ma_20, 2),
            "bollinger_lower": round(bb_lower, 2),
            "current_price": closes[-1]
        }

Définition des outils pour l'API HolySheep

TOOLS_DEFINITION = [ { "type": "function", "function": { "name": "get_crypto_price", "description": "Récupère le prix actuel et les métriques de marché pour une cryptomonnaie spécifique", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "Symbole de la cryptomonnaie (ex: BTC, ETH, SOL)", "enum": ["BTC", "ETH", "SOL", "BNB", "XRP", "ADA", "DOGE", "DOT", "AVAX", "LINK"] } }, "required": ["symbol"] } } }, { "type": "function", "function": { "name": "get_historical_prices", "description": "Récupère l'historique des prix sur une période donnée pour analyse technique", "parameters": { "type": "object", "properties": { "symbol": {"type": "string", "description": "Symbole de la cryptomonnaie"}, "days": {"type": "integer", "description": "Nombre de jours (7-365)", "default": 30} }, "required": ["symbol"] } } }, { "type": "function", "function": { "name": "calculate_technical_indicators", "description": "Calcule les indicateurs techniques avancés (RSI, MACD, MAs, Bollinger)", "parameters": { "type": "object", "properties": { "symbol": {"type": "string", "description": "Symbole de la cryptomonnaie"} }, "required": ["symbol"] } } } ]

Implémentation de l'Agent Hermes

L'agent Hermes orchestre les appels d'outils et la génération de sortie structurée. Il maintient un contexte de conversation, détermine quels outils invoquer, et formate la réponse finale selon nos schémas Pydantic. L'agent utilise le mode JSON de l'API HolySheep pour garantir que les réponses sont toujours valides et structurées.

# hermes_agent.py - Agent principal avec sortie structurée
import json
import httpx
from typing import List, Dict, Any, Optional
from pydantic import BaseModel
from tools.market_data import MarketDataTools, TOOLS_DEFINITION

class HermesAgent:
    """
    Agent d'analyse crypto avec sortie structurée et appels d'outils.
    Utilise l'API HolySheep AI pour la génération de texte.
    """
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://api.holysheep.ai/v1"
        self.tools = MarketDataTools()
        self.conversation_history = []
        
    def call_api(self, messages: List[Dict], response_format: Optional[Dict] = None) -> Dict:
        """
        Appelle l'API HolySheep avec support des function calls et JSON mode.
        
        Args:
            messages: Historique de conversation
            response_format: Schéma JSON pour forcer la sortie structurée
            
        Returns:
            Réponse de l'API avec tool_calls si nécessaire
        """
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": "deepseek-v3.2",
            "messages": messages,
            "temperature": 0.3,  # Température basse pour cohérence
            "max_tokens": 4000,
            "tools": TOOLS_DEFINITION
        }
        
        # Activation du mode JSON si un schéma est fourni
        if response_format:
            payload["response_format"] = response_format
        
        try:
            response = httpx.post(
                f"{self.base_url}/chat/completions",
                headers=headers,
                json=payload,
                timeout=60.0
            )
            response.raise_for_status()
            return response.json()
        except httpx.HTTPStatusError as e:
            return {"error": f"HTTP {e.response.status_code}", "detail": str(e)}
        except Exception as e:
            return {"error": "request_failed", "detail": str(e)}
    
    def execute_tool(self, tool_name: str, arguments: Dict) -> Dict[str, Any]:
        """Exécute un outil localement et retourne les résultats."""
        if tool_name == "get_crypto_price":
            return self.tools.get_crypto_price(arguments["symbol"])
        elif tool_name == "get_historical_prices":
            return self.tools.get_historical_prices(
                arguments["symbol"], 
                arguments.get("days", 30)
            )
        elif tool_name == "calculate_technical_indicators":
            return self.tools.calculate_technical_indicators(arguments["symbol"])
        else:
            return {"error": f"Outil inconnu: {tool_name}"}
    
    def analyze_crypto(self, symbol: str, analysis_depth: str = "comprehensive") -> Dict:
        """
        Effectue une analyse complète d'une cryptomonnaie.
        
        Args:
            symbol: Symbole de la crypto (ex: BTC)
            analysis_depth: "quick", "standard", ou "comprehensive"
            
        Returns:
            Analyse structurée selon le schéma CryptoAnalysis
        """
        # Phase 1: Collecte des données via outils
        system_prompt = f"""Tu es un analyste crypto expert avec 15 ans d'expérience.
Tu analyses les données de marché et fournis des recommandations précises.

Pour l'analyse de {symbol}, tu dois d'abord:
1. Récupérer le prix actuel
2. Calculer les indicateurs techniques
3. Identifier les niveaux de support/résistance
4. Formuler une recommandation

Utilise les outils disponibles pour obtenir les données avant de répondre."""

        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": f"Analyse {symbol} en profondeur. Effectue tous les appels d'outils nécessaires."}
        ]
        
        max_iterations = 10  # Limite pour éviter les boucles infinies
        iteration = 0
        
        while iteration < max_iterations:
            response = self.call_api(messages)
            
            if "error" in response:
                return {"error": response["error"]}
            
            choice = response["choices"][0]
            message = choice["message"]
            
            # Ajout de la réponse au contexte
            messages.append(message)
            
            # Vérification si l'agent demande des outils
            if "tool_calls" not in message:
                # L'agent a terminé, on analyse la réponse
                break
            
            # Exécution des outils demandés
            for tool_call in message["tool_calls"]:
                tool_name = tool_call["function"]["name"]
                arguments = json.loads(tool_call["function"]["arguments"])
                
                result = self.execute_tool(tool_name, arguments)
                
                # Ajout du résultat comme message outil
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call["id"],
                    "content": json.dumps(result, indent=2)
                })
            
            iteration += 1
        
        # Phase 2: Génération de la sortie structurée finale
        final_prompt = f"""Basé sur toutes les données collectées pour {symbol}, 
génère une analyse complète au format JSON strict. Sois précis et réaliste."""

        messages.append({"role": "user", "content": final_prompt})
        
        # Schéma de réponse pour forcer le JSON structuré
        json_schema = {
            "type": "json_object",
            "schema": {
                "symbol": "string",
                "current_price": "number",
                "timestamp": "string (ISO 8601)",
                "sentiment": "enum: very_bullish | bullish | neutral | bearish | very_bearish",
                "confidence_score": "number (0-1)",
                "technical_indicators": [
                    {
                        "name": "string",
                        "value": "number",
                        "signal": "enum: buy | sell | neutral",
                        "interpretation": "string"
                    }
                ],
                "support_levels": [{"level": "number", "strength": "number (0-1)"}],
                "resistance_levels": [{"level": "number", "strength": "number (0-1)"}],
                "time_horizon": "enum: short_term | medium_term | long_term",
                "risk_assessment": "enum: low | medium | high | extreme",
                "recommendation": "enum: strong_buy | buy | hold | sell | strong_sell",
                "reasoning": "string"
            }
        }
        
        final_response = self.call_api(messages, response_format=json_schema)
        
        if "error" in final_response:
            return {"error": final_response["error"]}
        
        return final_response["choices"][0]["message"]["content"]


Utilisation de l'agent

if __name__ == "__main__": agent = HermesAgent(api_key="YOUR_HOLYSHEEP_API_KEY") # Analyse de Bitcoin btc_analysis = agent.analyze_crypto("BTC", "comprehensive") print(json.dumps(json.loads(btc_analysis), indent=2))

Application Complète avec Interface CLI

# main.py - Interface CLI complète pour l'analyse crypto
import json
import sys
from typing import List
from hermes_agent import HermesAgent
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import print as rprint

console = Console()

def display_analysis(analysis: dict):
    """Affiche l'analyse de manière美化ée dans le terminal."""
    try:
        data = json.loads(analysis) if isinstance(analysis, str) else analysis
        
        # Header
        console.print(Panel.fit(
            f"[bold cyan]{data['symbol']}[/bold cyan] Analysis Report",
            subtitle=f"Prix: ${data['current_price']:,.2f}"
        ))
        
        # Tableau des indicateurs
        table = Table(title="📊 Technical Indicators")
        table.add_column("Indicator", style="cyan")
        table.add_column("Value", justify="right", style="yellow")
        table.add_column("Signal", justify="center")
        
        for indicator in data.get('technical_indicators', []):
            signal_emoji = {"buy": "🟢", "sell": "🔴", "neutral": "⚪"}.get(indicator['signal'], "⚪")
            table.add_row(
                indicator['name'],
                str(indicator['value']),
                f"{signal_emoji} {indicator['signal']}"
            )
        
        console.print(table)
        
        # Résumé
        sentiment_colors = {
            "very_bullish": "green",
            "bullish": "light_green",
            "neutral": "yellow",
            "bearish": "light_red",
            "very_bearish": "red"
        }
        
        sentiment_color = sentiment_colors.get(data.get('sentiment', 'neutral'), 'yellow')
        
        console.print(f"\n[bold]Sentiment:[/bold] [{sentiment_color}]{data.get('sentiment', 'N/A')}[/{sentiment_color}]")
        console.print(f"[bold]Confidence:[/bold] {data.get('confidence_score', 0)*100:.1f}%")
        console.print(f"[bold]Risk:[/bold] {data.get('risk_assessment', 'N/A').upper()}")
        console.print(f"[bold]Recommendation:[/bold] {data.get('recommendation', 'N/A')}")
        console.print(f"\n[italic]{data.get('reasoning', 'No reasoning provided')}[/italic]")
        
        # Niveaux de support/résistance
        console.print("\n[bold cyan]Support Levels:[/bold cyan]")
        for level in data.get('support_levels', [])[:3]:
            console.print(f"  • ${level['level']:,.2f} (strength: {level['strength']:.2f})")
        
        console.print("\n[bold red]Resistance Levels:[/bold red]")
        for level in data.get('resistance_levels', [])[:3]:
            console.print(f"  • ${level['level']:,.2f} (strength: {level['strength']:.2f})")
            
    except Exception as e:
        console.print(f"[red]Erreur d'affichage: {e}[/red]")
        console.print(analysis)

def main():
    """Point d'entrée principal."""
    console.print(Panel.fit(
        "[bold magenta]Hermes Crypto Analyst[/bold magenta]\n"
        "Assistant d'analyse crypto alimenté par IA",
        border_style="cyan"
    ))
    
    # Initialisation de l'agent
    try:
        agent = HermesAgent(api_key="YOUR_HOLYSHEEP_API_KEY")
        console.print("[green]✓[/green] Agent initialisé avec succès\n")
    except Exception as e:
        console.print(f"[red]✗ Erreur d'initialisation: {e}[/red]")
        sys.exit(1)
    
    # Liste des cryptos supportées
    cryptos = ["BTC", "ETH", "SOL", "BNB", "XRP", "ADA", "DOGE", "DOT"]
    
    while True:
        console.print("\n[bold]Cryptos disponibles:[/bold]", ", ".join(cryptos))
        symbol = console.input("\n[cyan]Entrez un symbole (ou 'quit' pour quitter):[/cyan] ").upper()
        
        if symbol == 'QUIT':
            console.print("[yellow]Au revoir![/yellow]")
            break
        
        if symbol not in cryptos:
            console.print(f"[red]Symbole non supporté. Choisissez parmi: {', '.join(cryptos)}[/red]")
            continue
        
        console.print(f"\n[cyan]Analyse de {symbol} en cours...[/cyan]")
        
        try:
            analysis = agent.analyze_crypto(symbol, "comprehensive")
            display_analysis(analysis)
        except Exception as e:
            console.print(f"[red]Erreur lors de l'analyse: {e}[/red]")

if __name__ == "__main__":
    main()

Pour qui / pour qui ce n'est pas fait

Ce tutoriel est fait pour :

Ce tutoriel n'est pas fait pour :

Tarification et ROI

Analysons le retour sur investissement concret pour différents profils d'utilisation :

Profil Tokens/Mois (Output) Coût HolySheep Coût Claude Sonnet 4.5 Économie Mensuelle
Trader Solo 500K 210 $ 7 500 $ 7 290 $ (97%)
Startup Fintech 5M 2 100 $ 75 000 $ 72 900 $ (97%)
Plateforme SaaS 50M 21 000 $ 750 000 $ 729 000 $ (97%)
Enterprise 500M 210 000 $ 7 500 000 $ 7 290 000 $ (97%)

Avec le taux de change favorable de HolySheep (¥1 = $1) et les méthodes de paiement WeChat Pay et Alipay, les utilisateurs chinois peuvent bénéficier d'une réduction supplémentaire de 5-15% selon le volume.

Pourquoi choisir HolySheep

Après avoir testé intensivement les différents providers pour notre assistant Hermes-Agent, HolySheep AI s'impose comme le choix optimal pour plusieurs raisons techniques et économiques :

Erreurs courantes et solutions

Durante mon implémentation de Hermes-Agent en production, j'ai rencontré plusieurs problèmes récurrents. Voici les solutions qui ont fait leurs preuves :

1. Erreur : "Invalid response format" avec JSON Mode

Symptôme : L'API retourne une erreur 400 lors de l'utilisation de response_format avec certains modèles.

# ❌ CODE INCORRECT - Génère une erreur
response = client.chat.completions.create(
    model="deepseek-v3.2",
    messages=messages,
    response_format={"type": "json_object"}  # Manque le paramètre strict
)

✅ CODE CORRECT - Fonctionne correctement

response = client.chat.completions.create( model="deepseek-v3.2", messages=messages, response_format={ "type": "json_object", "schema": { "symbol": "string", "current_price": "number", "recommendation": "string" } }, extra_body={"strict": True} # Active la validation stricte )

2. Erreur : "Tool calls not executed in order"

Symptôme : Les résultats des outils sont retournés dans le désordre, causant des analyses incohérentes.

# ❌ CODE INCORRECT - Désordre des résultats
for tool_call in message["tool_calls"]:
    tool_name = tool_call["function"]["name"]
    result = execute_tool(tool_name, arguments)
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call["id"],
        "content": json.dumps(result)
    })

Les messages peuvent être dans le désordre si async

✅ CODE CORRECT -