OpenAI · GPT-6 Astra

GPT-6 Astra Function Calling en 2026 : appeler des API, bases de données et outils personnalisés

2026.09.11 · ~15 min de lecture

Function Calling n'est pas difficile — les pièges sont une boucle d'outils mal écrite, une isolation des droits insuffisante et un enfermement dans Chat Completions qui bloque les outils hébergés. Ci-dessous : schéma d'outil HTTP API, boucle complète, pattern DB en lecture seule, comparatif fonctions vs outils hébergés, matrice et 7 étapes.

Développeur déboguant une boucle d'outils GPT-6 Astra Function Calling sur un écran

Le Function Calling de GPT-6 Astra est le moteur des agents IA : le modèle décide quel outil appeler et quels arguments passer ; votre runtime exécute l'effet de bord ; le résultat retourne au modèle pour continuer le raisonnement. Quand cette boucle est correcte, Astra peut interroger des API, lire des bases de données et exécuter une logique personnalisée de façon autonome. Quand elle est défectueuse, la boucle se bloque ou les droits des outils dépassent ce qui était prévu. Ce qu'est le Function Calling est couvert dans la comparaison de protocoles ; comment obtenir une clé API est dans le tutoriel API. Cet article couvre les trois patterns d'outils qui font passer de « ça tourne » à « c'est déployable en sécurité ».

Responses
Seul chemin pour les outils
function_call
Type d'événement dans output
allowlist
Ligne de sécurité des outils DB
L'API Responses est obligatoire
Les outils de fonctions, les outils hébergés (recherche web, interpréteur de code, Computer Use) et les boucles async exigent l'API Responses. Ajouter un outil hébergé à une requête Chat Completions renvoie HTTP 400. Tout le code de cet article suppose un chemin texte fonctionnel et utilise Responses.

Étape 1 : Définir un schéma d'outil

Un schéma d'outil est un objet JSON qui indique au modèle le nom de l'outil, ce qu'il fait et les paramètres qu'il accepte. Voici un outil qui appelle une API météo HTTP :

Schéma d'outil (outil API HTTP)
import json
from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get current weather for a city via HTTP API.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "City name, e.g. Tokyo, London, Shanghai",
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Temperature unit. Default celsius.",
                },
            },
            "required": ["city"],
            "additionalProperties": False,
        },
    }
]

La description doit dire ce que fait l'outil — pas seulement répéter son nom. Le modèle lit ce champ pour décider d'appeler l'outil. Les champs requis vont dans required ; les optionnels dans properties, mais pas dans required. additionalProperties: false réduit les clés inattendues. Plusieurs outils vont dans la même liste ; le modèle en choisit un ou plusieurs selon la conversation. En cas d'appels parallèles, la boucle doit traiter tous les résultats avant de continuer.

Étape 2 : La boucle d'outils complète

Le pattern : envoyer la requête → vérifier les éléments function_call dans output → exécuter → ajouter les résultats à input → renvoyer, jusqu'à ce qu'il n'y ait plus de function_call. La boucle doit être un while True — un if unique ne reçoit jamais la réponse finale du modèle.

Boucle d'outils complète (API Responses)
import json
import requests
from openai import OpenAI

client = OpenAI()

def call_weather_api(city: str, unit: str = "celsius") -> dict:
    """Replace with your real HTTP endpoint."""
    url = "https://api.example.com/weather"
    r = requests.get(url, params={"city": city, "unit": unit}, timeout=5)
    r.raise_for_status()
    return r.json()  # e.g. {"city": "Tokyo", "temp": 22, "condition": "sunny"}

# Initial request — model may call tools
response = client.responses.create(
    model="gpt-6-astra",
    input="What is the weather in Tokyo right now?",
    tools=tools,
    reasoning={"effort": "low"},
)

# Tool loop: keep going until model stops calling tools
while True:
    tool_calls = [o for o in response.output if o.type == "function_call"]
    if not tool_calls:
        break  # model is done — final answer is in response.output_text

    tool_results = []
    for call in tool_calls:
        args = json.loads(call.arguments)
        if call.name == "get_weather":
            result = call_weather_api(**args)
        else:
            result = {"error": f"Unknown tool: {call.name}"}
        tool_results.append({
            "type": "function_call_output",
            "call_id": call.call_id,
            "output": json.dumps(result, ensure_ascii=False),
        })

    # Append history + results and continue
    response = client.responses.create(
        model="gpt-6-astra",
        input=response.output + tool_results,
        tools=tools,
        reasoning={"effort": "low"},
    )

print(response.output_text)

Détails d'implémentation. ① response.output est une liste de types mélangés : ne filtrer que type == "function_call". ② Pour continuer, passer response.output + tool_results en input. Envoyer seulement tool_results fait perdre l'historique de conversation. ③ La call_id du résultat doit correspondre à celle de l'appel d'outil. ④ Sérialiser les valeurs de retour avec json.dumps — ne pas passer de dict Python brut.

Sécurité : liste blanche et isolation de l'exécution
Ce qu'un outil peut faire est décidé par votre runtime, pas par le modèle. Valider le champ name contre une allowlist connue. Vérifier les types d'arguments. Ajouter un timeout et une allowlist de domaines pour les outils HTTP. Les outils DB n'exécutent que des instructions SQL prédéfinies — ne jamais concaténer la sortie du modèle dans une chaîne SQL. Les outils qui écrivent sur disque ou exécutent des commandes shell doivent tourner sur un Mac distant jetable.

Étape 3 : Un outil de base de données en lecture seule

Trois exigences pour un outil DB sûr : connexion en lecture seule (pas d'INSERT, UPDATE, DELETE), requêtes paramétrées (pas d'injection SQL), SQL allowlist (pas de SQL arbitraire).

Outil DB en lecture seule (allowlist + paramétrage)
import sqlite3
from typing import Any

# Only these parameterized queries can be executed — no raw user SQL
ALLOWED_QUERIES: dict[str, str] = {
    "get_order":   "SELECT id, status, total, created_at FROM orders WHERE id = ?",
    "list_orders": "SELECT id, status, total FROM orders WHERE user_id = ? LIMIT 20",
}

def query_db(query_name: str, params: list[Any]) -> list[dict]:
    """Execute an allowlisted, parameterized read-only query.
    Never accepts raw SQL strings from the model.
    """
    sql = ALLOWED_QUERIES.get(query_name)
    if sql is None:
        raise ValueError(f"Query '{query_name}' not in allowlist")
    con = sqlite3.connect("orders.db", check_same_thread=False)
    con.row_factory = sqlite3.Row
    try:
        rows = con.execute(sql, params).fetchall()
        return [dict(r) for r in rows]
    finally:
        con.close()

# Schema exposed to the model
db_tool = {
    "type": "function",
    "name": "query_db",
    "description": "Query the orders DB. Only read-only allowlisted queries.",
    "parameters": {
        "type": "object",
        "properties": {
            "query_name": {
                "type": "string",
                "enum": list(ALLOWED_QUERIES.keys()),
                "description": "Name of the allowlisted query",
            },
            "params": {
                "type": "array",
                "items": {"type": ["string", "number"]},
                "description": "Positional parameters for the query",
            },
        },
        "required": ["query_name", "params"],
    },
}

En production : pool de connexions, timeout de requête, limite de lignes dans chaque SQL, masquage des colonnes sensibles. Le résultat renvoyé au modèle doit être un résumé, pas un dump brut de table — chaque ligne retournée coûte des tokens d'entrée à la prochaine requête.

Outils de fonctions vs outils hébergés

DimensionOutils de fonctions (type: function)Outils hébergés (exploités par OpenAI)
Lieu d'exécutionVotre runtime (local / Mac distant)Infrastructure OpenAI
Idéal pourAPI privées, BDD internes, logique métierRecherche web, interpréteur de code, shell, Computer Use
Effort de développementSchéma + fonction d'exécution + boucle à écrireNommer l'outil dans la liste, OpenAI gère l'exécution
FacturationTokens uniquementTokens + frais d'outil par appel
IsolationLes outils en écriture nécessitent un environnement isoléOpenAI gère le sandbox ; vous gérez la sécurité des données

Les deux types peuvent coexister dans la même requête. Les résultats des outils hébergés entrent automatiquement dans l'historique de conversation, sans soumission manuelle. Les résultats des outils de fonctions doivent être soumis manuellement via function_call_output.

Matrice de décision

Si vous avez besoin deChoisissezPourquoi
Appeler une API REST interneOutil de fonctionRéseau privé inaccessible depuis l'infra OpenAI
Interroger une BDD interne (lecture seule)Outil de fonction + SQL allowlistDonnées privées ; gérer les droits d'accès soi-même
Recherche web en temps réelOutil hébergé web_search_previewCrawling et classement gérés par OpenAI
Faire exécuter du Python au modèleOutil hébergé code_interpreterExécution dans le sandbox OpenAI
Le modèle pilote un bureau / navigateurOutil hébergé computer_use + Mac isoléBureau visible nécessaire ; isolation pour éviter les accidents
Commandes shell avec écriture disqueOutil de fonction + Mac distant isoléLes droits en écriture doivent rester sur un hôte jetable

A — Développeur solo / prototype : machine locale, outils de fonctions pour HTTP (pas d'écriture disque). Écrire le schéma, stabiliser la boucle, loguer les call_id. Passer aux outils multiples seulement après un loop mono-outil fiable.

B — Petite équipe / produit : outils de fonctions derrière des services internes avec auth par token. Outil DB en lecture seule + pool de connexions + timeout. Outils hébergés activés selon le type de tâche. Logique d'exécution couverte par des tests unitaires.

C — Entreprise : tous les appels d'outils via une API gateway avec log d'audit. DB : réplica en lecture seule + row-level security. Computer Use sur des Mac nodes jetables et isolés. Compte et livraison dans le centre d'aide ; coût mensuel des nodes sur la page tarifs.

Erreurs courantes

  1. Boucle exécutée une seule fois (if au lieu de while) : la réponse finale du modèle n'arrive jamais.
  2. Résultats soumis sans historique : passer seulement tool_results en input fait perdre le contexte.
  3. Sortie du modèle directement concaténée en SQL/shell : une allowlist + requêtes paramétrées éliminent cette surface d'attaque.
  4. Pas de timeout sur les outils HTTP : un service en aval qui se bloque gèle toute la session agent.
  5. Grands dumps renvoyés par les outils : les lignes consomment des tokens et peuvent déclencher l'uplift 272K.

Plan d'action : 7 étapes

  1. Confirmer d'abord que le chemin texte Responses fonctionne (voir le tutoriel API).
  2. Écrire le premier schéma d'outil. Description en phrase verbale, required rempli, additionalProperties: false.
  3. Implémenter la fonction d'exécution. Timeout pour les HTTP, allowlist + paramétrage pour les DB.
  4. Envoyer la requête Responses avec tools, afficher response.output et confirmer la présence de function_call.
  5. Implémenter la boucle while True. call_id alignées, function_call_output soumis, historique inclus dans input.
  6. Ajouter les outils hébergés si nécessaire. Leurs résultats ne nécessitent pas de soumission manuelle.
  7. Déplacer les outils en écriture sur un Mac distant isolé et détruire le workspace en fin de session.

FAQ

L'API Responses est-elle obligatoire pour Function Calling ?

Oui. Appels d'outils, outils hébergés et boucles async exigent Responses. Un outil hébergé sur Chat Completions renvoie 400.

Combien d'outils peut-on définir par requête ?

Pas de petite limite stricte, mais plus d'outils = plus de tokens. Ne passer que les outils utiles à la tâche en cours.

Comment prévenir l'injection SQL ?

Requêtes paramétrées avec ? combinées à une SQL allowlist. Ne jamais concaténer la sortie du modèle dans du SQL.

Outil de fonction ou outil hébergé ?

API privée, BDD interne, logique custom → outil de fonction. Recherche web, code, Computer Use → outil hébergé. Les deux peuvent coexister.

Peut-on streamer la réponse finale après des appels d'outils ?

Oui. Stabiliser d'abord la boucle sans streaming, puis ajouter stream=True.

Conclusion

Les trois fondations du Function Calling GPT-6 Astra : un schéma avec une description claire, une boucle while qui soumet l'historique complet avec chaque résultat, et des outils DB avec allowlist et requêtes paramétrées — les outils en écriture sur un Mac isolé. Les nodes Mac distants se trouvent sur les pages location et tarifs ; les questions de compte au centre d'aide.

Pour aller plus loin

Outils appelant de vraies API ? Exécutez-les sur un Cloud Mac isolé

Appeler un endpoint HTTP public en local est correct. Un outil qui écrit sur le disque, modifie un dépôt ou pilote un navigateur ne doit pas partager votre bureau quotidien. Les Mac distants isolent un espace de travail par session.

Commander · Voir les tarifs

GPT-6 Astra Function Calling

Outils appelant de vraies API ? Exécutez-les sur un Cloud Mac isolé

Cloud Mac · isolated agent runtime

Commander
Mac Commander