Auditoría en vivo · sin teatro · 2026-07-27
Comparación campo a campo entre las 3 capturas de Instagram que mandaste de MillonAI (Paraguay) y el código que hoy corre en producción del bot de Zymplo — el mismo escenario en los tres: texto, audio y foto de ticket.
La primera pasada (dos sub-agentes en paralelo) auditó /repos/langgraph — un clon con remote skn-alarmas/langgraph, congelado el 30 de abril y sin ningún workflow de deploy. Ahí salió un hallazgo de "asteriscos sueltos rompiendo el formato". Antes de escribirlo como hecho, se cruzó el commit que otra nota interna marca como el desplegado hoy (bdd3640e) contra ese repo: no existe ahí. Aparece en zymplo-inc/zymplo → zymplo-langgraph/, cuyo propio CLAUDE.md dice explícitamente "es la ÚNICA fuente de verdad del bot… corre en producción en agents.zymplo.com". Se repitió toda la auditoría ahí. Lo que sigue —incluido el hallazgo de asteriscos, que resultó estar ya resuelto en el repo correcto— corresponde al repo que realmente corre hoy.
Lado a lado
Izquierda: reconstrucción fiel de tus capturas de millonai.app (mismo texto, mismo orden, mismos emoji). Derecha: reconstrucción a partir del código real de zymplo-langgraph — plantillas y valores tal como los arma el bot hoy, con los campos que vienen de la base de datos marcados {así} en vez de inventados.
Hallazgos
Nada de esto es opinión — cada línea abajo apunta a un archivo y un número de línea reales, verificados en este mismo turno.
Más allá de estos 3 mensajes
Esto es lo que hay además del cuaderno de gastos. Confianza "alta" = probado este turno leyendo el código y su comportamiento real. Confianza "media" = el archivo existe y el nombre coincide con la función (confirmado este turno), pero no se re-verificó línea por línea si el flag está prendido en producción — la misma prudencia que hizo falta con el módulo huérfano de arriba.
| Capacidad | MillonAI (tus capturas) | Zymplo | Confianza |
|---|---|---|---|
| Gasto por texto | ✓ visto | ✓ erp_registrar_compra | alta |
| Gasto/ingreso por audio | ✓ visto | ✓ 3 motores STT | alta |
| Gasto por foto de ticket (OCR) | ✓ visto | ✓ Claude Vision | alta |
| Cobro / link de pago (PIX) | no visto | ✓ payments/pix_brcode.py, pix_inbox/ | media |
| Pasarela de pago Paraguay | no visto | ✓ payments/pagopar.py | media |
| Facturación fiscal (12 países) | no visto | ✓ NFS-e/CFDI/SIAT/SRI/DIAN/CFE/ARCA/AEAT/SUNAT/Hacienda/FE-US | media |
| Banco conectado (Open Finance) | no visto | ✓ belvo.py + carpetas openfinance-* | media |
| Respuesta por nota de voz (TTS) | no visto | ✓ integrations/tts.py | media |
| Calendario / recordatorios | no visto | ✓ google/calendar.py | media |
| Firma electrónica de contratos | no visto | ✓ docs/zapsign.py, docuseal.py | media |
Veredicto
En las 3 cosas exactas que MillonAI mostró, Zymplo ya iguala o supera lo que se ve en la captura: foto con lectura real (no una plantilla adivinada), audio con tres motores de respaldo, y un texto libre que además detecta moneda distinta y vincula cliente y cuenta solo — nada de eso aparece en las capturas de MillonAI. El único punto donde la tarjeta de MillonAI se ve más prolija es exactamente donde tiene menos que hacer: es una tarjeta de 4 líneas fija, mientras que la de Zymplo para un ingreso libre todavía deja pasar la palabra "RECEITA" en portugués en un chat en español — un defecto de traducción, no de arquitectura. Fuera de esos 3 mensajes ya no hay comparación posible con lo que mostró MillonAI: PIX, facturación fiscal en 12 países, banco conectado y voz de salida no aparecen en ninguna de sus capturas.
tx_registered/RECEITA/DESPESA a Ingreso/Gasto cuando el idioma detectado no sea portugués — cambio de diccionario en erp_api_tools.py, no de arquitectura. Es el gap más visible de los dos encontrados.# repos/langgraph — remote zymplo apunta a un commit de abril, sin bdd3640e $ git ls-remote zymplo | grep -iE "develop|main" 563384a14e8530b6552cafddb5ef3aeb7dc1350f refs/heads/main # 30-abr-2026, sin "develop" $ git cat-file -t bdd3640e fatal: Not a valid object name bdd3640e
# repos/zymplo/zymplo-langgraph — remote zymplo-inc/zymplo
$ git cat-file -t bdd3640e
commit
$ git log --all --format="%H %s" | grep bdd3640
bdd3640eb7bb01f0dbd7b118592144b7634c398c Merge pull request #2750 from zymplo-inc/develop
$ git log origin/main -1 --format="%H %ci %s"
f2c09bef6784775574a5211882a539d54a9e12d0 2026-07-27 15:54:22 -0300 Merge pull request #2782 from zymplo-inc/develop
# 1. la plantilla real todavía arma **bold** con doble asterisco handlers.py:1954 lines.append(f"✅ **{total_items} movimientos registrados!**\n") # 2. pero el transporte de salida lo limpia — confirmado en los 2 proveedores bsp.py:174-176 text = strip_markdown_for_whatsapp(text) # 360dialog, el vivo meta_client.py:52-55 message = strip_markdown_for_whatsapp(message) # Meta Cloud, fallback # 3. el propio comentario del código documenta el porqué del rediseño handlers.py:405 "Historically this CONVERTED **bold** -> *bold*, which still shipped asterisks... Now it delegates to the shared strip sanitizer... The real choke-point is the outbound transport"
$ grep -rln "analyze_receipt_v2\|process_receipt_image" src --include="*.py" | grep -v /tests/ src/integrations/vision/__init__.py # solo se llama a sí mismo src/integrations/vision/receipt.py # solo se llama a sí mismo # handlers.py sigue importando la ruta vieja: handlers.py:21 from src.utils.image_processor import analyze_receipt, describe_image
_auto_register_from_receipt, plantilla del reciboerp_registrar_compra (gasto por texto/audio)erp_crear_transaccion (ingreso/gasto libre, RECEITA/DESPESA)strip_markdown_for_whatsappanalyze_receipt_v2, huérfano