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)

  1. 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.
  2. 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 tocar scheduler.py.
  3. 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.
  4. Idempotencia: task.output se cachea por hash(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?”

TaskWorkerDepende deOutput
DATA_PROFILELOCAL—data_profile.json
ANOMALY_PROFILELOCAL—anomaly_profile.json
BASELINE_MODELLOCAL—baseline_metrics.json
HYPOTHESIS_GENERATIONLINODE/GEMMA1,2,3hypotheses.json
EXPERIMENT_DESIGNHF4experiment_plan.json
LOCAL_VALIDATIONLOCAL5experiment_results.json
SYNTHESISLINODE/GEMMA1–6research_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 de Time y Amount, 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.csv NO entra al repo (gitignore). data/README.md explica cómo obtenerlo. El agente NO descarga el dataset.
  • Si el CSV falta: make data-mock genera un sintético con el mismo esquema y seed fija; job.json marca dataset_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) y V1–V28 son 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; .env nunca 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: pytest verde + run fraud-mvp-001 completo 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-worker en 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.sh que 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_privacy escanea 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 /health y /v1/jobs en local que en el Space.
  • H. Reproducibilidad: dos corridas con mismo commit + seed producen métricas idénticas; job.json lo 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.