Odoo guarda los datos de los que dependen la mayoría de las preguntas de negocio: clientes, pedidos, stock, facturas, pagos. Un asistente de IA que puede leer esos datos y actuar sobre ellos responde a "¿Dónde está el pedido del cliente X?" o "¿Qué facturas llevan más de 60 días vencidas?" en segundos en lugar de minutos de clics. Desde Odoo 19, la forma más limpia de conectar un asistente así es la nueva API JSON-2. Este artículo muestra la arquitectura que uso: autenticación, un usuario de integración dedicado, diseño de herramientas, exponer Odoo mediante el Model Context Protocol y las barandillas que impiden que un agente cause daños.

Por qué JSON-2 es la API sobre la que construir

Odoo 19 introdujo la API externa JSON-2: haces un POST con un cuerpo JSON a /json/2/<model>/<method> con una clave de API como token bearer y recibes en JSON el valor de retorno del método (Odoo: external JSON-2 API). Los endpoints antiguos XML-RPC y JSON-RPC (/xmlrpc, /xmlrpc/2, /jsonrpc) están obsoletos y está previsto eliminarlos en Odoo 22, en otoño de 2028 (Odoo: external RPC API). Las integraciones nuevas deberían usar JSON-2 desde el primer día.

Dos consecuencias prácticas:

  • Planifica las licencias. El acceso a la API externa solo está disponible en los planes Custom de Odoo, no en One App Free ni en Standard.
  • Planifica las actualizaciones. Si estás en Odoo 17 o 18 con integraciones basadas en RPC, migrarlas a JSON-2 forma parte de tu próximo proyecto de actualización.

Autenticación: claves de API y un usuario dedicado

JSON-2 usa claves de API enviadas en la cabecera Authorization. Las claves se crean por usuario en Preferencias → Seguridad de la cuenta → Nueva clave de API, requieren una descripción y una duración y no pueden durar más de tres meses, así que las integraciones de larga duración deben rotarlas (Odoo: API keys). Odoo también ofrece métodos para generar y revocar claves por programa, lo que permite automatizar la rotación.

La clave actúa con los permisos de su usuario. Esa es la decisión de diseño más importante:

  • Crea un usuario de integración dedicado para el agente, solo con los grupos de acceso que necesita: por ejemplo, lectura en Ventas e Inventario y sin acceso a Nóminas ni a la configuración de Contabilidad.
  • En asistentes de cara al usuario, actúa en nombre del usuario real siempre que sea posible, para que el asistente de un comercial vea exactamente lo que ve ese comercial. Las claves compartidas de "superusuario" convierten cada prompt injection en una brecha de datos.
  • Usa reglas de registro para limitar qué registros puede leer el usuario de integración, como una sola empresa en una configuración multiempresa.

Una llamada mínima a JSON-2

import requests

ODOO = "https://erp.example.com"
HEADERS = {
    "Authorization": f"bearer {API_KEY}",
    "X-Odoo-Database": "prod",
    "Content-Type": "application/json",
}

def odoo(model: str, method: str, **params):
    r = requests.post(f"{ODOO}/json/2/{model}/{method}",
                      json=params, headers=HEADERS, timeout=20)
    r.raise_for_status()
    return r.json()

overdue = odoo("account.move", "search_read",
    domain=[["move_type", "=", "out_invoice"],
            ["payment_state", "in", ["not_paid", "partial"]],
            ["invoice_date_due", "<", "2026-07-25"]],
    fields=["name", "partner_id", "amount_residual", "invoice_date_due"],
    limit=50)

Cada base de datos expone además una página /doc con los modelos, campos y métodos disponibles en esa instalación concreta, útil para escribir definiciones de herramientas sobre bases de datos personalizadas.

Diseñar herramientas para el agente

No le des al modelo una herramienta genérica de "llamar a cualquier método de Odoo". Envuelve la API en un pequeño conjunto de herramientas orientadas a tareas, con descripciones claras, parámetros acotados y resultados compactos:

Herramienta Llamadas a Odoo por detrás Notas
find_customer(query) res.partner search_read por nombre, correo, NIF Devuelve id, nombre, correo, comercial, crédito
get_order_status(order_ref) sale.order + albaranes y facturas relacionados Combina tres modelos en una sola respuesta
stock_level(product, warehouse) Lectura agrupada de stock.quant Cantidades disponibles frente a reservadas
overdue_invoices(customer_id?) account.move search_read Campos limitados, ordenados por vencimiento
draft_quotation(customer_id, lines) sale.order create en estado borrador Herramienta de escritura: solo crea un borrador, una persona confirma

Reglas que mantienen fiables las herramientas:

  1. Primero herramientas de lectura, después de escritura, y solo tras revisar los registros de uso real.
  2. Las escrituras crean borradores. El agente puede preparar un presupuesto, un pedido de compra o un correo; confirmar, contabilizar o enviar sigue siendo una acción humana.
  3. Valida los argumentos en el servidor, no solo en el esquema de la herramienta.
  4. Devuelve lenguaje de negocio. payment_state: "partial" está bien para el código; la herramienta puede traducirlo a "pagada parcialmente" para el modelo.

Exponer Odoo mediante MCP

Si varias aplicaciones de IA necesitan Odoo —un asistente de chat para ventas, un agente interno para finanzas, un asistente de programación para los desarrolladores—, envuelve estas herramientas en un servidor Model Context Protocol en lugar de reconstruirlas para cada aplicación. Así, cualquier host compatible con MCP puede usar las mismas herramientas con permisos y registros coherentes. El protocolo, el diseño de servidores y su modelo de seguridad se tratan en MCP para empresas.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("odoo")

@mcp.tool()
def get_order_status(order_ref: str) -> dict:
    """Status of a sales order by its reference (e.g. S00042): order state,
    delivery status with carrier tracking, and invoice/payment status."""
    order = odoo("sale.order", "search_read",
                 domain=[["name", "=", order_ref]],
                 fields=["state", "partner_id", "picking_ids", "invoice_ids"], limit=1)
    if not order:
        return {"error": f"No order {order_ref}. Check the reference format S00000."}
    return summarize_order(order[0])   # joins pickings and invoices into a compact dict

Casos de uso que compensan primero

  • Asistente de ventas: estado de pedidos, disponibilidad de stock, historial del cliente y borradores de presupuesto a partir de un correo.
  • Cobros: facturas vencidas por cliente con correos de recordatorio sugeridos para que los revise un contable.
  • Compras: productos por debajo del punto de pedido con borradores de pedidos de compra agrupados por proveedor.
  • Soporte: estado de pedidos y entregas para los agentes de soporte, combinado con respuestas de la base de conocimiento mediante recuperación, como se describe en RAG para empresas.
  • Preguntas de dirección: "Ingresos por categoría de producto este trimestre frente al anterior" mediante consultas agrupadas de solo lectura.

Barandillas

  • Mínimo privilegio para el usuario de integración, impuesto por los grupos y las reglas de registro de Odoo.
  • Confirmación humana para todo lo que contabilice, confirme, envíe o pague.
  • Registros de auditoría de cada llamada a herramienta con usuario, argumentos y tamaño del resultado.
  • Límites de frecuencia y timeouts para que un bucle del agente no sobrecargue los workers de Odoo.
  • Atención al prompt injection: los correos de clientes, las notas y las descripciones de productos son texto no confiable. Mi lista de comprobación está en seguridad de agentes de IA.
  • Rotación de claves: automatiza la renovación antes de que caduquen a los tres meses y revoca las claves de inmediato cuando se retire una integración.

Medir si el asistente ayuda

Trata la integración como cualquier funcionalidad de producto y mídela desde la primera semana del piloto:

  • Tasa de éxito de las tareas: proporción de preguntas respondidas correctamente o de acciones preparadas sin corrección, comprobada en una muestra de sesiones registradas.
  • Tiempo ahorrado: por ejemplo, minutos para responder a una pregunta sobre el estado de un pedido antes y después.
  • Tasa de errores de herramientas: llamadas fallidas o reintentadas por sesión, a menudo señal de descripciones poco claras o de permisos que faltan.
  • Tasa de corrección humana de los borradores: con qué frecuencia los presupuestos o pedidos de compra preparados por el agente necesitan cambios antes de confirmarse.
  • Carga sobre Odoo: llamadas a la API por minuto y tiempos de respuesta, para asegurarte de que el asistente no ralentiza a los usuarios.

Explico cómo construir un conjunto de pruebas a partir de preguntas reales en cómo evaluar aplicaciones LLM.

Guías relacionadas

Para extraer datos de facturas de proveedores y otros documentos hacia Odoo, consulta procesamiento de documentos con LLM.

Preguntas frecuentes

¿Funciona con Odoo 17 o 18? Esas versiones usan XML-RPC o JSON-RPC para el acceso externo. La arquitectura es la misma; cambia el transporte, y migrarás a JSON-2 cuando actualices.

¿Podemos usar las funciones de IA propias de Odoo? Las versiones recientes de Odoo incluyen capacidades de IA integradas en los planes Custom. Encajan bien dentro de las pantallas de Odoo; un agente externo tiene sentido cuando combinas Odoo con otros sistemas o necesitas tus propios workflows.

¿Es seguro dejar que una IA cree registros en nuestro ERP? Sí, con borradores y confirmación. El agente prepara y una persona aprueba.

¿Cuánto lleva una integración? Un asistente de solo lectura con cinco o seis herramientas suele llevar de dos a cuatro semanas, incluidos el usuario de integración, los registros y las pruebas con preguntas reales.

¿Qué modelo de lenguaje deberíamos usar? El patrón de integración es independiente del modelo. Elige según la calidad en tu propio conjunto de evaluación, el coste por tarea completada y las condiciones de tratamiento de datos; comparo las palancas de coste en optimización de costes de LLM.

¿Puede el agente trabajar en español? Sí. Los modelos de lenguaje actuales manejan bien el español; pasa el idioma del usuario en el context de la petición (por ejemplo, {"lang": "es_ES"}) para que Odoo devuelva traducidos los valores y nombres de los campos.

Fuentes

  1. Odoo. External JSON-2 API.
  2. Odoo. External RPC API (deprecated).
  3. Odoo. Pricing.
  4. Model Context Protocol. Specification, revision 2026-07-28.
  5. OWASP. Secrets Management Cheat Sheet.