Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions src/content/docs-es/agents.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
title: Agentes
description: "Despliega agentes de IA en una microVM aislada con QEMU: Hermes, terminal web, subida de ficheros y observabilidad."
description: "Despliega agentes de IA en una máquina privada en la nube aislada: Hermes, terminal web, subida de ficheros y observabilidad."
order: 19
group: Guías
---

# Agentes.

NaN Cloud te permite desplegar agentes de IA en tu propia **microVM**: una máquina virtual ligera con QEMU y KVM, con su propio kernel, su propio sistema de ficheros y acceso root completo. Aislada del host y del resto de miembros. El primer tipo de agente disponible es **Hermes**.
NaN Cloud te permite desplegar agentes de IA en tu propia **máquina privada en la nube**: una máquina virtual ligera con su propio kernel, su propio sistema de ficheros y acceso root completo. Aislada del host y del resto de miembros. El primer tipo de agente disponible es **Hermes**.

## Arquitectura

Cada agente corre dentro de su propia microVM de QEMU. En vez de compartir el kernel del host (como haría un contenedor normal), arranca con su propio kernel de Linux. La VM monta un disco ext4 de 20 GiB sobre un volumen persistente en modo bloque. Todo lo que hagas dentro (`apt install`, `pip install`, cambios en `/etc`, ficheros que subas) vive en ese disco y sobrevive a los reinicios.
Cada agente corre dentro de su propia máquina aislada. En vez de compartir el kernel del host (como haría un contenedor normal), arranca con su propio kernel de Linux. La máquina tiene su propio disco persistente de 20 GiB. Todo lo que hagas dentro (`apt install`, `pip install`, cambios en `/etc`, ficheros que subas) vive en ese disco y sobrevive a los reinicios.

El apagado es *limpio*: cuando reinicias o borras el agente, el sistema fuerza un `sync` y espera a que el journal de ext4 termine de volcarse antes de matar la VM. Sin corrupción.
El apagado es *limpio*: cuando reinicias o borras el agente, el sistema fuerza un `sync` y espera a que el disco termine de volcarse antes de parar la máquina. Sin corrupción.

## Hermes

Expand All @@ -31,7 +31,7 @@ Entra en [cloud.nan.builders/agents/new](https://cloud.nan.builders/agents/new)

### 3. Espera a que esté Running

Después de crear el agente, espera unos 30 segundos a que arranque la microVM, se formatee el disco por primera vez (`mkfs.ext4`) y se siembre el sistema de ficheros. El estado pasa a `Running` y Hermes a `Ready`.
Después de crear el agente, espera unos 30 segundos a que arranque la máquina, se prepare su disco por primera vez y se siembre el sistema de ficheros. El estado pasa a `Running` y Hermes a `Ready`.

### 4. Habla con tu agente

Expand All @@ -44,7 +44,7 @@ Busca tu bot en Telegram y mándale un mensaje. Hermes responderá con el modelo

## Console: terminal web

La pestaña **Console** abre una terminal interactiva (`bash --login`) dentro de tu microVM, sin necesidad de configurar SSH. El stream va por WebSocket con xterm.js: se redimensiona sola al ajustar el panel, tiene una pastilla de estado arriba a la derecha y un botón de reconexión por si se cae la sesión.
La pestaña **Console** abre una terminal interactiva (`bash --login`) dentro de la máquina de tu agente, sin necesidad de configurar SSH. El stream va por WebSocket con xterm.js: se redimensiona sola al ajustar el panel, tiene una pastilla de estado arriba a la derecha y un botón de reconexión por si se cae la sesión.

Casos de uso típicos:

Expand All @@ -58,7 +58,7 @@ Casos de uso típicos:

## Files: subida de ficheros

La pestaña **Files** permite subir ficheros a la microVM arrastrándolos o desde el selector. Admite varios a la vez, con cola secuencial y barra de progreso en vivo con MiB/s. Los ficheros aterrizan en `/persist/uploads/` y desde ahí puedes moverlos con la Console.
La pestaña **Files** permite subir ficheros a la máquina del agente arrastrándolos o desde el selector. Admite varios a la vez, con cola secuencial y barra de progreso en vivo con MiB/s. Los ficheros aterrizan en `/persist/uploads/` y desde ahí puedes moverlos con la Console.

- Tamaño máximo: **200 MiB** por fichero.
- Transporte: WebSocket con trozos de 256 KiB y backpressure de extremo a extremo.
Expand All @@ -70,8 +70,8 @@ La pestaña **Files** permite subir ficheros a la microVM arrastrándolos o desd
La pestaña **Observability** agrupa tres sub-pestañas:

- **Logs**: stream en vivo del stdout y stderr del agente por WebSocket. Búfer de las últimas 500 líneas en el cliente.
- **Events**: eventos del Pod de Kubernetes (BackOff, Scheduled, Pulled, Killing...) con tipo, motivo, mensaje, antigüedad y recuento. Se refresca solo cada 15s.
- **Metrics**: consumo real de CPU, RAM y disco frente a los límites configurados. CPU y RAM vía Prometheus (kubelet-cadvisor), disco con `df` dentro de la microVM (el sistema de ficheros es de modo bloque y kubelet no lo ve). Se refresca cada 10s.
- **Events**: eventos del ciclo de vida del agente (planificación, descarga de imágenes, reinicios, back-offs...) con tipo, motivo, mensaje, antigüedad y recuento. Se refresca solo cada 15s.
- **Metrics**: consumo real de CPU, RAM y disco frente a los límites configurados. La CPU y la RAM se miden desde fuera de la máquina y el disco desde dentro. Se refresca cada 10s.

## Web: exposición pública

Expand All @@ -93,21 +93,21 @@ Hermes incluye una UI web ligera ([nesquena/hermes-webui](https://github.com/nes

## Variables de entorno

La pestaña **Env** te permite añadir, editar y borrar variables de entorno del agente sin tocar el Deployment. Útil para inyectar API keys de terceros, configurar el comportamiento de Hermes, etc.
La pestaña **Env** te permite añadir, editar y borrar variables de entorno del agente sin tener que redesplegarlo tú. Útil para inyectar API keys de terceros, configurar el comportamiento de Hermes, etc.

Hay dos variables **protegidas** (solo se pueden editar, no borrar): `OPENAI_API_KEY` (tu key del clúster, que gestiona la plataforma) y `TELEGRAM_BOT_TOKEN`. El resto las puedes crear, editar o borrar libremente.

## Recursos y límites

Cada microVM se aprovisiona con:
La máquina de cada agente se aprovisiona con:

| Recurso | Request | Límite |
|---|---|---|
| CPU | 200m | 1 vCPU |
| RAM | 512 Mi | 2 GiB |
| Disco | (sin request) | 20 GiB (PVC en modo bloque) |
| CPU | 0,2 vCPU | 1 vCPU |
| RAM | 512 MiB | 2 GiB |
| Disco | (sin request) | 20 GiB (persistente) |

La CPU y la RAM son los límites máximos de la microVM; el consumo real suele quedar muy por debajo. El disco es persistente: todo lo que instales o modifiques (paquetes, ficheros, configuraciones) se conserva entre reinicios. Si el disco se llena (por encima del 90%), libéralo desde la Console (`du -sh /persist/*`).
La CPU y la RAM son los límites máximos de la máquina; el consumo real suele quedar muy por debajo. El disco es persistente: todo lo que instales o modifiques (paquetes, ficheros, configuraciones) se conserva entre reinicios. Si el disco se llena (por encima del 90%), libéralo desde la Console (`du -sh /persist/*`).

> **Límite actual**
> Ahora mismo cada miembro puede desplegar **1 agente en microVM**. Este límite se ampliará en versiones futuras.
> Ahora mismo cada miembro puede desplegar **1 agente**. Este límite se ampliará en versiones futuras.
2 changes: 1 addition & 1 deletion src/content/docs-es/hermes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Hay dos formas de tenerlo, y la primera no requiere configurar nada.

## Camino 1: desplegado en NaN Cloud

NaN Cloud despliega Hermes por ti en una **microVM propia**, y sale conectado al clúster de fábrica: la plataforma le inyecta tu clave y no tienes que tocar ninguna configuración de proveedor.
NaN Cloud despliega Hermes por ti en una **máquina privada en la nube propia**, y sale conectado al clúster de fábrica: la plataforma le inyecta tu clave y no tienes que tocar ninguna configuración de proveedor.

<Callout title="Esta es la vía corta">
Creas el agente desde el panel, eliges modelo, le das el token de tu bot de Telegram y ya está hablando. Está explicado paso a paso en [Agentes](/es/docs/agents), con capturas.
Expand Down
32 changes: 16 additions & 16 deletions src/content/docs/agents.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
title: Agents
description: "Deploy AI agents in an isolated microVM with QEMU: Hermes, web terminal, file uploads, and observability."
description: "Deploy AI agents in an isolated private cloud machine: Hermes, web terminal, file uploads, and observability."
order: 19
group: Guides
---

# Agents.

NaN Cloud lets you deploy AI agents in your own **microVM**: a lightweight virtual machine with QEMU + KVM, its own kernel, its own filesystem, and full root access. Isolated from the host and from other members. The first available agent type is **Hermes**.
NaN Cloud lets you deploy AI agents in your own **private cloud machine**: a lightweight virtual machine with its own kernel, its own filesystem, and full root access. Isolated from the host and from other members. The first available agent type is **Hermes**.

## Architecture

Each agent runs inside its own QEMU microVM. Instead of sharing the host kernel (like a regular container), it starts with its own Linux kernel. The VM mounts a 20 GiB ext4 disk on a block-mode persistent volume. Everything you do inside — `apt install`, `pip install`, edits to `/etc`, files you upload — lives on that disk and survives restarts.
Each agent runs inside its own isolated machine. Instead of sharing the host kernel (like a regular container), it starts with its own Linux kernel. The machine has its own 20 GiB persistent disk. Everything you do inside — `apt install`, `pip install`, edits to `/etc`, files you upload — lives on that disk and survives restarts.

Shutdown is *graceful*: when you restart or delete the agent, the system forces a `sync` and waits for the ext4 journal to finish flushing before killing the VM. No corruption.
Shutdown is *graceful*: when you restart or delete the agent, the system forces a `sync` and waits for the disk to finish flushing before stopping the machine. No corruption.

## Hermes

Expand All @@ -31,7 +31,7 @@ Go to [cloud.nan.builders/agents/new](https://cloud.nan.builders/agents/new) and

### 3. Wait for it to be Running

After creating the agent, wait ~30 seconds for the microVM to start, format the disk for the first time (`mkfs.ext4`), and seed the filesystem. The status changes to `Running` and Hermes to `Ready`.
After creating the agent, wait ~30 seconds for the machine to start, prepare its disk for the first time, and seed the filesystem. The status changes to `Running` and Hermes to `Ready`.

### 4. Chat with your agent

Expand All @@ -44,7 +44,7 @@ Find your bot on Telegram and send it a message. Hermes will respond using the m

## Console — web terminal

The **Console** tab opens an interactive terminal (`bash --login`) inside your microVM, without needing to configure SSH. The stream runs over WebSocket with xterm.js: auto-resize when you adjust the panel, status pill in the top right, and a reconnect button if the session drops.
The **Console** tab opens an interactive terminal (`bash --login`) inside your agent's machine, without needing to configure SSH. The stream runs over WebSocket with xterm.js: auto-resize when you adjust the panel, status pill in the top right, and a reconnect button if the session drops.

Typical use cases:

Expand All @@ -58,7 +58,7 @@ Typical use cases:

## Files — file uploads

The **Files** tab allows uploading files to the microVM with drag-and-drop or file picker. Multi-file, sequential queue, live progress bar with MiB/s. Files land in `/persist/uploads/` and from there you can move them with the Console.
The **Files** tab allows uploading files to the agent's machine with drag-and-drop or file picker. Multi-file, sequential queue, live progress bar with MiB/s. Files land in `/persist/uploads/` and from there you can move them with the Console.

- Max size: **200 MiB** per file.
- Transport: WebSocket with 256 KiB chunks and end-to-end backpressure.
Expand All @@ -70,8 +70,8 @@ The **Files** tab allows uploading files to the microVM with drag-and-drop or fi
The **Observability** tab groups three sub-tabs:

- **Logs** — live stream of the agent's stdout/stderr via WebSocket. Buffer of the last 500 lines on the client.
- **Events** — Kubernetes Pod events (BackOff, Scheduled, Pulled, Killing...) with type, reason, message, age, and count. Auto-refresh every 15s.
- **Metrics** — actual CPU, RAM, and disk usage against configured limits. CPU/RAM via Prometheus (kubelet-cadvisor), disk via `df` inside the microVM (the filesystem is block-mode, kubelet can't see it). Refreshes every 10s.
- **Events** — lifecycle events for the agent (scheduling, image pulls, restarts, back-offs...) with type, reason, message, age, and count. Auto-refresh every 15s.
- **Metrics** — actual CPU, RAM, and disk usage against configured limits. CPU and RAM are measured from outside the machine, disk usage from inside it. Refreshes every 10s.

## Web — public exposure

Expand All @@ -93,21 +93,21 @@ Hermes includes a lightweight web UI ([nesquena/hermes-webui](https://github.com

## Environment variables

The **Env** tab lets you add, edit, and delete agent environment variables without touching the Deployment. Useful for injecting third-party API keys, configuring Hermes behavior, etc.
The **Env** tab lets you add, edit, and delete agent environment variables without redeploying the agent yourself. Useful for injecting third-party API keys, configuring Hermes behavior, etc.

Two variables are **protected** (edit-only, no delete): `OPENAI_API_KEY` (your cluster key, managed by the platform) and `TELEGRAM_BOT_TOKEN`. The rest are free to create, edit, or delete.

## Resources and limits

Each microVM is provisioned with:
Each agent's machine is provisioned with:

| Resource | Request | Limit |
|---|---|---|
| CPU | 200m | 1 vCPU |
| RAM | 512 Mi | 2 GiB |
| Disk | — | 20 GiB (block-mode PVC) |
| CPU | 0.2 vCPU | 1 vCPU |
| RAM | 512 MiB | 2 GiB |
| Disk | — | 20 GiB (persistent) |

CPU and RAM are the microVM's maximum limits; actual usage is usually well below. Disk is persistent — everything you install or modify (packages, files, configurations) is preserved across restarts. If the disk fills up (90%+), free it from the Console (`du -sh /persist/*`).
CPU and RAM are the machine's maximum limits; actual usage is usually well below. Disk is persistent — everything you install or modify (packages, files, configurations) is preserved across restarts. If the disk fills up (90%+), free it from the Console (`du -sh /persist/*`).

> **Current limit**
> Currently each member can deploy **1 microVM agent**. This limit will be expanded in future versions.
> Currently each member can deploy **1 agent**. This limit will be expanded in future versions.
2 changes: 1 addition & 1 deletion src/content/docs/hermes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ There are two ways to have it, and the first one requires configuring nothing.

## Path 1: deployed on NaN Cloud

NaN Cloud deploys Hermes for you in **its own microVM**, and it comes connected to the cluster out of the box: the platform injects your key and you do not have to touch any provider configuration.
NaN Cloud deploys Hermes for you in **its own private cloud machine**, and it comes connected to the cluster out of the box: the platform injects your key and you do not have to touch any provider configuration.

<Callout title="This is the short way">
You create the agent from the panel, pick a model, give it your Telegram bot token, and it is already talking. It is explained step by step in [Agents](/docs/agents), with screenshots.
Expand Down
55 changes: 55 additions & 0 deletions src/tests/legal/noInfraDisclosure.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, expect, test } from 'vitest';
import { readdirSync, readFileSync, statSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';

/**
* Member-facing copy must not disclose how the platform is built underneath
* (virtualization stack, hypervisor, host names, backup tooling, hosting
* provider). Members read "workspace", "private cloud machine", "backups".
*
* Covers every docs page (EN + ES) and the legal pages. Kubernetes is not on
* the list on purpose: Spaces hand members a kubeconfig, so it is the product,
* not an implementation detail. LiteLLM is not either: the Claude Code guide
* tells members to run it on their own machine.
*/
const here = dirname(fileURLToPath(import.meta.url));
const src = resolve(here, '../..');

const FORBIDDEN =
/firecracker|micro-?vms?\b|qemu|\bkvm\b|kubelet|cadvisor|cloud-hypervisor|jailer|restic|hetzner|nan-eu0\d\d|\beu00\d\b|nan-vmd|\bkata\b/i;

function walk(dir: string): string[] {
return readdirSync(dir).flatMap((name) => {
const p = join(dir, name);
return statSync(p).isDirectory() ? walk(p) : [p];
});
}

const files = [
...walk(join(src, 'content/docs')),
...walk(join(src, 'content/docs-es')),
...['terms', 'privacy', 'cookies'].flatMap((page) => [
join(src, `pages/${page}.astro`),
join(src, `pages/es/${page}.astro`),
]),
].filter((p) => /\.(md|mdx|astro)$/.test(p));

describe('member-facing copy does not disclose infrastructure internals', () => {
test('there are pages to check', () => {
expect(files.length).toBeGreaterThan(20);
});

test.each(files.map((f) => [f.slice(src.length + 1), f]))('%s', (_rel, file) => {
const text = readFileSync(file, 'utf8');
const hit = text.match(FORBIDDEN);
expect(hit?.[0] ?? null).toBeNull();
});

test('the agents guide describes the machine in product terms', () => {
const en = readFileSync(join(src, 'content/docs/agents.md'), 'utf8');
const es = readFileSync(join(src, 'content/docs-es/agents.md'), 'utf8');
expect(en).toContain('your own **private cloud machine**');
expect(es).toContain('tu propia **máquina privada en la nube**');
});
});
Loading