Una tienda en la que el catálogo se lee en tiempo real, no se copia una vez y se olvida.
Construimos tiendas y, sobre ellas, la capa que suele faltar: el agente que responde al cliente lee el precio y el stock directamente de la tienda, en el momento de la pregunta, y se niega a inventar un precio no publicado.
Ya construidoSe poate verifica din exterior chiar acum, fără să ne întrebi pe noi. Punctul nostru de catalog livrat unui distribuitor răspunde 200 și spune „154 rezultate”; interfața publică a magazinului lui, interogată direct, întoarce antetul `x-wp-total: 154`. Aceeași cifră, două surse independente, verificat pe 06.09.2026. A doua implementare e integrată în platforma de asistenți: serviciul `storeCatalog.service.js` plus trei unelte pe care agentul le poate chema. Rezerva care trebuie spusă: acest al doilea traseu stă pe o ramură de dezvoltare (`feat/store-catalog-global`, `481cfa0`) și nu e încă unificat în trunchi — deci e livrat pentru clienții pe care i-am conectat, nu pornit implicit pentru toți.
La mayoría de las “integraciones de catálogo” en realidad son una exportación. Alguien descarga los productos una vez, los pega en un archivo, y desde entonces el agente que habla con el cliente lee una foto vieja de la tienda. Funciona impecablemente hasta el primer cambio de precio o el primer producto agotado —y entonces se equivoca con convicción, lo cual es peor que callar.
Nosotros leemos la tienda en el momento de la pregunta. Para tiendas en WooCommerce existe una interfaz pública —Store API— que devuelve productos, precios y disponibilidad sin claves, sin cuenta, sin plugin instalado. La dirección es `/wp-json/wc/store/v1/products`, la pedimos con 100 productos por página, con un tiempo máximo de espera de 20 segundos, y sabemos por el encabezado de la respuesta cuántas páginas hay, en vez de adivinar. La primera página la tomamos sola, el resto en paralelo.
La parte que separa una integración correcta de una que solo parece correcta es la traducción del precio. Store API no devuelve “129,90”; devuelve una cadena de cifras en unidades menores y, aparte, cuántos decimales tiene la moneda. Quien divide entre 100 por costumbre se equivoca en silencio con cualquier moneda que no tenga dos decimales. Y más importante: un precio cero no significa gratis, significa no publicado. En nuestro caso, cero se convierte en “precio a consultar — se confirma con colegas”, y el agente recibe la instrucción explícita de no inventar. Se ve en la respuesta pública del punto de catálogo, ahora mismo.
Encima del catálogo van las demás piezas, cada una con su estado real: carrito y envío del pedido al sistema de gestión del restaurante o la tienda, pago mediante la interfaz MAIB para comerciantes o mediante Stripe, recuperación de carritos abandonados, seguimiento del estado del pedido con sincronización cada 15 minutos. Donde no tenemos una integración funcional —y hay casos así—, escribe abajo exactamente cuál.
Qué incluye
El trabajo, por componentes
Catálogo leído en tiempo real, sin claves y sin plugin
Para WooCommerce usamos Store API, la interfaz pública de la tienda: `/wp-json/wc/store/v1/products`, 100 productos por página, tiempo máximo de espera de 20 segundos, un identificador de cliente propio en el encabezado y aceptación exclusiva del código 200. Leemos el número de páginas del encabezado `x-wp-totalpages`, y el total de productos de `x-wp-total` —no paginamos hasta agotarlo. La primera página se toma sola, el resto en paralelo, con un límite de 30 páginas. No se instala nada en la tienda y no se nos dan claves de comerciante.
Precio traducido correctamente, y cero tratado como no publicado
Store API devuelve el precio como una cadena en unidades menores, más el número de decimales de la moneda. Dividimos entre diez a la potencia de ese número, no entre 100 fijo — de otro modo cualquier moneda con otro número de decimales sale mal y nadie lo nota. Cero pasa a `null`, y en la respuesta aparece «precio a consultar — se confirma con colegas», junto con la instrucción explícita dada al agente de no inventar y de pedir la confirmación de un colega. El precio sale en dos formas a la vez: texto listo para mostrar en la interfaz y número para la lógica de fondo.
Tres herramientas que el agente puede llamar
En la plataforma de asistentes, el catálogo se expone como tres herramientas integradas — búsqueda por palabras, coincidencia por un aparato o un caso de uso, y obtención de un producto por identificador. El agente las ve con los nombres `catalog_cauta`, `catalog_potrivire` y `catalog_produs`, cada una con sus parámetros declarados. Cuando la plataforma de la tienda no es la esperada o falta la dirección, la herramienta se niega explícitamente en lugar de devolver una lista vacía que se interpretaría como «no tenemos el producto».
Las palabras de enlace no estropean el resultado
“Filtro de agua” buscado literalmente coincide con todo lo que contiene “de”. En el punto de catálogo entregado y en la búsqueda del widget vocal cortamos la lista de palabras vacías — `y`, `o`, `de`, `desde`, `a`, `con`, `sobre`, `en`, `para` — y, si después del corte no queda nada útil, volvemos a las palabras de más de dos letras. La coincidencia parcial tiene umbral: un producto entra en los resultados solo si alcanza al menos la mitad de las palabras restantes.
Cuando la tienda no tiene interfaz, leemos la página
No toda tienda tiene Store API. Para el resto tenemos un extractor que abre las páginas de listado y lee sus tarjetas de producto, con presupuesto escrito en código: máximo 20 páginas de listado, 200 productos, 24 páginas de detalle, 50.000 caracteres de HTML por página, 5 segundos por petición y un límite de 45 segundos para toda la operación. Lee primero los datos estructurados de tipo producto de la página, luego las tarjetas, luego los metadatos de compartición — en ese orden, porque la primera fuente es la que la tienda escribió intencionalmente.
Frescura con límites escritos, no con esperanza
El catálogo se mantiene en memoria 10 minutos por tienda, y las peticiones simultáneas para la misma tienda se fusionan en una sola, para que diez clientes que preguntan al mismo tiempo no produzcan diez descargas. En el punto público de catálogo, la respuesta también lleva instrucción de caché para la red de distribución: 5 minutos fresco, otros 10 minutos servido viejo mientras se refresca en segundo plano. El número de resultados devueltos está limitado a 20, con valor predeterminado 6.
Pedido, carrito y conexión con el sistema de gestión
El carrito, el envío del pedido y su entrega al sistema de gestión del cliente son funciones separadas, no un formulario. También existe la recuperación de carritos abandonados, el pedido por conversación y el seguimiento del estado del pedido, con dos tareas programadas que se ejecutan cada 15 minutos — una sincroniza el resultado de los pedidos, la otra completa los estados del sistema de gestión en una ventana de dos días atrás y un día adelante.
Pagos: qué funciona y qué no
Funcional y en código: la interfaz MAIB para comerciantes — token, luego solicitud de pago, con las credenciales de cada tienda leídas de la base de datos y la función activada explícitamente — y Stripe, con la suma convertida en unidades menores y el cobro guardado en el registro. Lo que NO funciona, para que no haya sorpresas: Paynet, Netopia y mobilPay no tienen implementación, y el código se niega explícitamente cuando se solicitan. El trayecto de Moldindconbank es un esqueleto que devuelve error sin credenciales. Los tomamos en el proyecto como trabajo, no como integración existente.
El agente no inventa cuando cae la red
Si la consulta a la tienda falla, la herramienta no devuelve una lista vacía — devuelve un mensaje que le dice al agente que no formule una respuesta sobre el catálogo. La diferencia es importante: una lista vacía se traduce en «no tenemos», y un «no tenemos» dicho erróneamente pierde un pedido con la misma seguridad que un precio incorrecto.
Qué aspecto tiene
El recorrido, paso a paso.
01
Verificación de la tienda, antes de cualquier promesa
Consultamos la interfaz pública con una sola petición, con tiempo máximo de espera de 15 segundos, y leemos cuántos productos tiene del encabezado. Con esa respuesta sabemos si el trayecto vivo es posible, cuántos productos hay y cuán completa es la información de precio. Si la tienda no responde, lo decimos antes de la oferta, no durante la implementación.
02
Conexión del catálogo y primer paso por los precios
Entregamos la conexión, además de un recorrido por los productos con precio cero o faltante — casi siempre son productos reales, no errores, y la forma en que el agente los trata es una decisión de la tienda, no nuestra. También entregamos el texto exacto con el que el agente se niega a dar un precio no publicado.
03
Las herramientas del agente y sus límites
Montamos la búsqueda, la coincidencia y la obtención de un producto, cada una con el número máximo de resultados establecido juntos. Aquí se escriben también los sinónimos propios de la tienda: cómo llama el cliente a un producto frente a cómo lo nombra el catálogo. Sin este paso, la búsqueda es técnicamente correcta y prácticamente inútil.
04
El pedido, el pago y la conexión con la gestión
Se construyen en este orden, y cada pieza entra solo después de verificar el acceso real al sistema del otro extremo. Para pagos se parte solo de un proveedor para el que tenemos implementación funcional; el resto se trata como trabajo nuevo, con el riesgo indicado antes, no como una casilla marcada en la oferta.
05
La entrega, con la lista de faltantes
Entregamos las direcciones, las configuraciones, los límites escritos en código y la lista de lo que no está cubierto. Por ejemplo: el punto público de catálogo entregado no tiene tiempo máximo de espera en la solicitud hacia la tienda — si la tienda responde muy lento, la solicitud se prolonga. Es una falta real; la ponemos en la lista de entrega y en el plan de reparaciones, no en una nota interna.
Magazinul, agentul care răspunde, sistemul de gestiune și furnizorul de plată — patru sisteme separate, cu o singură sursă de adevăr pentru preț: magazinul, citit în momentul întrebării.
Los datos
Qué tocamos, dónde están y cuánto se quedan
Las preguntas que hace cualquiera que tenga un delegado de protección de datos — hechas aquí antes de que las haga él.
Datos de catálogo
Nombre, descripción breve, precio actual y precio de lista, disponibilidad, imagen, categoría y la dirección del producto — todo leído desde la interfaz pública de la tienda, que lo publica de todos modos para cualquier visitante. No copiamos la base de datos de la tienda y no pedimos claves de comerciante. Se quedan con el cliente; nosotros los leemos a solicitud.
Dónde se almacena y cuánto tiempo
El catálogo se mantiene en la memoria del proceso 10 minutos por tienda y desaparece al reiniciar — no existe una copia persistente de él en nosotros. En el punto público de catálogo, la red de distribución lo mantiene 5 minutos fresco y 10 minutos como versión antigua mientras se actualiza. Un export congelado, cuando es la única opción técnica, se marca explícitamente como instantánea con fecha, no como fuente viva.
Datos de la conversación y del pedido
Lo que pregunta el cliente y lo que pide pasan por la plataforma de conversación y, cuando corresponde, al sistema de gestión de la tienda. Quién tiene acceso, cuánto tiempo se conserva y qué se elimina se establecen por proyecto, con el registro de tratamientos escrito antes del inicio, no después del primer incidente.
Las credenciales de pago
Las credenciales de comerciante se guardan en la base de datos de la plataforma, por tienda, y se leen solo cuando la función de pago se activa explícitamente para esa tienda. No llegan a la página pública y no pasan por la conversación. La configuración de la cuenta de comerciante la hace el titular de la cuenta, no nosotros.
Lo que no tocamos
No tomamos datos de tarjeta. No pedimos acceso de administrador a la tienda para leer el catálogo — la interfaz usada es pública. Cuando un proyecto realmente requiere acceso privilegiado, se pide por separado, con un propósito escrito, y no se guarda «por si acaso».
Un caso
Un catálogo de 154 productos, leído en el momento de la pregunta
La situación
Un distribuidor de café y agua en Chișinău, con tienda en WooCommerce y agentes que responden a los clientes por texto y por teléfono. El catálogo cambia a menudo; una lista copiada una vez queda incorrecta en unos días, y un precio equivocado dicho por teléfono no se retira.
Qué construimos
Montamos un punto de catálogo separado, que interroga la interfaz pública de la tienda: 100 productos por página, el número de páginas leído del encabezado, la primera página tomada sola y el resto en paralelo, límite de 30 páginas. El precio se traduce desde unidades menores según el número de decimales declarado por la tienda; cero se convierte en «precio a consultar — se confirma con los compañeros», con una instrucción escrita para el agente de no inventar. La búsqueda corta las palabras de enlace y exige que un producto alcance al menos la mitad de las palabras restantes antes de aparecer en los resultados. La respuesta se mantiene 10 minutos en memoria y 5 minutos en la red de distribución, con otros 10 minutos servidos obsoletos mientras se actualiza. Los agentes de voz lo llaman como un simple punto web, no como una integración especial.
Qué salió
Verificado el 06.09.2026, en dos solicitudes independientes: el punto de catálogo responde «154 resultados» y lista el primer producto con precio y disponibilidad, y el segundo con «precio a consultar — se confirma con los compañeros»; consultada directamente, la interfaz de la tienda devuelve `x-wp-total: 154`. La misma cifra de dos fuentes que no se conocen entre sí — esa es la verificación, no nuestra declaración.
Qué no dice el caso
El punto de catálogo entregado no tiene tiempo máximo de espera en la solicitud a la tienda: si la tienda responde muy lentamente, la solicitud se prolonga en lugar de fallar limpiamente. Es una carencia real, detectada al releer el código, y está en la lista de reparaciones — no en la lista de funciones. Por separado: el filtro de palabras vacías descrito arriba está activo en el punto entregado y en la búsqueda del widget de voz; en la variante integrada en la plataforma todavía no está portado, así que allí una búsqueda con muchas palabras de enlace da resultados más amplios.
Preguntas
Lo que nos pregunta la gente antes de llamar
¿Qué significa «catálogo vivo» y cómo verifico que no es una frase vacía?
Significa que el agente lee la tienda en el momento de la pregunta. Se verifica en dos solicitudes, sin nosotros: nuestro punto de catálogo para un distribuidor responde «154 resultados», y la interfaz pública de su tienda, consultada directamente, devuelve en el encabezado `x-wp-total: 154`. La misma cifra, dos fuentes independientes, en la misma fecha. Un catálogo copiado una vez no puede hacer eso — se desincroniza con el primer cambio.
¿Tengo que darles claves o acceso a la tienda?
Para la lectura del catálogo en WooCommerce, no. Store API es la interfaz pública de la tienda: los mismos datos que ve cualquier visitante, servidos en un formato legible por programa, sin clave de comerciante y sin plugin instalado. El comentario está escrito incluso en nuestro código, para que no se pierda. Pedimos acceso privilegiado solo donde la función realmente lo requiere — por ejemplo, al enviar pedidos al sistema de gestión — y entonces con un propósito escrito.
¿Qué pasa con los productos sin precio?
Se tratan como no publicados, no como gratuitos. En la interfaz de la tienda, un precio ausente llega como cero, y una integración ingenua lo muestra como «0 MDL». En la nuestra, cero se convierte en «precio a consultar — se confirma con los compañeros», y el agente recibe la instrucción explícita de no inventar una cifra y de pedir la confirmación de una persona. Se ve en la respuesta pública: el segundo producto de la lista aparece exactamente así.
¿Qué tan fresco es el precio, concretamente?
Como máximo 10 minutos de antigüedad a nivel de la plataforma, por tienda, y las solicitudes simultáneas para la misma tienda se fusionan en una sola descarga. En el punto público de catálogo, la red de distribución sirve durante 5 minutos la versión fresca y durante otros 10 minutos la versión antigua, mientras la actualiza en segundo plano. Los valores son configurables por proyecto; están escritos como variables, no ocultos.
Mi tienda no está en WooCommerce. ¿Qué hacen?
Depende de lo que exponga. Si tiene una interfaz propia, la leemos como cualquier otra. Si no tiene nada, tenemos un extractor que abre las páginas de listado y lee las tarjetas de producto, con un presupuesto escrito en código: 20 páginas, 200 productos, 5 segundos por solicitud, 45 segundos de plazo. Lee primero los datos estructurados de la página, luego las tarjetas, luego los metadatos de compartición. Es una solución de reserva honesta, no equivalente: una tienda que cambie su tema puede romper el extractor, y una interfaz no.
¿Qué pagos pueden integrar ahora mismo?
Funcional y en código: la interfaz MAIB para comerciantes — obtención de token, luego solicitud de pago, con las credenciales de cada tienda leídas desde la base de datos y la función activada explícitamente — y Stripe, con el importe convertido en unidades menores y el cobro guardado en el registro. Lo que no es funcional, dicho antes del contrato: Paynet, Netopia y mobilPay no tienen implementación, y el código rechaza explícitamente cuando se solicitan; la ruta de Moldindconbank es un esqueleto que devuelve error sin credenciales. Cualquiera de ellos se puede construir, pero entra como trabajo nuevo, con su riesgo.
¿Puede el agente inventar un producto que no tengan?
Puede, si no se lo impides — y de eso nos ocupamos nosotros. Tres barreras: el precio no publicado viene con una instrucción escrita de no inventar; la plataforma incorrecta o la falta de dirección hacen que la herramienta rechace explícitamente, no que devuelva una lista vacía; y la caída de la red devuelve un mensaje que le dice al agente que no formule una respuesta sobre el catálogo. La diferencia entre «lista vacía» y «no pude leer» es la diferencia entre un pedido perdido y uno aplazado con una frase.
¿Por qué importa quién divide entre 100?
Porque la interfaz no envía «129,90». Envía una cadena de cifras en unidades menores y, por separado, cuántos decimales tiene la moneda. Dividir entre 100 es correcto para las monedas con dos decimales y silenciosamente incorrecto para las demás — nadie recibe error, solo cifras malas. Nosotros dividimos por diez a la potencia del número declarado por la tienda. Es una línea de código, y es exactamente el tipo de línea en la que se ve si alguien leyó la documentación o adivinó.
¿Qué no asumes?
No recogemos datos de tarjeta ni configuramos la cuenta del comerciante en lugar del titular. No garantizamos que un extractor de páginas resista un cambio de tema de la tienda — por eso preferimos la interfaz cuando existe. No prometemos aumentos de ventas; lo que sí podemos mostrar es que la cifra dicha por el agente coincide con la cifra de la tienda, en la misma fecha. Y no presentamos como integración algo que en el código es un esqueleto: la lista de arriba dice cuáles son.
En qué se basan las afirmaciones anteriores (18 fuentes)
16 de ellas son código y archivos de nuestros repositorios. No publicamos su nombre ni la línea: juntos, en una sola página, describirían con demasiada precisión cómo están construidos sistemas que no son solo nuestros. Los repasamos contigo, en el repositorio, a petición — la verificación sigue siendo posible, solo que se hace en una conversación.