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.
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
- 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 stepsfetch-pdf→split-embed→insert-vectorize→update-metadatapara 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íaAuditLogger. - Servicios:
DocumentService(busca/ingesta),DocumentRepository(D1/Vectorize),AuditLogger(persistencia de pasos),McpService(registro de tools). Drizzle + esquemas ensrc/shared/db/schema.ts. - Herramientas MCP (
src/mcp/index.ts): registraUPLOAD_PDF,LIST_PDFSyPDF_QUERYcon los mismos contratos zod que la API.
- Ingesta:
POST /documentsdisparaRagWorkflow, almacena el PDF en D1 y los embeddings en Vectorize. - Planeación:
POST /questioncrea unAGENT_WORKFLOW. Consulta los documentos disponibles, diseña un plan de búsqueda y registra el paso. - Ejecución: por cada plan, consulta
VECTORIZEvíaDocumentService, razona con Workers AI y persiste la traza en D1. - Síntesis: combina los análisis, genera la respuesta final y devuelve el
workflowIdpara seguimiento asincrónico.
| 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 |
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:
AgentWorkflowsepara planeación, búsquedas RAG y síntesis. Cada fase se guarda como unstepNamediferente y puede auditarse. - Composabilidad: la lógica de documentos vive en
DocumentServicey las herramientas se registran dinámicamente. Nuevos agentes o documentos solo requieren agregar workflows/tools sin tocar las rutas. - Asincronía:
env.RAG_WORKFLOWyenv.AGENT_WORKFLOWcontinúan aun si se corta la conexión./questionexpone un patrón de polling para recuperar resultados.
- Node.js 18+ y
pnpm - Wrangler CLI
- Cuenta de Cloudflare con acceso a Workers, Workflows, D1, Vectorize y Workers AI.
| 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- Instalar dependencias y generar types
pnpm install && pnpm cf-typegen - Generar artefactos y migrar
pnpm run db:generate pnpm run db:migrate:local
- Levantar en local
Wrangler expone el worker en
pnpm run dev
http://127.0.0.1:8787. - Desplegar (opcional)
pnpm run deploy pnpm run db:migrate:remote
- 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).
# 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.
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": "...." }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.
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}'GET /documents— lista de PDFs.DELETE /documents/:id— borra un documento y sus embeddings.GET /questionoGET /question/:id— observabilidad de workflows ejecutados.- MCP: consumir
/mcpcon un cliente MCP compatible para correrUPLOAD_PDF,LIST_PDFSoPDF_QUERY.
El worker monta MyMCP y registra:
UPLOAD_PDF: reutiliza la validación deZodpara cargar documentos.PDF_QUERY: ejecuta una consulta semántica sobre un documento específico usandoquerySchema.
Esto facilita demostrar composabilidad multi-agente desde un IDE como Claude Desktop, Postman o VS Code MCP.

