Connecter un ERP d'entreprise à un agent d'intelligence artificielle a longtemps été synonyme de connecteurs XML-RPC verbeux, de gestion fragile de cookies de session ou de sérialisation positionnelle difficile à fiabiliser pour un grand modèle de langage (LLM). Avec l'introduction de l'API externe JSON-2 dans Odoo 19, l'architecture d'intégration change d'ère : chaque modèle et chaque méthode publique de l'ORM sont désormais accessibles via un contrat HTTP RESTful moderne, sans état (stateless) et conçu autour d'objets JSON nommés.
Cet article détaille comment brancher un agent IA sur Odoo via l'API JSON-2, quels sont les endpoints réellement accessibles, et surtout ce que l'on peut automatiser en toute sécurité en production.
Pourquoi l'API JSON-2 d'Odoo est idéale pour le tool calling des agents IA
Historiquement, les intégrations externes passaient par /xmlrpc/2/object (execute_kw) ou /jsonrpc. Pour un agent IA, ces protocoles posaient deux problèmes : l'obligation d'empiler des listes d'arguments positionnels ([[['is_company', '=', True]], {'fields': ['name']}]) sources d'erreurs de parenthésage, et l'absence de sémantique HTTP standard.
L'API JSON-2 résout ces limites grâce à quatre caractéristiques natives :
- Un adressage explicite par URL : Toutes les requêtes suivent le format
POST /json/2/<model>/<method>, où<model>désigne le nom technique de l'objet Odoo (par exempleres.partner,sale.order,account.move) et<method>la méthode ORM ou métier invoquée (search_read,read_group,create,write). - Une authentification Bearer sans session : La clé API personnelle générée dans le profil d'un utilisateur dédié est transmise dans l'en-tête standard
Authorization: Bearer <API_KEY>. Aucune gestion de cookiesession_idni jeton CSRF n'est nécessaire. - Un corps de requête exclusivement composé de paramètres nommés : L'agent envoie un dictionnaire JSON plat (
domain,fields,ids,vals_list,context), ce qui correspond exactement au format JSON Schema utilisé par le function calling des modèles IA modernes. - Une documentation auto-générée sur
/doc: Chaque instance Odoo expose son catalogue de modèles et de signatures sur l'endpoint/doc(disponible sur les plans Odoo Custom et les déploiements On-Premise / Odoo.sh).
Comment configurer la connexion technique étape par étape
1. Créer un compte de service au moindre privilège dans Odoo
Ne donnez jamais la clé API d'un administrateur système à un agent IA. Créez un utilisateur technique dédié (par exemple agent-ia@entreprise.ch), rattachez-le uniquement aux groupes de sécurité requis (lecture CRM, création de devis en brouillon, lecture analytique) et générez une clé API dédiée depuis Préférences → Sécurité du compte → Nouvelles clés API. En cas d'incident, cette clé est révocable instantanément sans impacter les collaborateurs humains.
2. Anatomie d'un appel HTTP vers /json/2/<model>/<method>
Chaque appel vers l'API JSON-2 requiert l'en-tête Authorization, le Content-Type: application/json; charset=utf-8 et, lorsque le serveur héberge plusieurs bases, l'en-tête X-Odoo-Database.
import os
import requests
ODOO_URL = os.environ["ODOO_BASE_URL"] # ex: https://erp.entreprise.ch
ODOO_DB = os.environ["ODOO_DATABASE"] # ex: entreprise_prod
ODOO_API_KEY = os.environ["ODOO_AGENT_API_KEY"] # Clé de l'utilisateur restreint
def call_odoo_json2(model: str, method: str, payload: dict) -> dict | list:
"""Exécute un appel sécurisé sur l'API JSON-2 d'Odoo."""
url = f"{ODOO_URL}/json/2/{model}/{method}"
headers = {
"Authorization": f"Bearer {ODOO_API_KEY}",
"Content-Type": "application/json; charset=utf-8",
"X-Odoo-Database": ODOO_DB,
"User-Agent": "21datas-agent-connector/1.0",
}
response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
return response.json()
# Exemple : rechercher les 5 opportunités CRM les plus importantes en Suisse
leads = call_odoo_json2(
model="crm.lead",
method="search_read",
payload={
"domain": [["type", "=", "opportunity"], ["probability", ">=", 50]],
"fields": ["name", "partner_id", "expected_revenue", "stage_id", "date_deadline"],
"order": "expected_revenue desc",
"limit": 5,
"context": {"lang": "fr_CH"},
},
)
Quels sont les endpoints accessibles via l'API JSON-2 ?
L'API JSON-2 n'expose pas une liste figée de routes codées en dur : elle expose dynamiquement toutes les méthodes publiques (@api.model, @api.model_create_multi, méthodes d'instance) autorisées par les règles d'accès (ir.model.access et ir.rule) de l'utilisateur appelant. Voici les endpoints fondamentaux à déclarer comme outils (tools) pour un agent IA :
| Endpoint JSON-2 | Paramètres clés du corps JSON | Rôle pour l'agent IA |
|---|---|---|
POST /json/2/<model>/search_read | domain, fields, limit, offset, order | Rechercher et lire des enregistrements filtrés en un seul aller-retour réseau. |
POST /json/2/<model>/read_group | domain, fields, groupby, lazy | Calculer des sommes, moyennes et comptages côté PostgreSQL sans saturer le contexte du LLM. |
POST /json/2/<model>/search_count | domain | Compter instantanément le volume de dossiers (ex. : factures en retard). |
POST /json/2/<model>/fields_get | attributes (string, type, relation, selection) | Permettre à l'agent d'inspecter dynamiquement le schéma et les champs personnalisés (x_studio_*). |
POST /json/2/<model>/create | vals_list, context | Créer un ou plusieurs enregistrements (piste CRM, devis brouillon, tâche projet). |
POST /json/2/<model>/write | ids, vals | Mettre à jour des champs précis sur des identifiants existants. |
POST /json/2/<model>/message_post | ids, body, message_type, subtype_xmlid | Publier un compte-rendu d'analyse ou une note interne directement dans le chatter Odoo. |
POST /json/2/sale.order/action_confirm | ids | Déclencher une transition de workflow métier (confirmation d'un devis en commande). |
Ce que l'on est vraiment capable de faire en production (et les pièges à éviter)
Au-delà de la démonstration technique, que peut-on réellement confier à un agent IA connecté à Odoo en production ? Notre retour d'expérience chez 21datas distingue clairement les automatisations à fort ROI immédiat et les opérations qui exigent une validation humaine.
1. Ce qui fonctionne avec une fiabilité supérieure à 95 % en autonomie
- Le pilotage analytique en langage naturel via
read_group: Un piège classique consiste à laisser l'agent appelersearch_readsur 25 000 lignes de factures (account.move.line) pour les additionner lui-même. Un LLM ne doit jamais faire d'arithmétique de masse dans sa fenêtre de contexte. En exposant un outil basé sur/json/2/account.move/read_groupou/json/2/sale.report/read_group, c'est PostgreSQL qui exécute l'agrégation exacte par mois, commercial ou axe analytique, et l'agent reçoit un tableau synthétique de 12 lignes parfaitement juste. - La qualification CRM et la préparation de devis (
crm.lead&sale.order) : Lorsqu'un e-mail client ou une demande issue du site arrive, l'agent vérifie si le client existe dansres.partner, recherche l'historique de ses tarifs dansproduct.pricelist, crée l'opportunité danscrm.leadet génère un devis complet à l'état brouillon (state = 'draft') danssale.order, avec les lignes d'articles (order_line) via les commandes ORM(0, 0, {...}). - Le triage support et la synthèse dans le chatter (
helpdesk.ticket&project.task) : L'agent lit le ticket entrant, consulte la base documentaire technique, vérifie le contrat d'abonnement actif du client et poste une proposition de réponse en note interne via/json/2/helpdesk.ticket/message_postpour faire gagner 80 % du temps au consultant support. - La saisie assistée des feuilles de temps (
account.analytic.line) : À partir d'un message Slack ou d'un calendrier, l'agent résout le projet et la tâche Odoo correspondants puis pré-remplit les imputations horaires des collaborateurs.
2. Les garde-fous indispensables : ce qu'il ne faut jamais laisser en exécution aveugle
Un agent IA connecté à un ERP manipule des données financières et légales. Trois règles d'ingénierie sont impératives :
- Interdire l'endpoint
unlinket la validation comptable directe : Le compte de service de l'agent ne doit jamais posséder le droit de suppression (unlink), ni le droit d'appeleraction_postsur une écriture comptable (account.move) ou un paiement (account.payment) sans validation humaine. L'agent crée la pièce à l'étatdraft, joint le justificatif PDF analysé et mentionne le comptable dans le chatter. - Encapsuler JSON-2 derrière des outils métiers typés (MCP / Tool Server) : Plutôt que de donner un outil générique
call_any_odoo_endpoint(model, method, body)au LLM, exposez des fonctions bornées commesearch_customer_invoices(),create_draft_quotation()oupost_internal_chatter_note()qui imposent des limites (limit <= 100) et valident les paramètres avec Zod ou Pydantic. - Gérer l'idempotence des écritures : Avant tout appel à
createsurres.partner,crm.leadousale.order, le connecteur vérifie l'existence d'une clé externe ou d'une référence unique afin qu'une relance réseau ne crée jamais de doublon dans l'ERP.
Vous souhaitez connecter votre instance Odoo à des agents IA gouvernés ou déployer une interface conversationnelle comme 21brain sur vos données ERP et votre entrepôt data engineering ? Prenez rendez-vous avec notre équipe ou contactez-nous.
in Data