Hace unos meses empecé a preguntarme: ¿qué se necesita realmente para construir una plataforma de agentes autónomos desde cero, lista para producción? No un wrapper de chatbot o un proxy de API — sino un sistema donde agentes reales ejecutan comandos reales, orquestados por una máquina de estados, controlados por políticas y respaldados por memoria persistente.
La respuesta es CaS — CLI as a Service: una arquitectura de referencia totalmente implementada y ejecutable construida en TypeScript/NestJS. 136 tests, 8 fases, cero compromisos.
La Visión
La mayoría de las “plataformas de agentes” actuales son chatbots que generan texto. CaS fue diseñado para algo diferente: agentes que actúan — leen archivos, ejecutan comandos shell, lanzan GitHub Actions, procesan datos — todo dentro de un runtime controlado, auditado y gobernado por políticas.
Inspirado en Codex CLI y los agentes de desarrollo modernos, CaS permite que los agentes operen directamente sobre la infraestructura con niveles de autonomía configurables, manteniendo seguridad, trazabilidad y controles empresariales.
Arquitectura General
CaS está dividido en tres planos:
┌─────────────────────────────────────────────┐
│ Control Plane │
│ API Gateway │ Orchestrator │ Planner │
│ Policy Engine │ Tools Registry │ PlanStore │
├─────────────────────────────────────────────┤
│ Execution Plane │
│ Shell Runner │ CI/CD Runner │ Data Runner │
│ RunnerRegistry │ RunnerOrchestrator │
├─────────────────────────────────────────────┤
│ Memory Layer │
│ InMemoryStore (default) │ SQLite (driver) │
└─────────────────────────────────────────────┘
Todo el proyecto se construyó con mi flujo Spec-Driven Development (SDD) — un proceso estructurado con fases de exploración, especificación, diseño, implementación y verificación, cada una documentada como ADRs.
Control Plane
API Gateway
Servidor REST + WebSocket en :3000. Rutas principales:
| Ruta | Método | Descripción |
|---|---|---|
/goals | GET | Listar todos los objetivos |
/goals | POST | Crear un nuevo objetivo |
/goals/:id/plan | GET | Obtener plan de ejecución |
/memory | GET | Buscar en memoria |
/tools | GET | Listar herramientas registradas |
/health | GET | Health check del servidor |
Los eventos WebSocket (goal.created, goal.planned, goal.completed, goal.failed) mantienen a los clientes sincronizados en tiempo real.
Orchestrator
Una máquina de estados que gestiona el ciclo de vida de los Goals:
created → planned → running → completed
↘ failed
Cada transición emite eventos WebSocket y persiste en el PlanStore. El orquestador es el sistema nervioso central — recibe comandos de la API, coordina con el planner y despacha trabajo al Execution Plane.
Planner
Planificador basado en templates que crea planes de ejecución con pasos y mapeo de herramientas. Dada una descripción de objetivo, produce un plan estructurado que el orquestador puede ejecutar de forma determinista.
Policy Engine
Sistema de autorización de tres modos, configurado via la variable POLICY_MODE:
| Modo | Comportamiento |
|---|---|
ALLOW | Todas las operaciones permitidas |
DENY | Todas las operaciones bloqueadas |
REQUIRE_APPROVAL | Operaciones requieren aprobación explícita |
Esta es la capa de enforcement que separa a CaS de un simple ejecutor de scripts — guardrails de nivel empresarial sin sacrificar flexibilidad.
Tools Registry
8 herramientas seed, cada una con esquema, versionado y declaración de capacidades:
shell— ejecutar comandos shellread_file— leer archivoswrite_file— crear/sobrescribir archivossearch_files— operaciones grep/findplan— generar planes de ejecuciónreview— operaciones de code reviewdelegate_task— lanzar subagentesmemory— leer/escribir en el store de memoria
Execution Plane
Tres runners para diferentes contextos de ejecución:
| Runner | Descripción |
|---|---|
| Shell Runner | Ejecuta comandos shell con captura de stdout/stderr, timeout y reporte de estado |
| CI/CD Runner | Dispara workflows de GitHub Actions con tipos de evento, refs e inputs configurables |
| Data Runner | Ejecuta scripts Python de procesamiento de datos con captura de stdout y propagación de errores |
El RunnerRegistry gestiona el descubrimiento de runners, y el RunnerOrchestrator coordina la ejecución con lógica de reintento, asegurando aislamiento entre cargas de trabajo.
Memory Layer
Implementación dual via el token DI MEMORY_STORE:
In-Memory (default): respaldado por Map, efímero. Perfecto para desarrollo y tests — cero configuración, reset instantáneo.
SQLite (MEMORY_DRIVER=sqlite): respaldado por better-sqlite3, persistente entre reinicios. Almacena registros de objetivos completados y provee inyección de contexto para los planners.
Este diseño hace trivial intercambiar backends de almacenamiento sin tocar la lógica de negocio — un patrón clásico de Inyección de Dependencias que NestJS maneja elegantemente.
Dashboard
Un SPA con tema oscuro servido en http://localhost:3000/ con:
- Feed de objetivos en tiempo real via WebSocket (Socket.IO)
- Creación y seguimiento de objetivos
- Visualización de planes
- Búsqueda en memoria
- Conexión directa al API Gateway
El dashboard prueba que el sistema funciona end-to-end y provee un feedback loop visual durante el desarrollo.
CLI: El Comando cas
Un CLI con Commander.js + Chalk con 7 comandos:
cas health # Ver estado del servidor
cas goals list # Listar objetivos
cas goals get <id> # Ver detalle de objetivo (resolución parcial)
cas goals create <desc> # Crear nuevo objetivo
cas goals plan <id> # Generar plan para un objetivo
cas tools # Listar herramientas
cas memory <query> # Buscar en memoria
La resolución parcial de IDs es un detalle interesante — cas goals get abc encuentra el primer objetivo que empieza con abc, evitando tener que escribir UUIDs completos.
El CLI se publica como packages/cas-cli en el monorepo, instalable con un alias shell.
Stats & Testing
- Fases: 8 (0 a la 7), construidas con SDD workflow
- Tests: 136 pasando — tests unitarios para cada servicio, e2e para el API Gateway
- Archivos fuente: 40+ archivos TypeScript en el monorepo
- Docs: Bilingües (EN principal, traducciones
.es.md) — 7 docs de arquitectura + notas de investigación - ADRs: Architecture Decision Records documentando cada decisión de diseño importante
- Build: TypeScript + tsup, monorepo NestJS con pnpm workspaces
El Viaje SDD
CaS se construyó con el flujo Spec-Driven Development, fase por fase:
| Fase | Qué se hizo |
|---|---|
| 0 | Documentación de arquitectura, framework ADR, setup bilingüe |
| 1 | Control Plane MVP — API Gateway, Orchestrator, Planner, Policy Engine, Tools Registry |
| 2 | Execution Plane MVP — Shell, CI/CD, Data runners con orquestación |
| 3 | Memory Layer — interfaz abstracta IMemoryStore, impls in-memory + SQLite |
| 4 | Memoria SQLite persistente — integración better-sqlite3, diseño de esquema |
| 5 | Dashboard — SPA con WebSocket en tiempo real, UI de gestión de objetivos |
| 6 | CLI tooling — comando cas con Commander.js, resolución parcial de IDs |
| 7 | Cobertura e2e + estabilización — 136 tests, overhaul del README |
Cada fase incluyó un Judgment Day donde evaluaba si la arquitectura seguía siendo sólida antes de continuar.
Probarlo
git clone https://github.com/fxckcode/CaS.git
cd CaS/src/control-plane
pnpm install
pnpm build && node dist/main.js
# → Servidor en http://localhost:3000
# → Dashboard en http://localhost:3000/
# Memoria persistente (opcional)
MEMORY_DRIVER=sqlite node dist/main.js
# Ejecutar tests
pnpm test # 136 tests, 0 failures
# CLI (desde otra terminal)
cas health
cas goals create "Desplegar API v3"
El proyecto tiene licencia MIT y está disponible en GitHub. Ya sea que estés construyendo una plataforma de agentes para tu equipo o simplemente tengas curiosidad sobre cómo funcionan estos sistemas internamente, el código está ahí para leerlo, ejecutarlo y forkearlo.