El problema

No hacía falta un producto comercial, hacía falta una herramienta de uso familiar: sin cuentas, sin suscripciones, todo en local. El objetivo era fácil de enunciar y menos fácil de construir — escribir el nombre de un producto una sola vez y ver el mejor precio en cuatro plataformas distintas, cada una con su estructura, sus filtros, sus enlaces de afiliación.

La solución técnica más directa habría sido un scraper para cada sitio. La más robusta — y la que elegí — fue delegar la búsqueda en un modelo con acceso a la web en tiempo real.

Arquitectura de dos velocidades

El backend es FastAPI en Python, el frontend un HTML de página única que habla con localhost:8000. La parte interesante es cómo está dividida la búsqueda:

TareaCómo funciona
AmazonTarea de Gemini 2.0 Flash dedicada y separada (_search_amazon_via_ai), lista para pasar a la PA-API v5 oficial en cuanto esté disponible
AliExpress / eBay / TrovaprezziUna única llamada a Gemini 2.0 Flash con Google Search grounding (_search_others_via_gemini)
Paralelismoasyncio.gather lanza los dos grupos en executors separados
PersistenciaSQLite local (bivio.db), autocreado en el primer arranque

El detalle que más tiempo me hizo perder: Amazon tiene que quedar fuera del grupo "otros" incluso cuando la PA-API oficial está desactivada. Lo intenté, al principio, para simplificar el código — resultado: Gemini devolvía un array vacío para Amazon cada vez que se agrupaba junto con los otros tres. Dos tareas separadas, dos prompts separados, problema resuelto.

El truco de los enlaces de afiliado

Un problema que no esperaba: los enlaces de producto que devuelve Gemini en la respuesta a menudo están inventados — URLs con aspecto plausible que llevan a páginas 404 o a productos distintos. Google Search grounding ayuda a encontrar los resultados correctos, pero no garantiza que el enlace final sea real.

La solución fue dejar de confiar en los enlaces generados por el modelo y reconstruirlos yo mismo, en el backend, con una función única (_affiliate_url) que genera URLs de búsqueda reales con el tracking ya incluido:

  • Amazon: amazon.it/s?k={query}&tag=...
  • AliExpress: aliexpress.com/wholesale?SearchText={query}&tblci=... (no tracking_id, que parece correcto pero no lo es)
  • eBay: query string con campid y mkevt de la eBay Partner Network
  • Trovaprezzi: enlace de búsqueda directo, sin afiliación activa

Gemini sirve para decidir qué buscar y para estimar precios orientativos. Los enlaces que el usuario clica de verdad siempre los genera mi propio código, nunca se copian de la respuesta del modelo.

Wishlist, alertas de precio y un scheduler silencioso

Por encima de la búsqueda corre una segunda capa, pensada más para el uso diario que para la demo: una wishlist para guardar los productos interesantes y un sistema de alertas que notifica cuando un precio baja de un umbral configurado. APScheduler comprueba todas las alertas cada 24 horas en segundo plano, además de un endpoint manual (/api/alerts/check) para forzar la verificación cuando no se quiere esperar.

De casa a cualquier lugar

BIVIO corre enteramente en local — ningún servidor que pagar, ningún dato que salga de casa. Para usarlo también fuera de casa añadí un Cloudflare Tunnel: ningún puerto abierto en el router, ninguna IP estática que configurar, solo cloudflared tunnel run bivio apuntando al dominio.

Los problemas reales

Tres obstáculos concretos, de los que no se encuentran en la documentación oficial.

1. El antivirus interceptaba las llamadas HTTPS. Las peticiones a Gemini fallaban con errores SSL intermitentes. Causa: el antivirus local hacía inspección TLS en las conexiones salientes. Solución (temporal, no ideal): parche global con ssl._create_unverified_context aplicado a httpx.

2. La cuota de Gemini se agota, y en un momento incómodo. Para grabar un reel de demostración la cuota diaria ya se había acabado. Solución estructural: dos claves API en cascada (GEMINI_API_KEY_2 primaria, GEMINI_API_KEY como fallback), y para las demos en directo, datos inyectados directamente después de la respuesta del backend en lugar de esperar al reinicio de la cuota.

3. La PA-API de Amazon exige 3 ventas cualificadas antes de activarse. Las credenciales de Associates por sí solas solo bastan para generar la etiqueta de tracking, no para consultar la API oficial — hace falta historial de ventas. Mientras tanto, Amazon pasa por el mismo canal de Gemini + grounding que los otros tres marketplaces, listo para pasar a PA-API v5 el día en que el historial lo desbloquee.

El modelo de IA no sustituye la integración con las APIs oficiales — la anticipa. El día en que se desbloquee la PA-API, cambio una función y el resto de la arquitectura sigue igual.

Coste real

  • Hosting: 0 €/mes (corre en un PC de casa)
  • Gemini 2.0 Flash: gratuito en el tier gratuito, con doble clave de fallback
  • Cloudflare Tunnel: gratuito
  • SQLite: incluido, cero configuración

Qué añadiría

La PA-API oficial de Amazon en cuanto maduren las 3 ventas requeridas, un histórico de precios para saber si conviene comprar ahora o esperar, y una versión mobile-first del frontend — de momento pensado sobre todo para escritorio en casa.