Prompt curado — MVP de arquitectura distribuida de agentes para investigación de datos
Fecha: 2026-09-21
Origen: unión de la sesión sobre RAG/frontier/MLOps/open-weights (decisiones
[CREDENCIAL].md y
[CREDENCIAL].md) con el brief de Nef para
distributed-fraud-mvp (Credit Card Fraud, MLG-ULB).
Uso: pegar el bloque completo como primer mensaje de un agente de código (opencode / Claude Code) en un repo vacío. El agente ejecuta en silencio por milestones y entrega evidencia, no reportes.
ENCARGO: distributed-fraud-mvp
0. Rol y modo de trabajo
Eres arquitecto e implementador. Construye el MVP de abajo por milestones, verificando cada uno antes de pasar al siguiente. Ejecuta en silencio: no re-preguntes lo ya especificado. Responde en español; código, schemas, nombres de archivo y commits en inglés.
Entrega por milestone:
- archivos exactos creados/modificados;
- comandos de verificación ejecutados y su salida;
- qué quedó mock y qué es real;
- siguiente milestone.
Prohibido afirmar éxito sin evidencia ejecutada. Si algo del brief es ambiguo, elige la opción más pequeña que cumpla el DoD y documéntala.
1. Objetivo y no-objetivo
Objetivo: demostrar una arquitectura distribuida con trabajos concurrentes, separación de responsabilidades, minimización de datos y ejecución reproducible, usando como dataset dummy Credit Card Fraud Detection (MLG-ULB, Kaggle: mlg-ulb/creditcardfraud).
No-objetivo: sistema de producción de detección de fraude; chatbot; orquestador genérico; RAG/vector DB (el dataset es tabular, no texto: no aplica); UI web antes de que la CLI complete el DoD.
2. Principio arquitectónico
Modela el sistema como un cuerpo distribuido:
- HEAD — Orchestrator: recibe el research job, planea, divide en tareas, asigna, ejecuta lo concurrente, espera dependencias, recolecta, hace merge, produce el reporte final. Control plane: NO procesa datasets.
- TORSO — Linode + Gemma: estado/memoria, resultados intermedios, razonamiento local (Gemma vía Ollama), hipótesis, síntesis. Expone API HTTP mínima. Si Gemma no está disponible, adapter/mock claramente separado.
- ARMS — Hugging Face Docker Space: cómputo delegable; worker remoto
sustituible por un modelo frontier después. Nunca recibe el dataset ni
información privada. Solo jobs sanitizados.
POST /v1/jobs,GET /health, respuestas JSON estructuradas. - LEGS — máquina local: acceso al dataset, archivos, Python, Docker, Git, validación, artefactos. Todo lo que requiera datos privados. El dataset completo vive aquí.
- PRIVACY GATE: función única que decide qué cruza la frontera.
El sistema debe sobrevivir la pérdida de cualquier worker: perder un ARMS no pierde el job.
3. Contratos primero (antes de implementar workers)
- Schemas JSON en
schemas/:job.schema.json,task.schema.json,signal.schema.json,result.schema.json. Validación en el gateway, no en cada worker. - Worker protocol:
{id, capabilities, health(), submit(task) -> result}. El scheduler NUNCA importa workers concretos: los recibe por registro. Sustituir HF o Gemma = registrar otro adapter, sin tocarscheduler.py. - Gateway único de egress remoto (
orchestrator/workers.py): ahí viven sanitización, caps de tamaño, timeouts, retries y logging. Ningún worker remoto se llama fuera de él. - Idempotencia:
task.outputse cachea porhash(input + code_version); re-ejecutar una tarea completada no repite cómputo ni duplica archivos.
4. Job fraud-mvp-001
Pregunta: “¿Qué patrones estadísticos y de modelado permiten identificar transacciones potencialmente fraudulentas en este dataset extremadamente desbalanceado?”
| Task | Worker | Depende de | Output |
|---|---|---|---|
| DATA_PROFILE | LOCAL | — | data_profile.json |
| ANOMALY_PROFILE | LOCAL | — | anomaly_profile.json |
| BASELINE_MODEL | LOCAL | — | baseline_metrics.json |
| HYPOTHESIS_GENERATION | LINODE/GEMMA | 1,2,3 | hypotheses.json |
| EXPERIMENT_DESIGN | HF | 4 | experiment_plan.json |
| LOCAL_VALIDATION | LOCAL | 5 | experiment_results.json |
| SYNTHESIS | LINODE/GEMMA | 1–6 | research_report.md |
Las tres primeras no dependen entre sí (cada una lee el dataset por su cuenta): deben correr concurrentemente para cumplir el DoD A.
Contenido por tarea:
- DATA_PROFILE: filas, columnas, tipos, missing, duplicados, distribución
de
Class, stats deTimeyAmount, media/std/min/max por feature, prevalence. Nada sale de local. - ANOMALY_PROFILE: perfil estadístico Class=0 vs Class=1; features con diferencias relevantes.
- BASELINE_MODEL: al menos Logistic Regression y Random Forest, split estratificado con seed fija, sin leakage. Métricas completas (sección 6).
- HYPOTHESIS_GENERATION: recibe SOLO data_profile + anomaly_profile + baseline_metrics. Produce señales, riesgos metodológicos, imbalance, errores posibles y experimentos siguientes.
- EXPERIMENT_DESIGN: recibe SOLO el resumen sanitizado de la sección 5. Produce plan experimental estructurado.
- LOCAL_VALIDATION: ejecuta el plan sobre el dataset real y guarda resultados.
- SYNTHESIS: combina todo en
research_report.md.
5. Privacidad (PRIVACY GATE)
sanitize_for_remote_worker() con allowlist explícita: solo agregados
del ejemplo del brief (rows, features, positive_class,
negative_class, positive_rate, feature_summary, baseline_metrics).
Rechaza campos desconocidos, tipos inválidos y payloads sobre el cap.
Nunca envía: dataset, filas, identificadores, archivos locales, paths, env vars, API keys, tokens, passwords, memoria completa, prompts privados innecesarios.
Test duro (tests/test_privacy.py): escanear todos los payloads que salen
por el gateway y fallar si aparece cualquier nombre de columna (V1…V28,
Class, Time, Amount), valores de filas, paths o patrones de secreto.
También: payload desconocido → rechazado; payload sobredimensionado →
rechazado.
Honestidad de frontera: el README debe decir “application telemetry minimized”, nunca “el proveedor no puede observar nada”. Los metadatos y logs de infraestructura del proveedor cloud quedan fuera de tu control y se documentan como tales.
6. Dataset y métricas
data/creditcard.csvNO entra al repo (gitignore).data/README.mdexplica cómo obtenerlo. El agente NO descarga el dataset.- Si el CSV falta:
make data-mockgenera un sintético con el mismo esquema y seed fija;job.jsonmarcadataset_fingerprint: "synthetic"y el reporte lo declara. El MVP debe completar el DoD así. - Guardar
split.json(índices/hash del split) para comparabilidad entre corridas. - Caveat metodológico obligatorio en el reporte: el dataset es temporal
(
Time≈ 2 días) yV1–V28son PCA anonimizados; un split aleatorio puede filtrar patrones temporales. Incluir un experimento con split por tiempo y reportar ambos. - Métricas mínimas: precision, recall, F1, PR-AUC/AUPRC, ROC-AUC, confusion matrix, fraud prevalence. Accuracy prohibida como métrica principal (solo como contexto explícitamente marcado).
- Desbalance (~0.1727%): documentarlo, usar
class_weight/scale_pos_weight, y documentar la decisión de umbral: 0.5 no es neutral en desbalance — reportar la curva PR y justificar el umbral elegido.
7. Reproducibilidad y provenance
job.json: job_id, timestamp, dataset fingerprint (sha256 + filas), git commit, seed, task graph, modelos y versiones, parámetros, métricas, versiones de workers remotos.- Cada artefacto en
results/lleva bloque de provenance: código que lo generó, comando, entorno (python + libs), seed, hashes de input. research_report.md: cada número apunta al artefacto del que sale (tabla claim → archivo). Sin números huérfanos.
8. Observabilidad
- CLI:
python -m orchestrator run|status|results|retry fraud-mvp-001. - Dashboard de una corrida:
JOB fraud-mvp-001
[✓] DATA_PROFILE LOCAL 2.4s
[✓] ANOMALY_PROFILE LOCAL 4.1s
[✓] BASELINE_MODEL LOCAL 8.7s
[✓] HYPOTHESIS LINODE 3.2s
[✓] EXPERIMENT_PLAN HF 5.8s
[✓] VALIDATION LOCAL 21.4s
[✓] SYNTHESIS LINODE 4.0s
total 50.2s · concurrent peak 3 · failed 0 · retries 0 · remote bytes 1.2KB
- Trazas JSONL locales (
results/traces.jsonl): job_id, task_id, worker, status, duración, bytes del payload, hash. Nunca prompts, payloads, resultados completos ni dataset. - Telemetría:
DO_NOT_TRACK=1,HF_HUB_DISABLE_TELEMETRY=1,GRADIO_ANALYTICS_ENABLED=False. Sin Google Analytics, PostHog, Mixpanel, Segment ni Sentry.
9. Manejo de fallos
Timeout por tarea; retry con backoff y límite; estado failed; worker
caído → waiting_for_worker y el job se retoma después con retry;
respuesta malformada → failed con razón; schema inválido → rechazo en el
gateway. El job nunca se pierde por un worker ausente.
10. Docker y paridad
docker-compose.yml con orchestrator, linode-worker-mock y
hf-worker-local. El mismo Dockerfile de hf-worker/ corre local y se
despliega como Hugging Face Docker Space: mismo /health, mismo
/v1/jobs, mismo comportamiento. Sin dataset en la imagen. Healthcheck.
Secretos: HF Secrets en remoto, .env local desde .env.example (.env
nunca en Git).
11. Estructura del repo
distributed-fraud-mvp/
├── README.md
├── .gitignore
├── docker-compose.yml
├── orchestrator/
│ ├── app.py
│ ├── scheduler.py
│ ├── models.py
│ ├── workers.py
│ └── privacy.py
├── local-worker/
│ ├── profiler.py
│ ├── anomaly.py
│ ├── baseline.py
│ └── validator.py
├── linode-worker/
│ ├── app.py
│ ├── gemma.py
│ └── memory.py
├── hf-worker/
│ ├── Dockerfile
│ ├── README.md
│ ├── requirements.txt
│ ├── app.py
│ └── worker.py
├── schemas/
│ ├── job.schema.json
│ ├── task.schema.json
│ ├── signal.schema.json
│ └── result.schema.json
├── data/
│ └── README.md
├── results/
│ └── .gitkeep
└── tests/
├── test_scheduler.py
├── test_privacy.py
└── test_schema.py
12. NO (requisitos duros)
- NO subir el dataset ni muestras a ningún worker remoto.
- NO accuracy como métrica principal.
- NO secretos hardcodeados;
.envnunca en Git. - NO vector DB, LangChain, LlamaIndex ni RAG: el dataset es tabular.
- NO broker de mensajes (Redis/RabbitMQ/Kafka): estado en archivos, el scheduler es propio y mínimo.
- NO UI web antes de que la CLI complete el DoD.
- NO logs con prompts, payloads, resultados ni dataset.
- NO afirmar que la telemetría del proveedor cloud está eliminada.
- NO descargar el dataset (lo provee el usuario).
- NO sobreingenierizar: lo que no esté en el DoD, no se construye.
13. Milestones con verificación
- M0 — Esqueleto + mocks end-to-end: schemas, scheduler con concurrencia
real (3 tareas), CLI, workers mock, dashboard, tests. Verificación:
pytestverde +run fraud-mvp-001completo con mocks + demo de 3 tareas solapadas en el tiempo. - M1 — Tareas locales reales: profiler, anomaly, baseline sobre
data-mock(o real si existe); métricas correctas;split.json. - M2 — TORSO real: Gemma vía Ollama detrás del mismo contrato del mock; test de contrato para ambos adapters.
- M3 — ARMS real:
hf-workeren Docker local; deploy al Space; privacy tests; matar HF →waiting_for_worker→ retry → resume. - M4 — Síntesis, provenance y evidencia DoD: reporte,
job.json,scripts/demo_dod.shque ejecuta y captura la evidencia A–H.
Primero el camino completo con mocks. Después Gemma real. Después HF real. Después el worker HF se sustituye por un modelo frontier — sin tocar el scheduler.
14. Definition of Done (ejecutable)
Un comando por criterio, evidencia capturada en results/dod/:
- A. 3 concurrentes: la traza muestra overlap de timestamps de DATA_PROFILE, ANOMALY_PROFILE y BASELINE_MODEL.
- B. El dataset nunca salió:
test_privacyescanea todos los payloads remotos y falla si aparece cualquier dato crudo. - C. HF recibió solo sanitizado: imprimir el payload exacto enviado.
- D. HF caído y recuperado: HF apagado →
waiting_for_worker→ HF arriba →retry→ job completo. - E. Swap de worker: registrar un segundo adapter HF (stub) sin tocar
scheduler.py; el diff lo demuestra. - F. Swap de modelo: correr HYPOTHESIS con mock y con Gemma sin tocar
scheduler.py. - G. Paridad local/remoto: mismo tag de imagen, mismo
/healthy/v1/jobsen local que en el Space. - H. Reproducibilidad: dos corridas con mismo commit + seed producen
métricas idénticas;
job.jsonlo demuestra.
15. Herencia de la sesión de investigación (contexto, no requisito)
Estos patrones vienen de la discusión previa y explican los requisitos:
- PRIVACY GATE ↔ el corpus nunca sale de local en arquitecturas local-first.
- Gateway único de egress ↔ el model gateway empresarial (routing, caps, retries, auditoría en un solo lugar).
- Provenance por artefacto ↔ Claude Science (código + entorno + conversación soldados a cada resultado).
- Trazas JSONL mínimas ↔ observabilidad MLOps sin acoplar a un SaaS.
- Split fijo + suite de métricas ↔ golden set y regresión de evals: sin esto no hay comparabilidad entre corridas.
- Adapters de worker y de modelo ↔ open-weights vs frontier como capa pluggable; Gemma local primero, frontier solo como capacidad externa.
- La lección de retrieval (híbrida + RRF + rerank, citations con punteros exactos) NO aplica aquí porque el dataset es tabular. Aplicaría el día que el corpus sea texto — por ejemplo un research assistant sobre papers, donde ese MVP sería la capa de agentes y el RAG la capa de evidencia.