codacle.
DocsIniciá sesión →

Docs · 20

Arquitectura.

Monorepo Next.js + worker, Anthropic Managed Agents, Supabase Postgres + Storage. Cómo se hablan.

El monorepo

Codacle es un monorepo PNPM con tres paquetes principales:

PaqueteQué hace
apps/webNext.js 15 App Router. UI completa + server actions + scripts CLI (register-kit, cost-report, inspect-run, etc.).
apps/workerServicio long-running que consume jobs de Supabase y orquesta a Anthropic Managed Agents.
packages/dbSupabase client (supabaseAdmin()), Zod schemas para entidades compartidas, helpers de pricing (costUsd, PRICING_PER_MTOK).

El flujo end-to-end

[user]            [next.js]            [supabase]            [worker]            [anthropic]
   │                  │                     │                    │                     │
   ├─ crea ws ───────►│                     │                    │                     │
   │                  ├─ INSERT workspace ─►│                    │                     │
   │                  ├─ INSERT job analyze►│                    │                     │
   │                  │                     │◄─ poll jobs ───────┤                     │
   │                  │                     │                    ├─ create session ───►│
   │                  │                     │                    │◄── stream events ───┤
   │                  │                     │                    ├─ write vault_atoms ─┤
   │                  │                     │◄─ UPDATE ws.status─┤                     │
   │◄ revalidatePath ─┤                     │                    │                     │

Resumido:

  1. El user crea un workspace desde el marketplace.
  2. Next.js (server action createWorkspaceAndStart) inserta la row en workspaces y encola un job tipo analyze.
  3. El worker polleea jobs (interval corto), toma el job pendiente, abre una session en Anthropic, manda el agente del kit pinneado al workspace.
  4. El agente emite eventos (tool_use, text, report_phase, emit_atom). El worker traduce: emit_atom → INSERT en vault_atoms, report_phase → UPDATE en workspace_phases, etc.
  5. Cuando el agente cierra, el worker actualiza workspace.status. La UI hace polling de /api/workspaces/[id]/ops-state o phases y refresca live.

La tabla kits

Una row por (kit_id, version). El manifest (jsonb) tiene todo: agentes, skills, inputs, fases, tabs habilitadas, modelos a usar. Cuando registrás un kit con register-kit, la CLI:

  1. Lee el directorio del kit (<kit_dir>/manifest.yaml + skill files + agent definitions).
  2. Valida contra el schema Zod (apps/worker/src/lib/kit-manifest-schema.ts).
  3. Sube cada skill a Anthropic — devuelve un skl_... ID. Los guarda en el jsonb skill_ids.
  4. Crea un environment compartido — env_.... Lo guarda en columna propia (environment_id).
  5. Crea cada agent referenciando ese environment + skills — agent_.... Los guarda en agent_ids.
  6. Upsertea la row en kits con todos esos IDs.

kit_publications apunta a una versión concreta — workspaces nuevos usan esa. Cambiar de versión publicada es la operación de rollback / upgrade.

El worker en detalle

apps/worker/src/index.ts corre un loop que:

  1. Polleea SELECT * FROM jobs WHERE status='queued' LIMIT 1 FOR UPDATE SKIP LOCKED (Postgres lock evita doble proceso).
  2. Despacha al handler según job.type: analyze, map, migrate, kit_run.
  3. Cada handler abre una Session en Anthropic Managed Agents y stream-consumea sus eventos.
  4. Custom tools del agente (declarados en el kit) son dispatched por el worker — read_file, write_atom, report_phase, emit_output, etc. Las respuestas vuelven al agent por stop_reason.event_ids.
  5. Al cerrar la session: persiste usage + pricing_snapshot en workspace_runs para tener telemetría retroactiva estable cuando Anthropic cambie rates.

Telemetría y observabilidad

  • workspace_runs — una row por cada vez que el worker procesa un job. Tiene Anthropic IDs (session_id, agent_id, environment_id, memory_store_id), usage, duration_ms, status, pricing_snapshot. Base para /ops, /ops/[id], /ops/trends, /ops/errors, y el costo del /overview.
  • workspace_phases — el estado granular por fase. Lo escribe el worker al recibir report_phase events. /migrations/[id]/pipeline lee esto live.
  • vault_atoms — los entities extraídos. /migrations/[id]/vault lo navega.
  • messages — conversación de Barbara (el chat assistant). Persistido para context across sessions.

Caching

Server-side, usamos unstable_cache de Next con TTL cortas (30s) en lecturas que se pueden volver hot bajo polling — /ops/resources (Anthropic API) y listKitsCatalog son los principales. El catálogo de kits cambia raras veces; no hace falta golpear Supabase en cada request del marketplace.

revalidatePath se llama explícitamente desde los server actions que mutan datos relevantes (publishKitVersion, unpublishKit, createWorkspaceAndStart).