🔗 Integrar LLMs con tus sistemas corporativos (CRM, ERP, APIs)
Un manual técnico, con arquitecturas reales y patrones probados, para llevar modelos de lenguaje a producción dentro del tejido empresarial.
Introducción: del prototipo a la fábrica
Los LLMs (Modelos de Lenguaje de Gran Tamaño) ya no viven solo en demos. Cuando se conectan a tus sistemas —CRM, ERP, catálogos de productos, data warehouses, APIs internas— dejan de ser generadores de texto y se convierten en interfaces universales para procesos. El reto no es “hablar bonito”, sino operar con garantías: seguridad, auditoría, latencia, costos y trazabilidad. Este post es una guía de ingeniería para integrar LLMs de forma robusta y mantenible, con patrones, anti‑patrones, fórmulas de capacidad y ejemplos de arquitectura.
1) Patrones de integración que sí funcionan 🧩
Los LLMs no “se enchufan” sin más; se orquestan. Estos son los cuatro patrones base, normalmente combinados:
| Patrón | Idea | Cuándo usar | Coste/Ctx | Riesgos |
|---|---|---|---|---|
| RAG (Retrieval‑Augmented Generation) | Recuperar conocimiento interno y dárselo al LLM | FAQs, políticas, catálogos, tickets | Medio (embedding + context) | Knowledge drift si el índice no se refresca |
| Function/Tool Calling | El LLM decide llamar funciones (APIs) con argumentos bien tipados | Integrar CRM/ERP/servicios; workflows | Bajo/Medio | Validación de entradas/salidas |
| Program‑Aided (PAL/LCEL) | El LLM genera código/consultas que se ejecutan de forma segura | Análisis, SQL, transformaciones | Medio | Sandbox, timeouts |
| Fine‑tuning/Adapters | Especializar el modelo con tus datos etiquetados | Estilo, formatos, extracción | Alto | Gobernanza de datos, sobreajuste |
Regla empírica: RAG + Tool Calling cubre 80% de casos de negocio sin tocar los pesos del modelo.
2) Arquitectura de referencia por capas 🏗️
Piensa en cinco capas horizontales:
[Experiencias] ─ Chat, Copilotos, Slack/Teams, Web, Móvil
│
[Orquestación] ─ Flujos, agentes, tool-calling, control de prompts
│
[Conocimiento] ─ RAG, vectores, catálogos, features, caches
│
[Integración] ─ Conectores CRM/ERP, OData/REST, colas (Kafka/SQS)
│
[Plataforma] ─ LLM API, seguridad, observabilidad, coste, cumplimiento
Componentes clave:
- Gateway de IA: rate‑limit, autenticación, firma de peticiones, budget de tokens.
- Router de modelos: elige el modelo según tarea/coste/latencia.
- Policy Engine: redacciones seguras (PII), máscara de datos, guardrails.
- Observabilidad: trazas por conversación, tokens, latencia por etapa, hallucination score.
- Feature Store: señales de negocio (rol, región, LTV) para prompt conditioning.
3) Conectar CRM/ERP/APIs sin dolor (y sin perder el control) 🔌
CRM (Salesforce, Dynamics, HubSpot)
- Mecanismo: OAuth2 + REST/GraphQL; webhooks para eventos (lead creado, oportunidad actualizada).
- Buen patrón: exponer un “Facade API” con operaciones de alto nivel (ej.:
create_opportunity,find_contact_by_email). El LLM llama a funciones semánticas, no a CRUD disperso. - Idempotencia: usa requestId y upsert para evitar duplicados.
ERP (SAP, Oracle, Dynamics 365 FO)
- Mecanismo: OData/REST + colas para procesos largos (ATP, MRP, facturación).
- Buen patrón: Command Bus (ej.:
ReserveInventory,PostInvoice) con estados (PENDING → RUNNING → DONE/FAILED). El LLM consulta el estado, no espera bloqueado.
APIs internas
- Contrato: OpenAPI/JSON Schema versionado. El tool calling usa estos esquemas como fuente de verdad.
- Seguridad: mTLS, auditing en tabla de
ai_invocationsconactor,function,args_hash.
Mantén a los LLMs fuera de la red plana del ERP. Mediante un API Gateway y colas, reduces blast‑radius y latencia percibida.
4) Prompts como contratos: JSON, esquemas y validadores 📜
El prompt es un contrato: debe producir formas verificables, no solo textos bonitos. Úsalo con JSON Schema y validación estricta:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "CreateOpportunity",
"type": "object",
"properties": {
"account_id": {"type": "string"},
"name": {"type": "string", "minLength": 3},
"amount": {"type": "number", "minimum": 0},
"close_date": {"type": "string", "format": "date"},
"stage": {"type": "string", "enum": ["Prospecting","Proposal","Closed Won","Closed Lost"]}
},
"required": ["account_id","name","amount","close_date","stage"],
"additionalProperties": false
}
Y el system prompt que lo acompaña:
Eres un asistente de ventas. Cuando el usuario pida crear una oportunidad,
produce EXCLUSIVAMENTE un JSON válido para el esquema CreateOpportunity.
No añadas comentarios ni texto extra.
Truco: valida el JSON del LLM con tu propio validador. Si falla, re‑pregunta al modelo con el error del validador.
5) RAG que no se rompe: indexación, contexto y frescura 📚
- Chunking semántico (tamaño dinámico por puntuación de cohesión) y metadatos (sistema, región, vigencia).
- Embedding por dominio: no mezcles políticas legales con catálogos de precios en el mismo índice.
- Frescura: re‑indexa mediante CDC (change data capture) y marcas
valid_from/valid_to. - Context Builder: selecciona pasajes por relevancia + diversidad para evitar redundancia.
Latencia del RAG = t_embedding_lookup + t_db + t_merge_context. Mide cada término.6) Orquestación y agentes, sin convertir tu SI en un zoo 🤹
- Usa un State Machine explícito (p. ej., orquestador o workflow engine) con pasos:
parse → retrieve → decide → act → verify → respond. - Agentes especializados: SalesAgent, InventoryAgent, BillingAgent. Un Router decide quién lleva la conversación.
- Verificación: self‑consistency (N muestras, votación) solo para pasos críticos (no en cada turno).
Diagrama simplificado:
User → Chat API → Router → (SalesAgent | InventoryAgent | BillingAgent)
│ │ │
Tool-Call RAG + API ERP Command Bus
│ │ │
Validator Guardrails Audit Log
7) Seguridad, cumplimiento y privacidad 🔒
- PII/PCI: redacción y tokenización antes de salir a un proveedor externo.
- Política de datos: listas de columnas prohibidas en prompts,
denylista nivel de feature. - Firmas de solicitud:
HMAC(client_key, body)ynoncepara evitar replay. - Principio del mínimo privilegio: tokens de acceso por capability, p. ej.
crm.opportunity.create. - Registro inviolable: append‑only en
ai_audit_logcon hash encadenado.
Para jurisdicciones estrictas, usa LLMs en región y opta por aislamiento (VPC/privado) cuando el dato no pueda salir.
8) Observabilidad y evaluación: lo que no mides, te mide 📈
Métricas mínimas por turno de chat:
tokens_prompt,tokens_completion,latency_ms_total,latency_ms_llm,latency_ms_tools.calls_rag,docs_in_context,tool_calls,tool_error_rate.groundedness_score(¿la respuesta cita el contexto?),format_valid(JSON OK?).
Panel sugerido:
| Métrica | Objetivo | Alertas |
|---|---|---|
| Latencia p95 | < 2.0 s | > 3.5 s durante 5 min |
| Tasa tool‑error | < 1% | > 3% |
| Ratio grounding | > 0.8 | < 0.6 |
| Costo / 1k peticiones | según modelo | desviación > 20% |
Evaluación offline: conjuntos de golden prompts con rubrics (exact, fuzzy, semantic) y playbooks de regresión cuando cambias modelo o prompt.
9) Latencia y costos: matemáticas operativas ⏱️💸
Presupuesto de tokens por turno:
$$
T_{total} = T_{sys} + T_{instr} + T_{ctx} + T_{out}
$$
Costo esperado por petición:
$$
C = \alpha \cdot (T_{prompt}) + \beta \cdot (T_{completion}) + C_{tools}
$$
Latencia esperada en pipeline con paralelización de herramientas (asumiendo independencia):
$$
L \approx L_{LLM} + \max(L_{tool_1}, L_{tool_2}, \dots, L_{tool_k}) + L_{merge}
$$
Heurística: mantén T_ctx ≤ 20% del window del modelo y usa respuestas en streaming para “sentir” rapidez aunque el backend tarde.10) Caching, dedupe y streaming ⚡
- Cache semántica: clave por intent + slots (ej.:
intent:quote_shipping|sku=A123|zip=94105). - Cache de herramientas: resultados de APIs “caras” (ej.: tarifas) con TTL corto y invalidador por evento.
- Respuesta híbrida: stream del draft + patch cuando llegan datos de herramientas lentas (UI tipo progressive disclosure).
11) Gestión de contexto y “memoria” 🧠
- Memoria a corto plazo: summary chain por conversación con compresión periódica.
- Memoria a largo plazo: índices vectoriales por entidad (
account,case,policy). - Context Builder con slots:
{persona, objetivo, restricciones, datos_recientes}.
Evita memorias globales no gobernadas. Todo lo que “recuerde” el sistema debe ser auditable.
12) Pruebas, despliegue y gates de seguridad 🚦
- Suites de prompts críticos (ventas, finanzas) con aserciones deterministas.
- Shadow traffic cuando cambias de modelo o prompt. Compara
exactness/latency/cost. - Canary con kill‑switch por feature flag.
- Data loss prevention (DLP) tests: inyecta PII ficticia y verifica redacción.
13) Tres arquitecturas reales (blueprints)
A) Copiloto de Ventas en CRM
Objetivo: resumir cuentas, registrar actividades, crear oportunidades.
UI (Web/Teams) → Chat API → Orquestador → RAG (cuentas, notas, emails)
│
Tool-Calling
│
CRM Facade (create_opportunity, log_call)
│
Audit + Metrics
Tool schema (ejemplo):
{
"name": "create_opportunity",
"description": "Crea una oportunidad en el CRM",
"parameters": {
"type": "object",
"properties": {
"account_id": {"type": "string"},
"name": {"type": "string"},
"amount": {"type": "number"},
"close_date": {"type": "string", "format": "date"},
"stage": {"type": "string"}
},
"required": ["account_id","name","amount","close_date","stage"]
}
}
Validación: tras el tool call, se verifica contra políticas (límites de descuento, territorios).
B) Asistente Financiero en ERP (orden a cobro)
Objetivo: responder disponibilidad/precio, generar proformas y disparar facturación.
Chat → Router → InventoryAgent (RAG: catálogo + políticas) → ERP Command Bus
│
PricingService (cacheable)
│
BillingService
Estados del comando:
CREATE TABLE erp_commands (
id UUID PRIMARY KEY,
type TEXT,
payload JSONB,
status TEXT CHECK (status IN ('PENDING','RUNNING','DONE','FAILED')),
created_at TIMESTAMP,
updated_at TIMESTAMP
);
El LLM obtiene el id y consulta progreso; la UI hace polling para mostrar “Factura emitida ✅”.
C) ChatOps con APIs internas
Objetivo: inspeccionar microservicios, reiniciar pods, abrir incidents.
- Guardrails: lista blanca de comandos (
restart_service,scale_deployment,open_incident). - Justificación obligatoria: el LLM debe aportar rationale y ticket de cambio.
- Simulación: primer paso en dry‑run, segundo paso requiere confirmación humana.
14) Anti‑patrones que queman presupuesto 🔥
- LLM como router de red: que el modelo descubra endpoints a pelo. Usa un Facade tipado.
- Prompt‑spaghetti: prompts duplicados en clientes. Centraliza en un Prompt Registry versionado.
- Contextos enormes: meter el data‑lake entero. Curaduría + RAG.
- Sin auditoría:
- no podrás explicar por qué se creó una orden.
- Implementa
ai_audit_logdesde el día 0.
- Validación laxa: aceptar JSON “casi válido”. Falla temprano y vuelve a intentar con el error explícito.
15) Construir vs. Comprar 🧭
| Dimensión | Construir (in‑house) | Comprar (plataforma) |
|---|---|---|
| Control | Máximo, ajustado a tus políticas | Alto, pero dentro del marco del vendor |
| Time‑to‑value | Mayor | Rápido |
| Coste a largo plazo | Menor si hay escala | Dependiente de licencias |
| Riesgo técnico | Alto (equipo necesario) | Medio (lock‑in) |
| Diferenciación | Alta | Media |
Estrategia híbrida: propio el “núcleo” (orquestación, políticas, prompts, métricas), comprado lo commoditizado (vectores, colas, UI base).
16) Ejemplo de implementación: FastAPI + Orquestador + Tool‑Calling
Estructura mínima:
/app
main.py # API de chat
orchestrator.py # state machine
tools.py # funciones (CRM, ERP)
policies.py # validaciones, guardrails
prompts/
system.md
tools.py (fachada tipada):
from pydantic import BaseModel, Field
from datetime import date
class CreateOpportunity(BaseModel):
account_id: str
name: str
amount: float = Field(ge=0)
close_date: date
stage: str
async def create_opportunity(args: CreateOpportunity, auth) -> dict:
payload = args.model_dump()
# Llama a tu CRM Facade
res = await crm_client.post("/opportunities", json=payload, headers=auth)
return {"id": res["id"], "status": "created"}
orchestrator.py (máquina de estados simplificada):
from enum import Enum
class Step(Enum):
PARSE = 1
RETRIEVE = 2
DECIDE = 3
ACT = 4
VERIFY = 5
RESPOND = 6
async def run_turn(state, user_msg):
state.metrics.start()
intent, slots = await parse_intent(user_msg)
ctx = await retrieve_context(intent, slots)
decision = await decide(intent, slots, ctx)
result = None
if decision.tool:
args = await enforce_schema(decision.tool_schema, decision.args)
result = await call_tool(decision.tool, args)
await verify(result)
reply = await generate_reply(intent, ctx, result)
state.metrics.stop()
audit_log(state, intent, decision, result)
return reply
main.py (FastAPI):
from fastapi import FastAPI, Depends
from orchestrator import run_turn
app = FastAPI()
@app.post("/chat")
async def chat(msg: dict, user=Depends(auth)):
reply = await run_turn(get_state(user), msg["text"])
return {"reply": reply}
17) Diseño de UI: velocidad percibida y confianza 🎛️
- Streaming con partial reasoning: primero una “respuesta breve”, luego detalles.
- Trazabilidad visible: “Usé: Política de descuentos v3, Catálogo 2025Q4, Pedido #8123”.
- Controles de riesgo: botones “Revisar”/“Solicitar aprobación” con reglas por monto/impacto.
18) Checklist de producción ✅
- Threat model completado y mitigaciones implementadas.
- Guardrails: PII redactada, denylists, validadores estrictos.
- Observabilidad: dashboards, tracing, sampling de conversaciones.
- RAG: índices actualizados por CDC; SLAs de frescura definidos.
- Tooling: facades tipadas, colas para procesos largos, idempotency keys.
- Costo: presupuesto de tokens y alarmas por desviación.
- Evaluación: golden sets y pruebas de regresión.
- Gobernanza:
ai_audit_log, retención y acceso por rol.
🧭 Epílogo: la interfaz universal
Integrar LLMs con tus sistemas no es magia, es ingeniería con lenguaje. El modelo pone la conversación; tú pones las reglas, datos y procesos. Cuando el lenguaje se convierte en API, el negocio adquiere una nueva prótesis cognitiva: preguntar es invocar, explicar es ejecutar. Y como toda prótesis poderosa, exige higiene: medir, auditar, validar. El resto es iteración: pequeños pasos, buenas trazas y la paciencia de quien despliega fábricas, no demos.
Recursos sugeridos (neutros y atemporales)
- Patrones de RAG, tool‑calling y agentes en papers y repositorios de referencia.
- Documentación de tus CRMs/ERPs (OAuth2, OData, webhooks, límites de uso).
- Guías de threat modeling (STRIDE), privacy by design y auditoría de ML.
Mantén este documento vivo. Cada cambio de modelo, prompt o conector debe pasar por las mismas puertas de seguridad y observabilidad.