Skip to main content
Glama

vanth

Trabajos en segundo plano basados en eventos para agentes.

Vanth es un demonio de trabajos en segundo plano local con una interfaz de Protocolo de Contexto de Modelo (MCP). Ejecuta comandos de shell no interactivos y desacoplados; captura su salida de forma duradera; analiza eventos estructurados opcionales AGENT_EVENT en barras de progreso, series de métricas y puntos de control; y puede reactivar una sesión de Codex o OpenCode cuando un trabajo necesita atención. Está diseñado para un único usuario de confianza en una sola máquina.

  • Cualquier comando: descargas, procesamiento de imágenes/audio, ETL, entrenamiento de ML — si se ejecuta en un shell, Vanth puede ejecutarlo de forma desacoplada y rastrearlo.

  • Durable: los trabajos y eventos residen en SQLite (WAL, timeout de ocupado) y sobreviven a reinicios del demonio, MCP y de la máquina.

  • Prioridad a eventos: los agentes usan job_wait para esperar eventos significativos en lugar de consultar registros.

  • Reactivación por atención: las entregas duraderas al menos una vez reanudan un hilo de Codex o una sesión de OpenCode cuando un trabajo necesita un humano o agente.

  • Panel de control en terminal: el monitor nativo en Go monitor muestra un panel en vivo estilo W&B-LEET con trabajos, métricas y gráficos.

Fuera del alcance para v1: acceso remoto a la red, TLS, tenencia multiusuario/RBAC, cuotas, stdin interactivo e interfaz web.

Para agentes: inicie un trabajo con job_start, luego use job_wait para esperar eventos progress/checkpoint/completed en lugar de consultar; haga que los trabajos emitan líneas AGENT_EVENT (abajo) para que el progreso, las métricas y los puntos de control aparezcan en vivo en el panel vanth-monitor; y deje que los trabajos largos lo reactiven a través de objetivos de reactivación en lugar de que usted tenga que consultar.


Inicio rápido

Instalación (requiere uv; funciona en Python 3.11+):

uv tool install vanth

Esto instala el servidor MCP vanth, el demonio vanthd, vanth-monitor y la CLI de operaciones como herramientas independientes (el paquete wheel incluye el monitor nativo en Go, por lo que no se necesita el entorno de Go).

Desde una copia del código fuente (desarrollo):

git clone https://github.com/abhim-dv/vanth.git && cd vanth
uv sync

Inicie el demonio (mantenga abierta esta terminal):

uv run vanthd

En una segunda terminal, inicie un trabajo rastreado a través del servidor MCP:

uv run vanth

o use las herramientas directamente desde un cliente MCP (consulte Integración con MCP).

Verifique que todo esté correcto:

job_doctor()

De principio a fin: ejecutar un trabajo rastreado

Una vez que el cliente MCP esté conectado, este es el ciclo completo:

job_start(
  command="uv run python examples\\long_job.py",
  name="demo run",
  notify_on=["checkpoint", "failed", "completed"],
)
# -> job_<id>

job_wait(job_id="job_<id>", filters=["checkpoint"], timeout_seconds=120)
# -> returns the first checkpoint event + current status

job_wait(job_id="job_<id>", filters=["completed", "failed"], timeout_seconds=300)
# -> returns the terminal event + exit code

Y en una tercera terminal, vigílelo en vivo:

uv run vanth-monitor

Puntos de entrada de línea de comandos

Comando

Propósito

uv run vanth

Servidor MCP stdio (puente hacia el demonio); también subcomandos status / doctor / restart

uv run vanthd

El demonio HTTP en segundo plano

uv run vanth-monitor

Panel de control en terminal en vivo (binario Go, incluido en el wheel)

uv run vanth-codex-notify

Adaptador de entrega: lee una carga útil de reactivación desde stdin, la envía a Codex

CLI de operaciones

uv run vanth status              # is the daemon up? pid, schema, running jobs, deliveries
uv run vanth status --json       # machine-readable version
uv run vanth doctor              # full health report (same as job_doctor, human-readable)
uv run vanth restart             # gracefully stop + start the daemon (jobs survive)
uv run vanth setup               # register the MCP server in your clients' configs
uv run vanth setup --remove      # unregister it

vanth restart es la forma confiable de aplicar una actualización de código/versión: envía al demonio una señal de apagado ordenado a través de loopback, espera a que el proceso anterior libere completamente el bloqueo del directorio de inicio, luego inicia un nuevo demonio. Los trabajos en curso pertenecen a ejecutores desacoplados, por lo que continúan durante el reinicio.


Related MCP server: Background Process MCP

Cómo funciona

MCP client / HTTP client
        |
        v
   vanthd (localhost HTTP daemon, bearer-token auth)
        |                 |                    |
        |                 |                    +---> wake adapters
        |                 |                          (local_command / codex_thread / opencode_thread)
        |                 |
        |                 +----> jobs.sqlite (durable source of truth)
        |
        +----> vanth.runner (detached worker process)
                    |
                    +----> your command (own process group)
                              |
                              +----> stdout/stderr -> logs/ + AGENT_EVENT parsing

Reglas de propiedad:

  • el ejecutor posee el comando real, su timeout y el vaciado de flujos;

  • el demonio posee el mantenimiento, el envío de entregas, las solicitudes API y la recuperación;

  • SQLite es la fuente de verdad a través de reinicios del proceso;

  • los clientes MCP y HTTP nunca necesitan estar activos para que los trabajos continúen.

Un trabajo no se considera terminal hasta que ambos flujos de salida han llegado a EOF y todos los eventos estructurados se han almacenado.

Ciclo de vida del trabajo

Un trabajo pasa por un pequeño conjunto de estados. Los estados terminales son permanentes.

Estado

Significado

running

Carga de trabajo lanzada; el ejecutor está transmitiendo salida y latidos

completed

El comando terminó con código 0, flujos vaciados, eventos almacenados

failed

El comando terminó con código distinto de cero

timeout

El comando superó timeout_seconds; el ejecutor lo terminó

cancelled

Se emitió job_stop y el árbol de procesos se terminó realmente

orphaned

El ejecutor murió inesperadamente (fallo); nunca se descarta silenciosamente

El ejecutor aplica timeout_seconds incluso a través de reinicios del demonio. En la recuperación, un trabajo running cuyo ejecutor ha desaparecido se marca como cancelled (si se solicitó una detención) o orphaned (si no) — nunca se deja como una fila running zombie.


Instalación del servidor MCP

vanth es el servidor MCP stdio. Se comunica con el demonio, iniciándolo automáticamente en el primer uso si aún no está en ejecución.

Configuración única

Después de instalar la herramienta, conéctela a los clientes MCP de su máquina en un solo paso:

uv tool install vanth
vanth setup

vanth setup detecta sus clientes instalados (opencode, Codex y clientes genéricos de estilo mcpServers como Claude Code / Cursor), muestra lo que encontró, hace una copia de seguridad de cada configuración antes de modificarla (.vanth-setup-<ts>.bak) e inserta la entrada MCP de Vanth — dejando intactas todas las demás configuraciones y comentarios.

vanth setup                  # detect + configure everything found (prompts)
vanth setup --yes            # apply without prompting (scripts/CI)
vanth setup opencode codex   # only specific clients
vanth setup --json           # machine-readable result
vanth setup --remove         # remove the Vanth MCP entries instead

Configuraciones que gestiona:

Cliente

Archivo

Sección

opencode

~/.config/opencode/opencode.json

mcp.vanth

Codex

~/.codex/config.toml

[mcp_servers.vanth]

Claude Code / Cursor

~/.claude.json

mcpServers.vanth

Manualmente, las mismas entradas son:

opencode

Agregue a ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "vanth": {
      "type": "local",
      "command": ["vanth"],
      "enabled": true,
      "timeout": 15000
    }
  }
}

Desde una copia del código fuente, use uv directamente en lugar de un vanth simple:

{
  "mcp": {
    "vanth": {
      "type": "local",
      "command": ["uv", "run", "--directory", "/path/to/vanth", "vanth"],
      "enabled": true,
      "timeout": 15000
    }
  }
}

Verifique la conexión y las herramientas:

opencode mcp list

Clientes MCP estilo Claude (mcpServers)

Wheel publicado:

{
  "mcpServers": {
    "vanth": { "command": "vanth", "env": { "VANTH_HOME": "C:/Users/you/.vanth" } }
  }
}

Desde una copia del código fuente:

{
  "mcpServers": {
    "vanth": {
      "command": "uv",
      "args": ["--directory", "/path/to/vanth", "run", "vanth"],
      "env": { "VANTH_HOME": "C:/Users/you/.vanth" }
    }
  }
}

Configuración del directorio de inicio del demonio

Tanto el servidor MCP como el demonio resuelven la misma raíz de estado desde VANTH_HOME (por defecto %USERPROFILE%\.vanth en Windows, ~/.vanth en Unix; AGENT_BG_HOME se acepta como alias). Si ambos están configurados, deben resolverse en el mismo directorio.


Instrumentación de trabajos con agent_event

Cualquier script de Python puede emitir eventos estructurados a stdout (o stderr) que Vanth analiza y el monitor grafica. Esto es opcional — los scripts simples aún se ejecutan y registran — pero es lo que convierte un trabajo en un objeto rastreado de primera clase.

from vanth.agent_events import agent_event, progress

# A checkpoint: something meaningful happened.
agent_event("checkpoint", "epoch complete", epoch=10, val_loss=0.42)

# A progress update: drives the progress bar and progress.* plots.
progress(10, 100, unit="epoch", stage="train", message="10/100 epochs")

# Arbitrary scalar metrics: become their own line plots.
agent_event("metric", _step=10, loss=0.42, acc=0.88, mbps=12.4)

Notas:

  • el helper imprime AGENT_EVENT {json} con flush=True (el vaciado es importante);

  • progress(current, total, unit=..., stage=...) calcula percent por usted;

  • cargas útiles de metric: los campos numéricos se convierten en series; _step (si está presente y es numérico) es el eje x; de lo contrario, se usa el número de secuencia del evento; las claves que comienzan con _ distintas de _step se ignoran; los booleanos no son métricas; los valores NaN/Infinity/null se omiten y se cuentan en la insignia de advertencia del monitor;

  • cualquier otro campo (por ejemplo, file, stage, phase) se conserva y es visible en la tabla de eventos exactos.

Ejemplo: un descargador rastreado

# downloader.py
import os
from vanth.agent_events import agent_event, progress

files = ["a.bin", "b.bin", "c.bin"]
total = sum(os.path.getsize(f) for f in files)
done = 0

for f in files:
    agent_event("checkpoint", f"starting {f}", file=f)
    # ... download f ...
    done += os.path.getsize(f)
    progress(done, total, unit="bytes", stage="download",
             message=f"{done}/{total} bytes")

Ejemplo: un lote de procesamiento de imágenes

from vanth.agent_events import agent_event, progress

images = list(find_images("input/"))
for i, img in enumerate(images, 1):
    out = process(img)                    # resize, denoise, ...
    agent_event("metric", _step=i, sharpness=out.sharpness, size_mb=out.size_mb)
    progress(i, len(images), unit="images", stage="process", message=img.name)

Registro temporal y con niveles con loguru

Vanth incluye un envoltorio para loguru que envía cada registro a una línea AGENT_EVENT estructurada, de modo que los registros aparecen como eventos con marca de tiempo y nivel en la tabla de eventos (con la insignia de nivel y marcas de tiempo exactas) en lugar de texto sin formato:

from vanth.agent_logger import logger, log_with_context

logger.info("training started", lr=8e-5, batch_size=8)     # event type "log", level info
logger.warning("low disk", free_gb=2.5)
log_with_context("error", "failed to load checkpoint", path="best.pt")

Cada llamada emite AGENT_EVENT {"type":"log","level":"info","message":"...","data":{...}} que el demonio persiste como un evento duradero. data lleva contexto adicional. El monitor los muestra en la tabla de eventos exactos junto con los eventos metric/progress.


Referencia de herramientas (las 20 herramientas MCP)

Herramienta

Propósito

job_start

Lanzar un comando como un trabajo desacoplado

job_rerun

Relanzar un trabajo con su comando/env/cwd/objetivos originales

job_wait

Bloquear hasta que llegue un evento coincidente (o timeout) — la forma preferida de esperar trabajos

job_status

Estado, comando, env, progreso, último evento, vinculación, etiquetas de un trabajo

job_list

Trabajos recientes, filtrables por status / thread_id / name / tags

job_view

Resúmenes orientados al agente ordenados por prioridad de atención

job_events

Eventos estructurados de un trabajo (hacia adelante mediante since_event_id, o los más recientes primero con reverse)

job_tail

Cola limitada de stdout/stderr con desplazamientos de bytes

job_metrics_query

Leer series de métricas escalares almacenadas (pérdida, precisión, progress.percent, ...)

job_metric_compare

Comparar una métrica entre trabajos (último/medio/mín/máx/suma/recuento)

job_run_summary

Resumen de una sola llamada "¿funcionó?" — estado, tiempo de ejecución, progreso, métricas, artefactos

job_artifact_add

Adjuntar un artefacto (punto de control, CSV, salida) a un trabajo

job_artifacts

Listar artefactos adjuntos a un trabajo

job_dashboard

Vista de datos de gráfico submuestreados para cualquier renderizador

job_deliveries

Entregas de reactivación para un trabajo, filtrables por status

job_mark_delivery

Establecer manualmente el estado de una entrega

job_retry_delivery

Reencolar una entrega fallida para su envío

job_delivery_attempts

Historial de intentos/arrendamiento de una entrega

job_stop

Detener un trabajo en ejecución (terminar el árbol de procesos)

job_doctor

Salud del demonio, esquema, tablas, disponibilidad de binarios

job_cleanup

Eliminación en seco o real de trabajos terminales antiguos

job_start

job_start(
  command="uv run python examples\\long_job.py",
  name="training run",
  cwd="F:\\git\\project",            # optional
  env={"CUDA_VISIBLE_DEVICES": "0"}, # optional
  timeout_seconds=3600,              # optional; None = no timeout
  notify_on=["progress","checkpoint","failed","completed"],
  origin_thread_id="019f...",        # the agent thread that launched it
  tags=["training","gpu"],           # optional
  wake_targets=[...]                 # optional, see below
)

Devuelve job_id, status, worker_pid y las rutas de log/eventos.

job_status — ver qué está ejecutando un trabajo

job_status(job_id="job_...")

Devuelve estado, comando, cwd, env, timeout_seconds, notas, ejecución (autor, hostname, SO, versión de Python, CPU/GPU, repo git/rama/commit), runtime_seconds, progreso, último evento, vinculación de hilo, etiquetas y código de salida. Esta es la forma más rápida para que un agente responda "¿qué está haciendo este trabajo?" — y refleja la visión general de una ejecución en W&B.

Pase notes="..." a job_start para anotar una ejecución ("¿qué hace especial esta ejecución?"), que se conserva en job_rerun y se muestra en el monitor.

job_rerun — relanzar un trabajo fallido

job_rerun(job_id="job_...")

Relanza el trabajo con su comando, cwd, env, timeout, nombre, etiquetas, hilo de origen y objetivos de reactivación originales — se devuelve un nuevo job_id. Úselo para reintentar una descarga fallida, un lote de procesamiento inestable o un fallo transitorio sin reconstruir la solicitud.

job_list — filtrar por nombre o etiqueta

job_list(status=["running"], name="train", tags=["gpu"], limit=20)

Filtros: status (lista), thread_id, name (subcadena), tags (debe contener todas las etiquetas listadas).

job_events — hacia adelante o más recientes primero

job_events(job_id="job_...", since_event_id="evt_...", limit=20)      # events after the cursor
job_events(job_id="job_...", reverse=true, limit=20)                   # the 20 newest events, newest first

reverse: true devuelve los eventos más recientes (los más nuevos primero) — ideal para "¿qué pasó recientemente?" — y se puede combinar con since_event_id para paginar hacia atrás.

job_wait — el núcleo del uso del agente

job_wait(job_id="job_...", filters=["checkpoint","failed","completed"], timeout_seconds=3600)
  • Espera el primer evento que coincida con cualquier filtro, devolviéndolo con el estado actual;

  • pasa since_event_id para esperar solo eventos más recientes que el que ya viste;

  • en caso de tiempo de espera, devuelve result: "timeout"; en caso de apagado del daemon, devuelve result: "shutdown".

job_view — qué mostrar al usuario

job_view(thread_id="019f...", limit=20)

Devuelve resúmenes compactos ordenados por prioridad de atención: primero los trabajos en ejecución y fallidos, luego los trabajos con entregas pendientes/fallidas, y luego todo lo demás. Cada entrada incluye estado, progreso, el último evento, enlace de hilos, etiquetas y recuentos de entregas.

job_stop — detener un trabajo en ejecución

job_stop(job_id="job_...", signal="terminate", kill_after_seconds=10)

Termina el árbol de procesos del trabajo. Primero se envía una signal (por defecto terminate); si el trabajo no ha salido después de kill_after_seconds, se mata. El trabajo pasa a cancelled solo después de que el árbol de carga de trabajo haya terminado realmente; de lo contrario, permanece running y la detención se puede reintentar.

job_mark_delivery / job_retry_delivery — control manual de entregas

job_mark_delivery(delivery_id="del_...", status="delivered", error="optional reason")
job_retry_delivery(delivery_id="del_...")   # requeue a failed delivery

job_mark_delivery establece el estado de una entrega manualmente (por ejemplo, después de resolver un problema del adaptador); job_retry_delivery vuelve a poner en cola una entrega fallida para el siguiente pase de despacho. job_delivery_attempts muestra el historial de reclamaciones/arrendamientos.

job_cleanup — eliminar trabajos terminales antiguos

job_cleanup(older_than_seconds=86400, dry_run=true)   # preview
job_cleanup(older_than_seconds=86400, dry_run=false)  # delete

Elimina trabajos terminales más antiguos que el límite: registros, espejos de eventos, especificaciones, entregas, intentos, objetivos de activación, eventos y luego la fila del trabajo. Los trabajos en ejecución nunca se seleccionan. La ejecución en seco es completamente de solo lectura. La limpieza es segura de repetir.

job_metrics_query — leer series escalares almacenadas

job_metrics_query(job_id="job_...", metric="loss", from_ms=..., to_ms=..., limit=1000)

Devuelve la serie almacenada para un trabajo, agrupada por nombre de métrica. metric filtra a una sola serie (por ejemplo, loss, acc, progress.percent); from_ms/to_ms filtran por marca de tiempo del evento (época en milisegundos). Los puntos están ordenados por secuencia de eventos. Este es el lado de lectura de los datos del monitor terminal.

job_metric_compare — comparar una métrica entre ejecuciones

job_metric_compare(job_ids=["job_a", "job_b"], metric="val_loss", aggregation="min")

Compara una métrica entre trabajos (por ejemplo, val_loss entre semillas o configuraciones). aggregation es latest, mean, min, max, sum o count; el resultado incluye el valor por trabajo más los puntos primero/último. Esta es la primitiva "qué ejecución ganó" al estilo W&B.

job_run_summary — ¿funcionó?

job_run_summary(job_id="job_...")

Una llamada devuelve estado, nombre, tiempo de ejecución, código de salida, progreso más reciente, notas, resumen por métrica (último/primero/mín/máx/recuento) y artefactos adjuntos: la forma más rápida para que un agente informe sobre un trabajo finalizado.

job_artifact_add / job_artifacts — adjuntar salidas

job_artifact_add(job_id="job_...", name="best.pt", uri="file:///...", kind="checkpoint",
                 size_bytes=..., sha256="...", meta={"epoch": 5})
job_artifacts(job_id="job_...")

Adjunta artefactos (puntos de control, CSVs, salidas renderizadas) a un trabajo para que aparezcan en job_run_summary y se puedan recuperar más tarde. meta es JSON de formato libre.

job_dashboard — datos de gráficos para cualquier renderizador

job_dashboard(job_ids=["job_..."], limit=5000)

Devuelve la lista de trabajos más cada serie de métricas almacenada, submuestreada a limit puntos por serie: los mismos datos que grafica el monitor terminal Go, expuestos a través de HTTP/MCP para que cualquier cliente (un futuro panel web/nube) pueda renderizarlos.


Objetivos de activación (activar un agente cuando un trabajo necesita atención)

Cuando un trabajo emite un evento coincidente, el daemon crea una entrega duradera y la despacha a través del adaptador. La entrega es al menos una vez; cada carga útil lleva un delivery_id para desduplicación.

local_command

Ejecuta un comando arbitrario, pasando la carga útil de la entrega como JSON en stdin:

{
  "type": "local_command",
  "events": ["checkpoint", "failed", "completed"],
  "command": ["python", "deliver.py"]
}

La salida con código 0 marca la entrega como delivered; cualquier otra salida la marca como failed.

codex_thread

Reanuda un hilo de Codex a través del servidor de aplicaciones local:

{
  "type": "codex_thread",
  "thread_id": "019f...",
  "events": ["checkpoint", "failed", "completed"],
  "codex_command": ["C:\\codex\\codex.exe"]
}

Protocolo: initialize -> thread/resume -> turn/start.

opencode_thread

Reanuda una sesión de OpenCode:

{
  "type": "opencode_thread",
  "thread_id": "ses_...",
  "events": ["checkpoint", "failed", "completed"],
  "cwd": "F:\\git\\project",
  "opencode_command": ["opencode"],     # override the binary
  "attach": "http://127.0.0.1:4096",    # submit via an opencode serve instance
  "timeout_seconds": 120
}

El tiempo de espera predeterminado para un turno de OpenCode es de 30 segundos; auméntalo para turnos largos.

Opciones de entrega compartidas

{
  "type": "codex_thread",
  "thread_id": "019f...",
  "events": ["checkpoint"],
  "auto_dispatch": false,      // leave the delivery pending for manual inspection
  "max_attempts": 3,           // default 1
  "retry_delay_seconds": 5,    // default 5
  "timeout_seconds": 30        // adapter timeout; also sizes the delivery lease
}

Con auto_dispatch: false, las entregas permanecen pending hasta que un agente las despache manualmente o cambie el objetivo.

Operaciones de entrega

job_deliveries(job_id="job_...")
job_delivery_attempts(delivery_id="del_...")
job_retry_delivery(delivery_id="del_...")     # requeue a failed delivery
job_mark_delivery(delivery_id="del_...", status="delivered")

El historial de intentos registra el token de reclamación, las horas de inicio/fin, el estado y si el intento fue reclamado después de un arrendamiento vencido. Si el daemon falla después de que un adaptador acepta una activación pero antes de que Vanth registre el éxito, la entrega se reclama y se reintenta, apareciendo como un intento reclaimed en lugar de reclamado como una entrega exactamente una vez.


Ejecutar el daemon

En primer plano (para desarrollo o diagnóstico):

uv run vanthd

Opciones de inicio al iniciar sesión:

  • Windows: el daemon se inicia desde la carpeta de Inicio del usuario (startup_commands.bat) junto con otros comandos de inicio; también hay una plantilla de acción del Programador de tareas en deploy/vanthd.cmd.

  • Unix: deploy/vanthd.service es un servicio de usuario de systemd.

Habilita solo un daemon por VANTH_HOME. Un segundo daemon para el mismo hogar sale inmediatamente (bloqueo a nivel de SO). El daemon se vincula solo a loopback (127.0.0.1 / ::1 / localhost); se rechaza un VANTH_DAEMON_HOST que no sea loopback.

Seguridad

  • Cada ruta de datos requiere Authorization: Bearer <token>; el token se genera por hogar y nunca se registra. GET /health es la única ruta no autenticada (una sonda de actividad económica para supervisores).

  • Al iniciar el daemon, el directorio de estado se reajusta al propietario: Unix chmod 0700/0600; Windows deshabilita la herencia de ACL y otorga solo al propietario, SYSTEM y Administradores a través de icacls. Esto bloquea que otras cuentas (por ejemplo, usuarios de sandbox/CI que heredan lectura del perfil de usuario) lean el token o los datos de especificación/env por trabajo.

  • En Windows, el socket SO_REUSEADDR está deshabilitado para que un segundo daemon no pueda convertirse en un oyente fantasma en el mismo puerto; un enlace fallido libera el bloqueo del hogar y sale limpiamente.

El monitor terminal Go

El panel nativo de Go lee el mismo hogar solo lectura y renderiza gráficos en vivo, barras de progreso, la tabla de eventos exacta y colas de registros:

uv run vanth-monitor

Desde una rueda construida, vanth-monitor ejecuta el binario nativo incluido (no se necesita cadena de herramientas Go). Desde un checkout de código fuente, construye el monitor en el primer uso y lo almacena en caché en ~/.cache/vanth/ (requiere go en PATH):

go build -o bin\vanth.exe ./cmd\vanth
bin\vanth.exe monitor

Teclas: arriba/abajo o j/k seleccionan trabajos · enter fija la serie de un trabajo · e tabla de eventos · l cola de registros · +/- acercan/alejan un gráfico · [/] panorámica · t vuelve a la cola en vivo · ? ayuda · q o Ctrl+C salir.


Referencia de configuración

Variables de entorno (los valores predeterminados viven en src/vanth/server.py, src/vanth/daemon.py, src/vanth/migrations.py):

Variable

Valor predeterminado

Propósito

VANTH_HOME

~/.vanth

Raíz de estado (alias: AGENT_BG_HOME)

VANTH_DAEMON_URL

http://127.0.0.1:8765

Dónde los clientes alcanzan al daemon

VANTH_DAEMON_HOST

127.0.0.1

Dirección de enlace (solo loopback)

VANTH_DAEMON_PORT

8765

Puerto de enlace

VANTH_MAX_REQUEST_BYTES

1 MiB

Límite del cuerpo de solicitud HTTP

VANTH_MAX_RESPONSE_BYTES

4 MiB

Límite de respuesta HTTP

VANTH_MAX_EVENT_BYTES

64 KiB

Límite de carga útil de evento único

VANTH_MAX_EVENT_LINE_BYTES

1 MiB

Límite de línea AGENT_EVENT

VANTH_MAX_LOG_BYTES

10 MiB

Límite de registro por flujo (el drenaje continúa)

VANTH_MAX_EVENTS_PER_JOB

100000

Límite de eventos estructurados por trabajo

VANTH_DELIVERY_POLL_INTERVAL

0.2s

Cadencia del bucle de mantenimiento

VANTH_DELIVERY_LEASE_MARGIN

5s

Tiempo de arrendamiento adicional más allá del tiempo de espera del adaptador

VANTH_RUNNER_HEARTBEAT_INTERVAL

1s

Latido de actividad del ejecutor

VANTH_RUNNER_HEARTBEAT_STALE_AFTER

10s

Umbral de caducidad del latido

VANTH_CODEX_BIN

codex / C:\codex\codex.exe

Binario de Codex

VANTH_OPENCODE_BIN

opencode (vía shutil.which)

Binario de OpenCode

VANTH_LOG_LEVEL

INFO

Nivel de registro del daemon

VANTH_LOG_MAX_BYTES

5 MiB

Tamaño de registro rotatorio del daemon

VANTH_LOG_BACKUP_COUNT

3

Recuento de rotación de registros del daemon

VANTH_BUSY_TIMEOUT_MS

30000

Espera de bloqueo de escritura SQLite


Operaciones

Diseño del estado

~/.vanth/
  jobs.sqlite      durable jobs (incl. env, notes, run-overview) / events / deliveries / targets / attempts / tombstones
  token            bearer token (owner-only permissions)
  daemon.lock      single-daemon OS lock
  daemon.json      discovery metadata (url, pid, started_at, schema) — written atomically, removed on graceful shutdown
  logs/            daemon.log + per-job runner/stdout/stderr logs
  events/          per-job JSONL event mirrors (monitor fallback source)
  specs/           per-job launch specs (removed once the runner starts)
  backups/         pre-migration SQLite backups

Salud, preparación y diagnóstico

job_doctor()

Informa el directorio de estado, las tablas de la base de datos, los recuentos de entregas por estado, la versión del esquema, PRAGMA quick_check, los arrendamientos de entrega caducados, el disco libre, la ruta del token y si los binarios de Codex/OpenCode se resuelven. Nunca revela el token.

El daemon HTTP también expone:

  • GET /health — sonda de actividad económica y no autenticada para supervisores;

  • GET /ready — preparación autenticada (informe de diagnóstico; 503 cuando no está bien).

Actualizaciones y copias de seguridad

Los cambios de esquema son migraciones SQLite ordenadas. Antes de la primera migración de una base de datos existente, se escribe una copia de seguridad con marca de tiempo en backups/ a través de la API de copia de seguridad de SQLite (nunca una copia de archivo sin procesar mientras WAL está activo). Para actualizar manualmente, copia primero el backups/*.sqlite más reciente. Un esquema de base de datos futuro es rechazado sin tocar los archivos.


API HTTP (equivalente a las herramientas MCP)

Autenticado con Authorization: Bearer <token>.

Método

Ruta

Propósito

GET

/jobs

Listar trabajos (status, limit, thread_id, name, tags)

POST

/jobs

Iniciar un trabajo

POST

/jobs/{id}/rerun

Reejecutar un trabajo con su configuración original

GET

/jobs/{id}/status

Estado del trabajo (incluye comando/env/cwd)

GET

/jobs/{id}/events

Eventos (since_event_id, types, limit, reverse)

GET

/jobs/{id}/metrics

Series de métricas (metric, from_ms, to_ms, limit)

GET

/jobs/{id}/summary

Resumen de ejecución (estado, tiempo de ejecución, métricas, artefactos)

GET

/jobs/{id}/artifacts

Artefactos (limit)

POST

/jobs/{id}/artifacts

Añadir un artefacto

GET

/metrics/compare

Comparar métrica entre trabajos (job_ids, metric, aggregation)

GET

/dashboard

Datos de gráfico (job_ids, limit)

GET

/jobs/{id}/tail

Cola de registro (stream, max_bytes, offset)

POST

/jobs/{id}/wait

Esperar un evento

POST

/jobs/{id}/stop

Detener un trabajo

GET

/view

Vista del agente (thread_id, limit)

GET

/deliveries

Entregas (job_id, status, limit)

GET

/deliveries/{id}/attempts

Historial de intentos

POST

/deliveries/{id}/mark

Marcar una entrega

POST

/deliveries/{id}/retry

Reintentar una entrega

POST

/cleanup

Limpieza (older_than_seconds, dry_run)

GET

/doctor

Informe de salud

GET

/health

Vitalidad no autenticada


Consejos de uso del agente

  1. Espera, no consultes repetidamente. Usa job_wait(job_id, filters=[...], timeout_seconds=...) en lugar de hacer un bucle con job_status. El daemon despierta la espera inmediatamente cuando se persiste un evento coincidente.

  2. Pasa since_event_id al siguiente job_wait después de manejar un evento, para que nunca vuelvas a procesar uno antiguo.

  3. Etiqueta y encadena tus trabajos. Establece origin_thread_id (el hilo del agente que lanzó el trabajo) y tags; usa job_view(thread_id=...) para resumir.

  4. Prefiere job_view sobre job_status al presentar una situación a un usuario — ya está ordenado por prioridad de atención.

  5. Haz que los trabajos se autodescriban. Emite líneas AGENT_EVENT progress / checkpoint / metric (ver arriba). Los trabajos silenciosos aún funcionan, pero los trabajos rastreados son mucho más fáciles de entender.

  6. Usa objetivos de activación para trabajos largos. Si una ejecución de entrenamiento o una descarga larga necesita una decisión en un punto de control, añade un objetivo codex_thread o opencode_thread con events: ["checkpoint", "failed", "completed"] para que el agente se reanude en lugar de consultar repetidamente.

  7. Inspecciona fallos de entrega. job_delivery_attempts muestra el historial de arrendamiento/reclamación; job_retry_delivery vuelve a encolar una fallida después de corregir la causa.

  8. Establece un timeout_seconds razonable en job_start para que un comando colgado pase a estado timeout (terminal) en lugar de ejecutarse para siempre; el ejecutor lo aplica incluso tras reinicios del daemon.

  9. Limpia el estado antiguo con job_cleanup(older_than_seconds=..., dry_run=false) para que el almacén SQLite y los archivos de registro se mantengan acotados.

  10. Reejecuta trabajos fallidos, no los reconstruyas. job_rerun(job_id=...) relanza con el comando, entorno, cwd y objetivos de activación originales — ideal para reintentar una descarga o lote que falló transitoriamente.

  11. Pregunta "¿qué es este trabajo?" con job_status. Ahora devuelve el comando, cwd, entorno y timeout, para que puedas explicar un trabajo a un usuario sin leer registros.

  12. Filtra listas por nombre/etiqueta. job_list(name="train", tags=["gpu"]) reduce una lista creciente de trabajos sin tener que paginar todo.

  13. Usa reverse=true para "qué pasó recientemente". job_events(job_id, reverse=true, limit=20) devuelve los eventos más nuevos primero, y puedes retroceder más con since_event_id establecido al id más antiguo que hayas visto.

  14. Un trabajo sobrevive al daemon. El ejecutor está separado; los trabajos continúan a través de reinicios del daemon/MCP. Si un ejecutor ha desaparecido al recuperarse, el trabajo se marca como orphaned (nunca se descarta silenciosamente).


Ejemplos

uv run python examples\long_job.py    # emits progress + checkpoints

examples/long_job.py es un pequeño trabajo de referencia que usa vanth.agent_events. Inícialo mediante job_start y obsérvalo en vanth monitor.


Solución de problemas

  • Unauthorized (401): el token de portador en ~/.vanth/token es lo que espera el daemon. Confirma que VANTH_HOME es el mismo para el daemon y el cliente.

  • El segundo daemon no se inicia: another vanthd already owns this VANTH_HOME. Un daemon por home por diseño.

  • Trabajo atascado en running luego orphaned: el proceso del ejecutor murió. Revisa logs/<job_id>.runner.log y los umbrales de latido.

  • Sin gráficos en el monitor: el trabajo no está emitiendo líneas AGENT_EVENT metric o progress — agrégalas (opcional).

  • Tiempo de espera agotado en activación de OpenCode: aumenta timeout_seconds en el objetivo de activación más allá de la duración esperada del turno.

  • El monitor no muestra nada / estado vacío: confirma que VANTH_HOME apunta al home del daemon, y que jobs.sqlite existe allí.


Desarrollo

uv run pytest -q                 # Python suite (112 passed, 1 Linux-only skip)
uv run python -m compileall -q src tests examples
uv build                         # sdist + wheel; wheel bundles the Go monitor
go vet ./... && go test ./...    # Go: config, state, monitor

La compilación de la rueda ejecuta un hook de compilación de hatchling (build-hooks/bundle_monitor.py) que compila el monitor Go para la plataforma anfitriona y lo empaqueta en vanth/monitor-bin/ para que vanth-monitor no necesite la cadena de herramientas Go en tiempo de ejecución. go debe estar en PATH al compilar la rueda; no es necesario para instalarla o ejecutarla. Las ruedas están etiquetadas por plataforma (py3-none-<platform>) porque contienen el binario nativo.

La automatización de la puerta de lanzamiento reside en scripts/:

  • scripts/chaos_matrix.py — cargas de trabajo sintéticas pesadas y matriz de matar/reiniciar;

  • scripts/real_adapter_smoke.py — pruebas de humo en vivo opt-in de Codex/OpenCode (establece VANTH_SMOKE_CODEX_THREAD / VANTH_SMOKE_OPENCODE_SESSION);

  • scripts/generate_go_fixture.py — regenera el fixture determinista de conformidad schema-v5 en testdata/;

  • scripts/demo_jobs.py — inicia trabajos de demostración (ejecución de entrenamiento, tarea rápida, tarea fallida) para el monitor.

Limitaciones (v1)

  • La entrada estándar interactiva y job_send no están implementados; los trabajos se ejecutan con stdin cerrado (usa banderas no interactivas en los comandos).

  • La entrega es al menos una vez; un fallo después de que un adaptador acepte una activación pero antes de que Vanth registre el éxito es una ambigüedad documentada y expuesta.

  • El acceso remoto, TLS, la política multiusuario, las cuotas, los trabajadores distribuidos y un gestor de servicios personalizado están fuera del alcance.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Git-backed platform for skills, tools, and context for AI agents

  • Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.

  • Reliable async execution for agent tool calls: schema gating, retries, idempotency, audit trail.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/abhim-dv/vanth'

If you have feedback or need assistance with the MCP directory API, please join our Discord server