CaS — CLI as a Service: An Executable Reference Architecture for Autonomous Agent Systems

A few months ago I started wondering: what does it actually take to build a production-grade autonomous agent platform from scratch? Not a chatbot wrapper or an API proxy — but a system where real agents execute real commands, orchestrated by a state machine, gated by policies, and backed by persistent memory.

The answer is CaS — CLI as a Service: a fully implemented, executable reference architecture built in TypeScript/NestJS. 136 tests, 8 phases, zero compromises.


The Vision

Most of today’s “agent platforms” are chatbots that generate text. CaS was designed for something different: agents that act — read files, run shell commands, dispatch GitHub Actions, process data — all inside a controlled, auditable, policy-governed runtime.

Inspired by Codex CLI and modern development agents, CaS lets agents operate directly on infrastructure with configurable autonomy levels, while maintaining security, audit trails, and enterprise policy controls.


Architecture Overview

CaS is split into three planes:

┌─────────────────────────────────────────────┐
│               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)   │
└─────────────────────────────────────────────┘

The entire project was built using my Spec-Driven Development (SDD) workflow — a structured process with exploration, specification, design, implementation, and verification phases, each documented as ADRs.


Control Plane

API Gateway

REST + WebSocket server on :3000. Routes include:

RouteMethodDescription
/goalsGETList all goals
/goalsPOSTCreate a new goal
/goals/:id/planGETRetrieve execution plan
/memoryGETSearch memory store
/toolsGETList registered tools
/healthGETServer health check

WebSocket events (goal.created, goal.planned, goal.completed, goal.failed) keep connected clients in sync in real time.

Orchestrator

A state machine managing the Goal lifecycle:

created → planned → running → completed
                            ↘ failed

Each transition emits WebSocket events and persists to the PlanStore. The orchestrator is the central nervous system — it receives commands from the API, coordinates with the planner, and dispatches work to the Execution Plane.

Planner

Template-based planner that creates execution plans with steps and tool mappings. Given a goal description, it produces a structured plan that the orchestrator can execute deterministically.

Policy Engine

Three-mode authorization system, configured via POLICY_MODE env var:

ModeBehavior
ALLOWAll operations permitted
DENYAll operations blocked
REQUIRE_APPROVALOperations require explicit approval

This is the enforcement layer that separates CaS from a simple script runner — enterprise-grade guardrails without sacrificing flexibility.

Tools Registry

8 seed tools, each with schema, versioning, and capability declarations:

  • shell — execute shell commands
  • read_file — read file contents
  • write_file — create/overwrite files
  • search_files — grep/find operations
  • plan — generate execution plans
  • review — code review operations
  • delegate_task — spawn subagents
  • memory — read/write memory store

Execution Plane

Three runners handle different execution contexts:

RunnerDescription
Shell RunnerExecutes shell commands with stdout/stderr capture, timeout enforcement, and status reporting
CI/CD RunnerDispatches GitHub Actions workflows with configurable event types, refs, and inputs
Data RunnerRuns Python data processing scripts with stdout capture and error propagation

The RunnerRegistry manages runner discovery, and the RunnerOrchestrator coordinates execution with retry logic, ensuring fault isolation between workloads.


Memory Layer

Dual implementation via the MEMORY_STORE DI token:

In-Memory (default): Map-backed, ephemeral. Perfect for development and testing — zero setup, instant reset.

SQLite (MEMORY_DRIVER=sqlite): better-sqlite3-backed, persistent across restarts. Stores goal completion records and provides context injection for planners.

This design makes it trivial to swap storage backends without touching business logic — a classic Dependency Injection pattern that NestJS handles elegantly.


Dashboard

A dark-themed SPA served at http://localhost:3000/ with:

  • Real-time goal feed via WebSocket (Socket.IO)
  • Goal creation and status tracking
  • Plan visualization
  • Memory search
  • Connects directly to the API Gateway

The dashboard proves the system works end-to-end and provides a visual feedback loop during development.


CLI: The cas Command

A Commander.js + Chalk CLI tool with 7 commands:

cas health              # Check server status
cas goals list          # List all goals
cas goals get <id>      # Get goal by ID (partial ID resolution)
cas goals create <desc> # Create a new goal
cas goals plan <id>     # Generate a plan for a goal
cas tools               # List available tools
cas memory <query>      # Search memory store

Partial ID resolution is a nice touch — cas goals get abc matches the first goal starting with abc, so you don’t need full UUIDs.

The CLI is published as packages/cas-cli in the monorepo, installable with a shell alias.


Stats & Testing

  • Phases: 8 (0 through 7), built with SDD workflow
  • Tests: 136 passing — unit tests for every service, e2e tests for the API Gateway
  • Source files: 40+ TypeScript files across the monorepo
  • Docs: Bilingual (EN primary, .es.md translations) — 7 architecture docs + research notes
  • ADRs: Architecture Decision Records documenting every major design choice
  • Build: TypeScript + tsup, NestJS monorepo with pnpm workspaces

The SDD Journey

CaS was built using the Spec-Driven Development workflow, phase by phase:

PhaseWhat
0Architecture documentation, ADR framework, bilingual setup
1Control Plane MVP — API Gateway, Orchestrator, Planner, Policy Engine, Tools Registry
2Execution Plane MVP — Shell, CI/CD, Data runners with orchestration
3Memory Layer — abstract IMemoryStore interface, in-memory + SQLite implementations
4Persistent SQLite memory — better-sqlite3 integration, schema design
5Dashboard — SPA with WebSocket real-time feed, goal management UI
6CLI tooling — cas command with Commander.js, partial ID resolution
7e2e coverage + stabilization — 136 tests, README overhaul

Each phase included a Judgment Day review where I assessed whether the architecture was still sound before proceeding.


Try It

git clone https://github.com/fxckcode/CaS.git
cd CaS/src/control-plane
pnpm install
pnpm build && node dist/main.js
# → Server on http://localhost:3000
# → Dashboard at http://localhost:3000/

# Enable persistent memory (optional)
MEMORY_DRIVER=sqlite node dist/main.js

# Run tests
pnpm test  # 136 tests, 0 failures

# CLI (from another terminal)
cas health
cas goals create "Deploy API v3"

The project is MIT licensed and available on GitHub. Whether you’re building an agent platform for your team or just curious about how these systems work under the hood, the code is there to read, run, and fork.

Share
D
Diego Duran
@fxckcode

Backend engineer who ships agentic CLI tooling. NestJS, Go, Django, AWS.

CaS — CLI as a Service: Una Arquitectura de Referencia Ejecutable para Sistemas de Agentes Autónomos

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:

RutaMétodoDescripción
/goalsGETListar todos los objetivos
/goalsPOSTCrear un nuevo objetivo
/goals/:id/planGETObtener plan de ejecución
/memoryGETBuscar en memoria
/toolsGETListar herramientas registradas
/healthGETHealth 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:

ModoComportamiento
ALLOWTodas las operaciones permitidas
DENYTodas las operaciones bloqueadas
REQUIRE_APPROVALOperaciones 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 shell
  • read_file — leer archivos
  • write_file — crear/sobrescribir archivos
  • search_files — operaciones grep/find
  • plan — generar planes de ejecución
  • review — operaciones de code review
  • delegate_task — lanzar subagentes
  • memory — leer/escribir en el store de memoria

Execution Plane

Tres runners para diferentes contextos de ejecución:

RunnerDescripción
Shell RunnerEjecuta comandos shell con captura de stdout/stderr, timeout y reporte de estado
CI/CD RunnerDispara workflows de GitHub Actions con tipos de evento, refs e inputs configurables
Data RunnerEjecuta 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:

FaseQué se hizo
0Documentación de arquitectura, framework ADR, setup bilingüe
1Control Plane MVP — API Gateway, Orchestrator, Planner, Policy Engine, Tools Registry
2Execution Plane MVP — Shell, CI/CD, Data runners con orquestación
3Memory Layer — interfaz abstracta IMemoryStore, impls in-memory + SQLite
4Memoria SQLite persistente — integración better-sqlite3, diseño de esquema
5Dashboard — SPA con WebSocket en tiempo real, UI de gestión de objetivos
6CLI tooling — comando cas con Commander.js, resolución parcial de IDs
7Cobertura 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.

Compartir
D
Diego Duran
@fxckcode

Ingeniero backend que construye herramientas CLI agentivas. NestJS, Go, Django, AWS.