10 KiB
AGENTS.md
Capa agentica (MCP): para uso desde Claude Code u otros clientes LLM, este repo expone un servidor MCP stdio en
mcp_server/con tools tipadas (defaults dry-run,confirm_tokenpara aplicar, rollback víascript_audit). Ver docs/AGENT_TOOLS.md para el catálogo y recetas. Manifest navegable engenerated/agent/tools_manifest.json.
Commands
- Install deps with
python -m pip install -r requirements.txt. - Run the local app with
python main.py; it serves FastAPI/Uvicorn athttp://127.0.0.1:8000with reload enabled. - On Windows,
start.batrunspython main.pyin a new window and opens the browser;stop.batkills any process using port8000. - There is no test, lint, or formatter config in this repo. For a syntax-only check, run
python -m py_compile main.py db.py ghl_client.py sync_engine.py script_runner.pyand add specific scripts as needed. - Run focused utility scripts directly, for example
python scripts\mp_contact_search.py <query>orpython scripts\mp_opportunity_search.py <query-or-status>. - Global dashboard sync parallelism is controlled with
SYNC_ENGINE_MAX_WORKERS; default is12, hard maximum is20. It affects theSincronizar Todobutton and processes multiple GHL locations in parallel. - Dashboard batch parallelism is controlled globally with
SCRIPT_RUNNER_MAX_WORKERS; default is4, hard maximum is20. Higher values can increase GHL429/timeout risk because script subprocesses do not share in-memory rate-limit state.
App Wiring
main.pyis the app entrypoint; API routes calldb.py,sync_engine.py, andscript_runner.py.templates/index.htmlplusstatic/js/app.jsandstatic/css/style.cssare the single-page dashboard UI.db.pyowns the local SQLite schema atgenerated/data/mp_manager.sqlite(path comes frompaths.DB_PATH); sync writes replace per-location contacts, pipelines, and opportunities inside transactions.sync_engine.pyreadsBucéfalo - Mesa de control - API Tokens - MP.csvat startup/sync time. The CSV must includeLocation_ID,Nombre, andAPI_token; tokens are cached in memory and are not stored in SQLite.- The main brand account is hard-coded as location
GbKkBpCmKu2QmloKFHy3; all other CSV locations are treated as branches.
Generated Files
All dynamic outputs live under generated/ and are sourced from paths.py. Never hardcode disk paths in new code — import from paths (or via scripts/common.py, which re-exports them). Layout: generated/data/ (SQLite), generated/reports/ (audit/dup/drift/coverage outputs), generated/exports/ (downloads served by /api/exports/), generated/logs/ (errors.jsonl + script_runs/), generated/migrations/ (pre-destructive snapshots), generated/browser/ (Playwright session, profile, screenshots), generated/runtime/ (server_info.json, last_mode, in-flight bulk batches), generated/_archive/ (legacy). The whole tree is gitignored and megaignored.
GHL API Gotchas
ghl_client.pyis the executable source for GHL behavior: base URLhttps://services.leadconnectorhq.com, API version header2021-07-28, and bearer-token auth.- Keep the per-token rate limiting in
GHLClient._wait_for_rate_limit; global sync concurrency must useSYNC_ENGINE_MAX_WORKERSinstead of hardcoded worker counts. - Contacts paginate with
meta.nextPageUrlandstartAfter; do not replace this with offset pagination. - Opportunities must be fetched with
POST /opportunities/search;GET /opportunities/is documented here as returning empty/zero results. - If GHL returns no pipelines but opportunities have pipeline IDs, sync creates synthetic pipelines from opportunity stages instead of failing.
GHL Pagination & Full Dataset Retrieval
- Contactos: usar la paginación cursor-based de GHL con
meta.nextPageUrl,startAftery, cuando aplique,startAfterId. No usar offset pagination. Continuar solicitando páginas hasta que no exista siguiente cursor/URL o hasta alcanzar un límite explícito del script (--limit,--max-contacts, etc.). - Oportunidades: usar exclusivamente
POST /opportunities/searchporlocationId. Si se requiere un dataset completo, paginar/iterar la búsqueda hasta agotar resultados o alcanzar un límite explícito. No usarGET /opportunities/para escaneos porque puede devolver vacío/cero resultados. - Acumulación segura: cada página debe agregarse a una colección global, deduplicando por
idpara evitar repetidos entre páginas o reintentos. - Protección anti-loop: todo paginador debe controlar cursores/URLs ya vistos, páginas vacías repetidas o límites máximos razonables para evitar ciclos infinitos.
- Auditorías profundas: antes de comparar, sincronizar o corregir datos, el script debe haber consolidado todas las páginas necesarias de contactos/oportunidades para no dejar datos fuera del análisis.
- Resumen final: los scripts que paginan deben reportar total de páginas consultadas, total recibido, total único procesado, duplicados descartados y si se cortó por límite.
Dynamic Schema & Custom Fields Mapping
Para consultar y mapear campos personalizados cuyos IDs varían entre diferentes sucursales de GHL, se debe utilizar el siguiente flujo de API (ambos usando la cabecera Version: 2021-04-15):
- Obtener Catálogo de Objetos:
- Endpoint:
GET https://services.leadconnectorhq.com/objects/?locationId={locationId} - Detalle: Requerido para inicializar y autorizar la sesión de consulta de esquemas de metadatos en GHL para esa ubicación.
- Endpoint:
- Obtener Esquema por Objeto (Schema by Key):
- Endpoint:
GET https://services.leadconnectorhq.com/objects/{objectKey}?locationId={locationId} - Parámetro
{objectKey}: Usarcontactoopportunity. - Detalle: Devuelve el listado completo de campos (estándar y personalizados). Permite mapear de forma dinámica campos por su nombre (ej.
"Canal de Origen"o"Fuente de Prospecto") a su correspondiente ID dinámico en esa sucursal para lectura o actualización segura.
- Endpoint:
Business Logic & Field Correlations (Monte Providencia Rules)
Derivado de DOCUMENTACIÓN de Monte Providencia.md, estas reglas rigen el comportamiento de los scripts, la integridad de los datos y el mapeo en GHL:
1. Flujo de Sincronización y Prioridades
- Sincronización de Contactos: Bidireccional entre la cuenta de Marca principal (
GbKkBpCmKu2QmloKFHy3) y las sucursales. Cualquier creación/modificación en un lado se sincroniza al otro. - Sincronización de Oportunidades: Unidireccional de Sucursal a Marca (la sucursal tiene prioridad). Las modificaciones de oportunidades en la cuenta de marca no se sincronizan hacia las sucursales.
- Multi-Oportunidades: Un mismo contacto puede tener más de una oportunidad (múltiples intentos de empeño).
2. Campos Requeridos para Business Intelligence (BI)
Cada contacto u oportunidad debe poblar consistentemente:
Sucursal(y campoTIENDA) alineados con el "verificador de sucursales".Canal de Origen(e.g., FORMULARIO, FACEBOOK, WHATSAPP, LLAMADA, INSTAGRAM, SUCURSAL).Fuente de Prospecto(e.g., CLIENTE CONOCIDO, SUCURSAL, PROSPECCIÓN, REFERIDO, ALIANZA, EVENTO ESPECIAL, LEAD DIGITAL).
3. Reglas de Validación de Origen/Fuente
LEAD DIGITALsiempre proviene de un canal digital (Canal de Origen: Formulario, Facebook, etc.).- Si el
Canal de OrigenesSUCURSAL, laFuente de Prospectono puede serLEAD DIGITAL. - El tag
"sucursal"en contactos implica creación manual en sucursal, a menos que el camposourcenativo de GHL indique lo contrario (un origen digital).
4. Correlación de Datos de Vehículo
- Para prospectos con fuente
LEAD DIGITAL, el campoVehículode la oportunidad debe construirse concatenando los campos personalizados del contacto:"Marca del Vehículo" + "Versión del Vehículo" + "Año del Vehículo". - En oportunidades creadas manualmente, el campo de vehículo de la oportunidad puede diferir de los datos del contacto.
5. Pipelines y Oportunidades Huérfanas
- Toda oportunidad debe residir en un pipeline activo válido (comúnmente llamado
"Standar"). - Oportunidades huérfanas (sin pipeline válido) se deben reubicar según coincidencia de nombre de etapa (stage) o marcar para revisión.
Scripts And Data Safety
script_runner.pyexposes only scripts listed inSCRIPTS_METADATA; add metadata there when adding a dashboard-runnable script.- Most scripts read
mp_manager.sqlitefrom the repo root and expect a prior dashboard sync. Some scripts are live GHL mutators (fix_*,migrate_*,move_*,update_*,sync_contact_*); prefer read-only audit/search scripts first unless the user explicitly asks to modify GHL data. - Treat
Bucéfalo - Mesa de control - API Tokens - MP.csvand any printed API tokens as secrets.
Case log (registro de casos)
docs/casos/is the chronological log of real operations/investigations on Bucéfalo, written for agent recall (dense, exact commands, literal ids/errors). It complements thedocs/PLAYBOOK_*files (timeless theory) and the agent memory (atomic facts).- When to add a case: after any Bucéfalo mutation (with
run_id/snapshot) OR after closing a non-trivial investigation that reached a root cause (even with no mutation). - How: copy
docs/casos/_PLANTILLA.md→docs/casos/YYYY-MM-DD-<slug>.md, fill it, add the row todocs/casos/INDEX.md, and link the related memory with[[slug]]. - Before investigating a new symptom,
grepdocs/casos/for the error/symptom — it may already be solved.