Aller au contenu

Connecteurs API

Plutôt que de copier vos données dans une base de connaissance, vous pouvez laisser l’IA interroger votre API en direct. Vous enregistrez une connexion (URL + authentification + opérations), et chaque opération en lecture devient un outil que le modèle peut appeler dans sa réflexion, comme la recherche web ou le RAG agentique.

Au portail (Intégrations → Connecteurs API) ou via l’API. Une connexion porte :

  • un nom et une URL de base (https://…) ;
  • une authentification : none, api_key (header ou query), bearer, basic, ou oauth2 (Google Drive et tout autre fournisseur OAuth2 — cf. section dédiée ci-dessous). Le secret est chiffré au repos (AES-256-GCM, une clé dédiée par connexion) ;
  • des headers statiques optionnels (auth_config.headers), envoyés sur chaque requête — typiquement une version d’API imposée par le fournisseur, ex. Notion : "auth_config": { "headers": { "Notion-Version": "2022-06-28" } }. Jamais de secret ici : ces headers ne sont pas chiffrés (et voyagent dans l’export du connecteur) ; les headers Authorization et Cookie y sont refusés, le secret passe par credential ;
  • une liste d’opérations définies à la main.
Fenêtre de terminal
curl https://api.astrolabe.chat/v1/connections \
-H "Authorization: Bearer $ASTROLABE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Mon Airtable",
"base_url": "https://api.airtable.com",
"auth_type": "bearer",
"credential": "patXXXX.XXXX",
"operations": [
{
"name": "list_records",
"description": "Liste les enregistrements d une table.",
"method": "GET",
"path": "/v0/{base_id}/{table}",
"params": [
{ "name": "base_id", "in": "path", "type": "string", "required": true },
{ "name": "table", "in": "path", "type": "string", "required": true },
{ "name": "filterByFormula", "in": "query", "type": "string" }
],
"access": "read"
}
]
}'

La réponse renvoie le slug de la connexion (identifiant stable par compte) — c’est lui qui sert à l’activer dans une requête de chat. Le secret n’est jamais renvoyé.

ChampRôle
namenom de l’opération → suffixe de l’outil exposé au modèle (<slug>__<opération>).
description(optionnel) contexte d’usage injecté dans la déf d’outil — aide fortement le modèle à savoir quand/comment l’appeler.
methodGET, POST… (une lecture peut être un POST, ex. une requête de recherche).
pathgabarit relatif à base_url ; les {param} sont substitués depuis les arguments. Peut aussi être une URL ABSOLUE (https://…) — elle court-circuite alors base_url pour cette opération précise. Utile quand un même jeu de credentials (ex. les mêmes tokens OAuth2) couvre plusieurs hôtes d’API — cf. l’exemple Google Docs ci-dessous.
paramsliste typée. inpath | query | body ; typestring | integer | number | boolean ; required.
accessread (défaut) | write. Les deux sont exécutées ; write ajoute un marqueur « modifie des données » à la déf et permet de restreindre l’accès par clé.
examples(optionnel) tableau JSON d’exemples d’appel ([{…args…}]) → une « bibliothèque » que le modèle peut imiter.

Au niveau de la connexion, un champ doc_url (optionnel) pointe vers la doc de l’API : il est ajouté au contexte des outils, et l’IA peut le lire via web_fetch si la recherche web est active.

Certains fournisseurs (Google Drive en premier lieu) exigent OAuth2 plutôt qu’un secret statique. Le mécanisme est générique (réutilisable pour tout fournisseur OAuth2) — Google n’est qu’un préréglage.

Créer l’app côté Google (une fois, dans la console Google Cloud de votre Workspace) :

  1. Créez un projet, puis un écran de consentement OAuth de type Interne (« Internal ») — pas besoin de vérification Google, aucun plafond d’utilisateurs, refresh token de durée normale.
  2. Activez l’API Google Drive sur le projet.
  3. Créez des identifiants OAuth client ID (type « Application Web »), avec comme URI de redirection autorisée :
    https://app.astrolabe.chat/api/integrations/oauth/callback
  4. Notez le Client ID et le Client secret générés.

Créer la connexion côté Astrolabe (portail, auth_type: "oauth2") :

{
"name": "Google Drive",
"base_url": "https://www.googleapis.com/drive/v3",
"auth_type": "oauth2",
"auth_config": {
"authorize_url": "https://accounts.google.com/o/oauth2/v2/auth",
"token_url": "https://oauth2.googleapis.com/token",
"scopes": ["https://www.googleapis.com/auth/drive.readonly"],
// quirk Google : force l'émission d'un refresh_token à CHAQUE consentement
"extra_authorize_params": { "access_type": "offline", "prompt": "consent" }
},
"credential": { "client_id": "", "client_secret": "" },
"operations": [
{
"name": "list_files",
"method": "GET",
"path": "/files",
"access": "read",
"params": [
{ "name": "q", "in": "query", "type": "string" },
{ "name": "pageSize", "in": "query", "type": "integer" },
{ "name": "pageToken", "in": "query", "type": "string" },
{ "name": "fields", "in": "query", "type": "string" }
]
}
]
}

Le param q scope l’opération à un dossier précis, ex. "'<folder_id>' in parents" (fixé en paramètre fixe de la config de synchronisation, cf. section suivante) — sans lui, list_files liste tout le Drive accessible à l’app.

Au portail, cliquez ensuite « Connecter » sur la carte du connecteur : vous êtes redirigé vers l’écran de consentement Google, puis ramené au portail une fois l’autorisation accordée. La finalisation du consentement (l’échange du code contre les tokens) se fait uniquement au portail — un navigateur est nécessaire, ce n’est pas exposé sur /v1. La création de la connexion (avec client_id/client_secret), elle, reste possible via l’API.

Activez-la avec tools_enabled, en référençant son slug préfixé par connection: :

Fenêtre de terminal
curl https://api.astrolabe.chat/v1/chat/completions \
-H "Authorization: Bearer $ASTROLABE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "mistral-large",
"messages": [{ "role": "user", "content": "Combien d enregistrements dans la table Clients ?" }],
"tools_enabled": ["connection:mon-airtable"]
}'

Toutes les opérations de la connexion sont alors proposées au modèle, qui choisit lesquelles appeler. Les connecteurs coexistent avec la recherche web et le RAG agentique dans la même réflexion : tools_enabled: ["web_search", "connection:mon-airtable"] + knowledge_base.

Pour n’exposer qu’une opération (au lieu de toutes), suffixez le slug par : + le nom de l’opération : tools_enabled: ["connection:mon-airtable:list_records"]. Seule cette déf d’outil est injectée — utile pour les automatisations (Make/n8n) qui savent ce qu’elles veulent, et pour réduire le contexte (donc le coût) sur les connecteurs riches en opérations.

Deux niveaux :

  • Scope de clé connections : une clé API doit porter ce scope pour utiliser le moindre connecteur (choisi à la création/édition de la clé). Sans lui, les connecteurs ne sont pas proposés au modèle.
  • Accès par connexion : par défaut, toutes vos clés peuvent utiliser un nouveau connecteur (toutes ses opérations, lecture comme écriture). Au portail (bouton Accès), vous restreignez l’accès à des clés précises.
MéthodeRouteRôle
GET/v1/connectionsliste
POST/v1/connectionscréer
GET/v1/connections/{slug}détail
PATCH/v1/connections/{slug}modifier (credential omis = inchangé)
DELETE/v1/connections/{slug}supprimer
POST/v1/connections/{slug}/syncdéclencher une synchronisation{ ok, outcome }

Toutes ces routes exigent le scope connections. Le POST .../sync lance la synchronisation configurée (cf. section suivante) et facture l’embedding sur la clé de l’appel — c’est la parité API du bouton « Synchroniser » du portail (en plus de la planification automatique).

Synchroniser une connexion vers une base de connaissance

Section intitulée « Synchroniser une connexion vers une base de connaissance »

Pour rendre les données d’un connecteur cherchables, la voie recommandée est de les synchroniser dans une base de connaissance : Astrolabe aspire les enregistrements d’une opération de liste et les enregistre comme documents de la base (un enregistrement = un document, clé d’upsert = external_id). La recherche reste alors unifiée sur la base — même pertinence, mêmes facettes, et surtout la recherche sémantique — pour n’importe quel connecteur, y compris ceux dont l’API n’offre aucune recherche texte.

Dans la modale du connecteur, section Synchronisation :

  1. Opération de liste : une opération read qui liste les enregistrements (Astrolabe pagine automatiquement en suivant le curseur de l’opération).

  2. Paramètres fixes (optionnel) : arguments requis par l’opération en plus de la pagination. Cas typique — une base Airtable dont la table est un paramètre (GET /{table}) : mettez {"table":"Entreprises"}. Une synchronisation cible une source ; pour plusieurs tables, créez une config (ou un connecteur) par table.

  3. Base cible : le slug de la base de connaissance qui reçoit les documents.

  4. Correspondance des champs (map) : comment transformer un enregistrement en document. Cliquez Détecter pour pré-remplir identifiant / titre / date / lien / version à partir d’un échantillon de l’opération (ajustez ensuite ; les facettes restent à définir car elles dépendent de votre base). Chaque champ est un nom de champ (top-level, chemin pointé, ou fields.X façon Airtable) ou un gabarit {champ} composant plusieurs champs.

    • external_id (requis) — l’identifiant stable de l’enregistrement (clé d’upsert) ;
    • title (requis) — le titre du document ;
    • text (optionnel) — le contenu indexé ; par défaut, tous les champs de l’enregistrement sont sérialisés en lignes « Clé : valeur » (bon pour le sémantique) ;
    • date (optionnel) — la date métier du document (doc_date) ;
    • url (optionnel) — un lien vers l’enregistrement, ex. https://airtable.com/appXXX/{id} ;
    • facets (optionnel) — une correspondance clé de facette → champ, pour filtrer ensuite ;
    • version (optionnel) — un champ de date de modification (ex. updated_at) : un document n’est ré-indexé que si cette valeur change → synchronisations incrémentales peu coûteuses, insensibles aux champs volatils (liens signés, etc.). Sinon, la détection se base sur le contenu.
  5. Découpage : simple (déterministe, gratuit, bon défaut pour des enregistrements courts), whole (un enregistrement = un extrait : le plus juste quand chaque fiche synchronisée est déjà une unité complète, contact ou facture) ou ai (un modèle re-segmente le document selon l’intention de la base et remplit les facettes, utile pour des documents longs ou quand la base a des facettes à extraire). En mode ai, choisissez le modèle de découpage et la clé qui porte la consommation (par défaut : la clé du compte). L’embedding, lui, est toujours facturé sur cette clé. Si vous ne précisez pas de découpage, la synchronisation suit le réglage par défaut de la base cible.

  6. Fréquence : manuelle (bouton uniquement) ou automatique — quotidienne, hebdomadaire ou mensuelle. Astrolabe resynchronise alors tout seul à cette cadence (vous pouvez toujours lancer une sync à la main entre deux).

Cliquez Synchroniser : Astrolabe reflète l’état de la source dans la base (vraie synchronisation miroir) :

  • ajouts / modifications → (ré)indexés par external_id. Un document n’est ré-embeddé que si son contenu a changé (empreinte) → les relances sont peu coûteuses ;
  • suppressions → les documents de ce connecteur disparus de la source sont supprimés de la base (réconciliation). Garde-fou : si la source ne renvoie aucun enregistrement (auth cassée, mauvaise config), rien n’est supprimé — le miroir n’est jamais vidé par erreur.

Seuls les documents issus de ce connecteur sont concernés : vos documents ajoutés à la main ou synchronisés depuis une autre source ne sont jamais touchés. La synchronisation est gratuite hormis l’embedding des documents (re)indexés (facturé sur la clé choisie).

// exemple de config `sync` (champ de la connexion, via l'API ou pré-rempli au portail)
{
"operation": "list_records",
"args": { "table": "Entreprises" },
"target_kb": "crm-airtable",
"map": {
"external_id": "id",
"title": "fields.Nom",
"date": "fields.Créé le",
"url": "https://airtable.com/appXXX/{id}",
"facets": { "ville": "fields.Ville", "statut": "fields.Statut" }
},
"chunking": "ai", // "simple" | "ai" | "whole" ; absent = défaut de la base cible
"chunk_model": "mistral-large", // (mode ai) modèle de découpage
"chunk_size": 1000, // (mode simple) taille cible des extraits, 200-6000
"key": "<token de clé>", // (optionnel) clé portant la conso ; défaut = clé du compte
"schedule": "daily" // "manual" (défaut) | "daily" | "weekly" | "monthly"
}

Fraîcheur : une synchronisation planifiée (schedule) se rafraîchit une fois par jour / semaine / mois. Pour une donnée qui doit être à la seconde, préférez le connecteur comme outil de l’agent (interrogation en direct).

Une configuration de connecteur est portable : vous pouvez l’exporter pour la partager (avec un collègue, entre deux comptes, ou pour la versionner) puis la réimporter ailleurs.

  • Exporter : sur la carte d’un connecteur, le bouton Exporter télécharge un fichier <slug>.connection.json. Il contient l’URL de base, le type d’auth, les opérations, la description, le schéma et la configuration de recherche, mais jamais le secret (clé/token). Pour oauth2, authorize_url/token_url/scopes (structurels) sont exportés, mais jamais client_id/client_secret ni les tokens obtenus. Côté API, un simple GET /v1/connections/{slug} renvoie la même configuration (le secret n’est jamais exposé).
  • Importer : le bouton Importer (en haut de la section) lit un fichier .json et pré-remplit la modale de création. Comme le secret n’est jamais inclus dans un export, vous ressaisissez votre clé avant de créer le connecteur. Côté API, postez le fichier sur POST /v1/connections en ajoutant le champ credential.

Le format tolère aussi une configuration écrite à la main : seul base_url est obligatoire.

  • Non-streaming : comme tout mode agentique, la réponse arrive en une fois (stream: true ignoré).
  • Gratuit : l’appel à votre API n’est pas facturé en plus (seuls les tokens du modèle le sont).
  • Sécurité : les réponses de votre API sont traitées comme des données, jamais comme des instructions. Les URL privées/loopback sont bloquées (garde SSRF) et les réponses sont bornées.
  • Souveraineté : une connexion vers votre API hébergée en UE garde les données dans un pipeline européen. Router vers un modèle cloud reste soumis à l’opt-in habituel.