Skip to content

luis-codex/compliance-agent

Repository files navigation

Compliance Q&A Agent (Cloudflare Workers)

Sistema serverless que ingiere leyes chilenas, construye embeddings y orquesta agentes para responder preguntas de compliance mediante Cloudflare Workers, Vectorize, Workflows y Workers AI. Aqui documento las decisiones arquitectónicas, los flujos asincrónicos, el uso de herramientas MCP, etc.


Arquitectura y flujo de datos

Arquitectura del agente

Estructura principal

src/
  app/               # Hono/Workers entrypoint y rutas HTTP
  workflows/         # Workflows de ingesta (RAG) y Q&A (agents) en segundo plano
  services/          # Servicios (documentos, logging/audit, MCP)
  shared/            # DB (Drizzle), libs (RAG/AI), schemas zod, utils
  mcp/               # Servidor MCP que registra tools dinámicamente

Componentes

  • API HTTP (Hono + Cloudflare Workers) expuesta en src/app/index.ts. Monta rutas REST (/question, /documents) y publica el servidor MCP en /mcp.
  • RagWorkflow (src/workflows/rag/rag.workflow.ts): orquesta steps fetch-pdfsplit-embedinsert-vectorizeupdate-metadata para procesar PDFs y persistir embeddings en Vectorize.
  • AgentWorkflow (src/workflows/agent/agent.workflow.ts): separa planeación (plan), búsquedas (search) y síntesis (synthesize); deja trazas en D1 vía AuditLogger.
  • Servicios: DocumentService (busca/ingesta), DocumentRepository (D1/Vectorize), AuditLogger (persistencia de pasos), McpService (registro de tools). Drizzle + esquemas en src/shared/db/schema.ts.
  • Herramientas MCP (src/mcp/index.ts): registra UPLOAD_PDF, LIST_PDFS y PDF_QUERY con los mismos contratos zod que la API.

Flujo de solicitud

  1. Ingesta: POST /documents dispara RagWorkflow, almacena el PDF en D1 y los embeddings en Vectorize.
  2. Planeación: POST /question crea un AGENT_WORKFLOW. Consulta los documentos disponibles, diseña un plan de búsqueda y registra el paso.
  3. Ejecución: por cada plan, consulta VECTORIZE vía DocumentService, razona con Workers AI y persiste la traza en D1.
  4. Síntesis: combina los análisis, genera la respuesta final y devuelve el workflowId para seguimiento asincrónico.

Modelos de IA utilizados

Objetivo Modelo Workers AI
Embeddings semánticos @cf/baai/bge-large-en-v1.5
Planeación de agentes/prompts @cf/meta/llama-3.1-8b-instruct-fast
Razonamiento profundo @cf/deepseek-ai/deepseek-r1-distill-qwen-32b

Decisiones de diseño y trade-offs

Elegí Workflows para ejecutar procesos en segundo plano y estado fuera de la request, Vectorize como vector store para almacenar embeddings, uso Hono para los endpoints, uso a D1 como base de datos, y cree contratos con Zod en src/shared/schemas/validation.schema.ts para que HTTP y MCP compartan uploadSchema y querySchema sin derivarse.


Razonamiento estructurado, composabilidad y asincronía

  • Razonamiento estructurado: AgentWorkflow separa planeación, búsquedas RAG y síntesis. Cada fase se guarda como un stepName diferente y puede auditarse.
  • Composabilidad: la lógica de documentos vive en DocumentService y las herramientas se registran dinámicamente. Nuevos agentes o documentos solo requieren agregar workflows/tools sin tocar las rutas.
  • Asincronía: env.RAG_WORKFLOW y env.AGENT_WORKFLOW continúan aun si se corta la conexión. /question expone un patrón de polling para recuperar resultados.

Requisitos y variables de entorno

Prerrequisitos

  • Node.js 18+ y pnpm
  • Wrangler CLI
  • Cuenta de Cloudflare con acceso a Workers, Workflows, D1, Vectorize y Workers AI.

Bindings necesarios

Binding Tipo Uso
DB D1 Tablas pdf_table y workflow_executions
VECTORIZE Vectorize index Embeddings por documento (namespace = id del PDF)
AI Workers AI Acceso a embeddings + LLMs
RAG_WORKFLOW / AGENT_WORKFLOW Workflows Orquestación de ingesta y Q&A
MCP_OBJECT Durable Object Servidor MCP con tools dinámicas

Provisiona los recursos con Wrangler y actualiza wrangler.jsonc con los IDs retornados:

# Base de datos y vector store
wrangler d1 create db --binding DB
wrangler vectorize create vectorize-index-pdf --dimensions 1024 --metric cosine

#    ⛅️ wrangler 4.45.0 (update available 4.49.0)
#   ─────────────────────────────────────────────
#   🚧 Creating index: 'vectorize-index-pdf'
#   ✅ Successfully created a new Vectorize index: 'vectorize-index-pdf'
#   To access your new Vectorize Index in your Worker, add the following snippet to your configuration file:
#   {
#     "vectorize": [
#       {
#         "binding": "VECTORIZE",
#         "index_name": "vectorize-index-pdf"
#       }
#     ]
#   }
#   ✔ Would you like Wrangler to add it on your behalf? … yes
#   ✔ What binding name would you like to use? … VECTORIZE
#   ✔ For local dev, do you want to connect to the remote resource instead of a local resource? … yes

Cómo correr el proyecto

  1. Instalar dependencias y generar types
    pnpm install && pnpm cf-typegen
  2. Generar artefactos y migrar
    pnpm run db:generate
    pnpm run db:migrate:local
  3. Levantar en local
    pnpm run dev
    Wrangler expone el worker en http://127.0.0.1:8787.
  4. Desplegar (opcional)
    pnpm run deploy
    pnpm run db:migrate:remote

Despliegue disponible

  • URL pública: https://compliance-agent.server-codex.workers.dev
  • Estado: el despliegue ya tiene ingeridos los 5 documentos oficiales con sus embeddings en Vectorize; puedes usar los endpoints tal cual (/documents, /question, /mcp).

Uso y llamadas curl

1. Cargar los 5 documentos oficiales del reto

# Ley 19.886 - Compras Públicas
curl -sS -X POST http://127.0.0.1:8787/documents \
  -H "content-type: application/json" \
  -d '{"pdfUrl":"https://pub-0e0e9ca0d502436bbf25ba03d6046c82.r2.dev/Ley-19886.pdf","title":"Ley 19.886","description":"Compras Públicas y Bases Tipo ChileCompra"}'

# Ley 19.496 - Protección de los consumidores
curl -sS -X POST http://127.0.0.1:8787/documents \
  -H "content-type: application/json" \
  -d '{"pdfUrl":"https://pub-0e0e9ca0d502436bbf25ba03d6046c82.r2.dev/Ley-19496.pdf","title":"Ley 19.496","description":"Derechos y obligaciones de los consumidores"}'

# Ley 20.393 - Responsabilidad penal de personas jurídicas
curl -sS -X POST http://127.0.0.1:8787/documents \
  -H "content-type: application/json" \
  -d '{"pdfUrl":"https://pub-0e0e9ca0d502436bbf25ba03d6046c82.r2.dev/Ley-20393.pdf","title":"Ley 20.393","description":"Responsabilidad penal corporativa"}'

# Ley 19.913 - UAF
curl -sS -X POST http://127.0.0.1:8787/documents \
  -H "content-type: application/json" \
  -d '{"pdfUrl":"https://pub-0e0e9ca0d502436bbf25ba03d6046c82.r2.dev/Ley-19913.pdf","title":"Ley 19.913","description":"Sujetos obligados y reportes UAF"}'

# Ley 21.521 - Fintec
curl -sS -X POST http://127.0.0.1:8787/documents \
  -H "content-type: application/json" \
  -d '{"pdfUrl":"https://pub-0e0e9ca0d502436bbf25ba03d6046c82.r2.dev/Ley-21521.pdf","title":"Ley 21.521","description":"Fintec y normas CMF (NCG 514/502)"}'

Cada carga crea un registro en pdf_table y dispara RagWorkflow; usa GET /documents/:id para confirmar que el estado cambió a completed.

2. Lanzar una pregunta asincrónica

curl -sS -X POST http://127.0.0.1:8787/question \
  -H "content-type: application/json" \
  -d '{"question":"Si tengo una empresa de software medioambiental para salmoneras, en el sur de Chile, ¿qué sugerencias tienes sobre cómo puedo cumplir con la ley de protección de datos personales?"}'
# => { "workflowId": "4f1c...", "status": "...." }

3. Consultar el resultado con workflowId

curl -sS -X POST http://127.0.0.1:8787/question \
  -H "content-type: application/json" \
  -d '{"workflowId":"4f1c..."}'

La respuesta incluye el estado y el arreglo steps con cada fase registrada.

4. Consultas específicas sobre un documento

curl -sS -X POST http://127.0.0.1:8787/documents/query \
  -H "content-type: application/json" \
  -d '{"documentId":"<id_del_pdf>","queryText":"obligaciones de reporte a la UAF","topk":5}'

5. Endpoints útiles

  • GET /documents — lista de PDFs.
  • DELETE /documents/:id — borra un documento y sus embeddings.
  • GET /question o GET /question/:id — observabilidad de workflows ejecutados.
  • MCP: consumir /mcp con un cliente MCP compatible para correr UPLOAD_PDF, LIST_PDFS o PDF_QUERY.

MCP y herramientas

El worker monta MyMCP y registra:

  • UPLOAD_PDF: reutiliza la validación de Zod para cargar documentos.
  • PDF_QUERY: ejecuta una consulta semántica sobre un documento específico usando querySchema.

Esto facilita demostrar composabilidad multi-agente desde un IDE como Claude Desktop, Postman o VS Code MCP. alt text alt text

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published