Skip to main content
Glama

vanth

面向智能体的事件驱动后台任务。

Vanth 是一个本地后台任务守护进程,具有模型上下文协议(MCP)接口。它运行分离的、非交互式的 shell 命令;持久化捕获其输出;将可选的 AGENT_EVENT 结构化事件解析为进度条、指标序列和检查点;并能在任务需要关注时唤醒 Codex 或 OpenCode 会话。它专为一台机器上的一个受信任用户构建。

  • 任何命令:下载、图像/音频处理、ETL、机器学习训练——只要能在 shell 中运行,Vanth 就能分离运行并跟踪它。

  • 持久化:任务和事件存储在 SQLite(WAL,忙等待超时)中,并在守护进程、MCP 和机器重启后仍然存在。

  • 事件优先:智能体通过 job_wait 等待有意义的事件,而不是轮询日志。

  • 按需唤醒:持久化的至少一次投递会在任务需要人工或智能体时恢复 Codex 线程或 OpenCode 会话。

  • 终端仪表盘:原生 Go 的 monitor 渲染一个实时的 W&B-LEET 风格仪表盘,显示任务、指标和图表。

v1 范围之外:远程网络访问、TLS、多用户租户/RBAC、配额、交互式标准输入和 Web UI。

对于智能体: 使用 job_start 开始工作,然后使用 job_wait 等待 progress/checkpoint/completed 事件,而不是轮询;让任务发出 AGENT_EVENT 行(如下),以便进度、指标和检查点实时显示在 vanth-monitor 仪表盘中;并让长时间运行的任务通过唤醒目标恢复你,而不是你主动检查。


快速开始

安装(需要 uv;运行于 Python 3.11+):

uv tool install vanth

这将安装 vanth MCP 服务器、vanthd 守护进程、vanth-monitor 和 ops CLI 作为独立工具(wheel 包捆绑了原生 Go 监控器,因此不需要 Go 工具链)。

从源代码检出(开发):

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

启动守护进程(保持此终端打开):

uv run vanthd

在第二个终端中,通过 MCP 服务器启动一个被跟踪的任务:

uv run vanth

或直接从 MCP 客户端使用工具(参见 MCP 集成)。

验证一切正常:

job_doctor()

端到端:运行一个被跟踪的任务

一旦 MCP 客户端连接,这就是完整的循环:

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

在第三个终端中,实时观看:

uv run vanth-monitor

命令行入口点

命令

目的

uv run vanth

MCP stdio 服务器(守护进程的桥接);还有 status / doctor / restart 子命令

uv run vanthd

后台 HTTP 守护进程

uv run vanth-monitor

实时终端仪表盘(Go 二进制文件,捆绑在 wheel 包中)

uv run vanth-codex-notify

投递适配器:从标准输入读取唤醒负载,将其分派到 Codex

操作 CLI

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 是可靠地获取代码/版本更新的方式:它向守护进程发送一个通过回环接口的优雅关闭信号,等待旧进程完全释放主目录锁,然后启动一个新的守护进程。正在运行的任务由分离的运行器拥有,因此它们会在重启期间继续运行。


Related MCP server: Background Process MCP

工作原理

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

所有权规则:

  • 运行器 拥有实际命令、其超时和流排空;

  • 守护进程 拥有维护、投递分派、API 请求和恢复;

  • SQLite 是跨进程重启的真相来源;

  • MCP 和 HTTP 客户端 无需保持存活即可让任务继续。

一个任务只有在两个输出流都达到 EOF 并且所有结构化事件都已持久化后,才被视为终止状态。

任务生命周期

一个任务经历一小部分状态。终止状态是永久的。

状态

含义

running

工作负载已启动;运行器正在流式传输输出并发送心跳

completed

命令退出码为 0,流已排空,事件已持久化

failed

命令退出码非零

timeout

命令超过 timeout_seconds;运行器终止了它

cancelled

发出了 job_stop 并且进程树实际已终止

orphaned

运行器意外死亡(崩溃);永远不会被静默丢弃

运行器即使在守护进程重启后也会强制执行 timeout_seconds。在恢复时,一个 running 状态的任务,如果其运行器已消失,则会被标记为 cancelled(如果请求了停止)或 orphaned(如果没有)——永远不会留下一个僵尸的 running 行。


安装 MCP 服务器

vanth 是 MCP stdio 服务器。它与守护进程通信,如果守护进程尚未运行,则在首次使用时自动启动它。

一次性设置

安装工具后,通过一个步骤将其连接到您机器上的 MCP 客户端:

uv tool install vanth
vanth setup

vanth setup 检测您已安装的客户端(opencode、Codex 和通用的 mcpServers 风格客户端,如 Claude Code / Cursor),显示它找到的内容,在修改每个配置之前备份它(.vanth-setup-<ts>.bak),并插入或更新 Vanth MCP 条目——保持所有其他设置和注释不变。

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

它管理的配置:

客户端

文件

部分

opencode

~/.config/opencode/opencode.json

mcp.vanth

Codex

~/.codex/config.toml

[mcp_servers.vanth]

Claude Code / Cursor

~/.claude.json

mcpServers.vanth

手动添加,相同的条目是:

opencode

添加到 ~/.config/opencode/opencode.json:

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

从源代码检出,直接使用 uv 而不是裸的 vanth:

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

验证连接和工具:

opencode mcp list

Claude 风格 MCP 客户端(mcpServers)

已发布的 wheel 包:

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

从源代码检出:

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

配置守护进程主目录

MCP 服务器和守护进程都从 VANTH_HOME(Windows 上默认为 %USERPROFILE%\.vanth,Unix 上为 ~/.vanth;AGENT_BG_HOME 也被接受作为别名)解析相同的状态根目录。如果两者都设置,它们必须解析到相同的目录。


使用 agent_event 检测任务

任何 Python 脚本都可以向标准输出(或标准错误)发出结构化事件,Vanth 会解析这些事件,监控器会绘制图表。这是可选的——纯脚本仍然可以运行和记录日志——但这是将任务转变为一级跟踪对象的方法。

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)

注意:

  • 辅助函数打印 AGENT_EVENT {json} 并带有 flush=True(刷新很重要);

  • progress(current, total, unit=..., stage=...) 会为您计算 percent;

  • metric 负载:数字字段成为序列;_step(如果存在且为数字)是 x 轴,否则使用事件序列号;以 _ 开头(除了 _step)的键被忽略;布尔值不是指标;NaN/Infinity/null 值被跳过并在监控器的警告徽章中计数;

  • 任何其他字段(例如 file、stage、phase)都会被保留并显示在精确事件表中。

示例:一个被跟踪的下载器

# 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")

示例:一个图像处理批次

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)

使用 loguru 进行带时间戳、分级的日志记录

Vanth 附带了一个 loguru 包装器,它将每条记录路由到结构化的 AGENT_EVENT 日志行中,因此日志会作为带时间戳、分级别的事件出现在事件表中(带有级别徽章和精确时间戳),而不是纯文本:

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")

每次调用都会发出 AGENT_EVENT {"type":"log","level":"info","message":"...","data":{...}},守护进程将其持久化为一个持久事件。data 携带额外的上下文。监控器会在精确事件表中与 metric/progress 事件一起显示这些日志。


工具参考(全部 20 个 MCP 工具)

工具

目的

job_start

将命令作为分离任务启动

job_rerun

使用原始命令/环境/工作目录/目标重新启动任务

job_wait

阻塞直到匹配的事件(或超时)——等待任务的首选方式

job_status

单个任务的状态、命令、环境、进度、最后事件、链接、标签

job_list

最近的任务,可按 status / thread_id / name / tags 过滤

job_view

面向智能体的摘要,按关注优先级排序

job_events

任务的结构化事件(通过 since_event_id 向前,或通过 reverse 最新优先)

job_tail

带字节偏移的有限标准输出/标准错误日志尾部

job_metrics_query

读取存储的标量指标序列(损失、准确率、progress.percent 等)

job_metric_compare

跨任务比较一个指标(最新/均值/最小值/最大值/总和/计数)

job_run_summary

一次调用“它工作了吗?”——状态、运行时间、进度、指标、产物

job_artifact_add

将产物(检查点、CSV、输出)附加到任务

job_artifacts

列出附加到任务的产物

job_dashboard

适用于任何渲染器的降采样图表数据视图

job_deliveries

任务的唤醒投递,可按 status 过滤

job_mark_delivery

手动设置投递的状态

job_retry_delivery

将失败的投递重新排队以进行分派

job_delivery_attempts

单个投递的尝试/租约历史

job_stop

停止正在运行的任务(终止进程树)

job_doctor

守护进程健康、模式、表、二进制可用性

job_cleanup

干运行或实际删除旧的终止任务

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
)

返回 job_id、status、worker_pid 以及日志/事件路径。

job_status — 查看任务正在运行什么

job_status(job_id="job_...")

返回状态、命令、cwd、env、timeout_seconds、notes、run(作者、主机名、操作系统、Python 版本、CPU/GPU、git 仓库/分支/提交)、runtime_seconds、进度、最后事件、线程链接、标签和退出码。这是智能体回答“这个任务在做什么?”的最快方式——并且镜像了你在 W&B 中看到的运行概览。

向 job_start 传递 notes="..." 来注释一次运行(“这次运行有什么特别之处?”),该注释会在 job_rerun 中保留并显示在监控器中。

job_rerun — 重新启动失败的任务

job_rerun(job_id="job_...")

使用任务的原始命令、cwd、env、超时、名称、标签、原始线程和唤醒目标重新启动它——返回一个新的 job_id。用于重试失败的下载、不稳定的处理批次或暂时性故障,而无需重新构建请求。

job_list — 按名称或标签过滤

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

过滤器:status(列表)、thread_id、name(子字符串)、tags(必须包含所有列出的标签)。

job_events — 向前或最新优先

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 返回最近的事件(最新的在前)——非常适合“最近发生了什么?”——并且可以与 since_event_id 结合使用以向后翻页。

job_wait — 代理使用的核心

job_wait(job_id="job_...", filters=["checkpoint","failed","completed"], timeout_seconds=3600)
  • 等待第一个匹配任何过滤器的事件,并返回该事件及其当前状态;

  • 传递 since_event_id 以仅等待比你已看到的事件更新的新事件;

  • 超时时返回 result: "timeout";守护进程关闭时返回 result: "shutdown"。

job_view — 向用户展示的内容

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

返回按关注优先级排序的紧凑摘要:首先显示运行中和失败的任务,然后是待处理/失败投递的任务,最后是其他所有任务。每个条目包括状态、进度、最新事件、线程关联、标签和投递计数。

job_stop — 停止运行中的任务

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

终止任务的进程树。首先发送一个优雅的 signal(默认为 terminate);如果任务在 kill_after_seconds 内未退出,则将其杀死。任务仅在工作负载树实际终止后才变为 cancelled;否则保持 running 状态,且停止操作可重试。

job_mark_delivery / job_retry_delivery — 手动投递控制

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

job_mark_delivery 手动设置投递状态(例如在解决适配器问题后);job_retry_delivery 将失败的投递重新排队,以便在下一轮调度中处理。job_delivery_attempts 显示声明/租约历史。

job_cleanup — 移除旧的终端任务

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

移除早于截止时间的终端任务:日志、事件镜像、规格、投递、尝试、唤醒目标、事件,最后是任务行。运行中的任务永远不会被选中。试运行是完全只读的。清理操作可安全重复。

job_metrics_query — 读取存储的标量序列

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

返回一个任务存储的序列,按指标名称分组。metric 过滤到单个序列(例如 loss、acc、progress.percent);from_ms/to_ms 按事件时间戳(纪元毫秒)过滤。点按事件序列排序。这是终端监视器数据的读取端。

job_metric_compare — 跨运行比较指标

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

跨任务比较一个指标(例如跨种子或配置的 val_loss)。aggregation 可以是 latest、mean、min、max、sum 或 count;结果包括每个任务的值以及第一个/最后一个点。这是 W&B 风格的“哪个运行赢了?”原语。

job_run_summary — 它成功了吗?

job_run_summary(job_id="job_...")

一次调用返回状态、名称、运行时间、退出代码、最新进度、备注、每个指标的概览(最新/第一个/最小/最大/计数)以及附加的工件——代理报告已完成任务的最快方式。

job_artifact_add / job_artifacts — 附加输出

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

将工件(检查点、CSV、渲染输出)附加到任务,以便它们列在 job_run_summary 中并可稍后检索。meta 是自由格式的 JSON。

job_dashboard — 为任何渲染器提供图表数据

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

返回任务列表以及每个存储的指标序列,每个序列下采样到 limit 个点——与 Go 终端监视器图表相同的数据,通过 HTTP/MCP 暴露,以便任何客户端(未来的 Web/云仪表板)都可以渲染它。


唤醒目标(当任务需要关注时唤醒代理)

当任务发出匹配的事件时,守护进程创建一个持久的投递并通过适配器调度它。投递是至少一次的;每个负载都携带一个 delivery_id 用于去重。

local_command

运行任意命令,将投递负载作为 JSON 通过 stdin 传递:

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

退出码 0 将投递标记为 delivered;任何其他退出码将其标记为 failed。

codex_thread

通过本地应用服务器恢复 Codex 线程:

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

协议:initialize -> thread/resume -> turn/start。

opencode_thread

恢复 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
}

默认的 OpenCode 轮次超时为 30 秒;对于较长的轮次请提高此值。

共享投递选项

{
  "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
}

当 auto_dispatch: false 时,投递保持 pending 状态,直到代理手动调度它们或更改目标。

投递操作

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")

尝试历史记录声明令牌、开始/结束时间、状态以及尝试是否在租约过期后被回收。如果守护进程在适配器接受唤醒之后但在 Vanth 记录成功之前崩溃,则投递被回收并重试——显示为 reclaimed 尝试,而不是声明为恰好一次投递。


运行守护进程

前台运行(用于开发或诊断):

uv run vanthd

登录时启动选项:

  • Windows:守护进程从用户启动文件夹(startup_commands.bat)与其他启动命令一起启动;任务计划程序操作模板也在 deploy/vanthd.cmd 中。

  • Unix:deploy/vanthd.service 是一个 systemd 用户服务。

每个 VANTH_HOME 只启用一个守护进程。同一主目录的第二个守护进程立即退出(操作系统级锁)。守护进程仅绑定到回环地址(127.0.0.1 / ::1 / localhost);非回环的 VANTH_DAEMON_HOST 被拒绝。

安全

  • 每个数据路由都需要 Authorization: Bearer <token>;令牌按主目录生成且从不记录。GET /health 是唯一未经身份验证的路由(用于管理器的廉价存活探针)。

  • 守护进程启动时,状态目录重新收紧为所有者:Unix chmod 0700/0600;Windows 禁用 ACL 继承并仅通过 icacls 授予所有者、SYSTEM 和管理员。这阻止其他账户(例如从用户配置文件继承读取权限的沙箱/CI 用户)读取令牌或每个任务的环境/规格数据。

  • 在 Windows 上,禁用套接字 SO_REUSEADDR,以便第二个守护进程无法成为同一端口上的幽灵监听器;绑定失败会释放主目录锁并干净退出。

Go 终端监视器

原生 Go 仪表板以只读方式读取同一主目录,并渲染实时图表、进度条、精确事件表和日志尾部:

uv run vanth-monitor

从构建的 wheel 中,vanth-monitor 运行捆绑的原生二进制文件(无需 Go 工具链)。从源代码检出中,它在首次使用时构建监视器并缓存到 ~/.cache/vanth/ 下(需要 go 在 PATH 中):

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

按键:up/down 或 j/k 选择任务 · enter 固定任务的序列 · e 事件表 · l 日志尾部 · +/- 缩放图表 · [/] 平移 · t 返回实时尾部 · ? 帮助 · q 或 Ctrl+C 退出。


配置参考

环境变量(默认值位于 src/vanth/server.py、src/vanth/daemon.py、src/vanth/migrations.py):

变量

默认值

用途

VANTH_HOME

~/.vanth

状态根目录(别名:AGENT_BG_HOME)

VANTH_DAEMON_URL

http://127.0.0.1:8765

客户端访问守护进程的地址

VANTH_DAEMON_HOST

127.0.0.1

绑定地址(仅回环)

VANTH_DAEMON_PORT

8765

绑定端口

VANTH_MAX_REQUEST_BYTES

1 MiB

HTTP 请求体上限

VANTH_MAX_RESPONSE_BYTES

4 MiB

HTTP 响应上限

VANTH_MAX_EVENT_BYTES

64 KiB

单个事件负载上限

VANTH_MAX_EVENT_LINE_BYTES

1 MiB

AGENT_EVENT 行上限

VANTH_MAX_LOG_BYTES

10 MiB

每流日志上限(继续排空)

VANTH_MAX_EVENTS_PER_JOB

100000

每个任务的结构化事件上限

VANTH_DELIVERY_POLL_INTERVAL

0.2s

维护循环节奏

VANTH_DELIVERY_LEASE_MARGIN

5s

超出适配器超时的额外租约时间

VANTH_RUNNER_HEARTBEAT_INTERVAL

1s

运行器存活心跳

VANTH_RUNNER_HEARTBEAT_STALE_AFTER

10s

心跳过期阈值

VANTH_CODEX_BIN

codex / C:\codex\codex.exe

Codex 二进制文件

VANTH_OPENCODE_BIN

opencode(通过 shutil.which)

OpenCode 二进制文件

VANTH_LOG_LEVEL

INFO

守护进程日志级别

VANTH_LOG_MAX_BYTES

5 MiB

轮转守护进程日志大小

VANTH_LOG_BACKUP_COUNT

3

守护进程日志轮转计数

VANTH_BUSY_TIMEOUT_MS

30000

SQLite 写锁等待时间


操作

状态布局

~/.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

健康、就绪和诊断

job_doctor()

报告状态目录、数据库表、按状态统计的投递计数、模式版本、PRAGMA quick_check、过期的投递租约、可用磁盘、令牌路径以及 Codex/OpenCode 二进制文件是否可解析。它从不泄露令牌。

HTTP 守护进程还暴露:

  • GET /health — 用于管理器的廉价、未经身份验证的存活探针;

  • GET /ready — 经过身份验证的就绪状态(医生报告;不健康时返回 503)。

升级和备份

模式更改是有序的 SQLite 迁移。在对现有数据库进行首次迁移之前,通过 SQLite 的备份 API 在 backups/ 下写入一个带时间戳的备份(在 WAL 活动时绝不进行原始文件复制)。要手动升级,请先复制最新的 backups/*.sqlite。未来的数据库模式将被拒绝,而不会触及文件。


HTTP API(等同于 MCP 工具)

使用 Authorization: Bearer <token> 进行身份验证。

方法

路径

用途

GET

/jobs

列出任务(status、limit、thread_id、name、tags)

POST

/jobs

启动一个任务

POST

/jobs/{id}/rerun

使用原始配置重新运行任务

GET

/jobs/{id}/status

任务状态(包含命令/环境变量/工作目录)

GET

/jobs/{id}/events

事件(since_event_id、types、limit、reverse)

GET

/jobs/{id}/metrics

指标序列(metric、from_ms、to_ms、limit)

GET

/jobs/{id}/summary

运行摘要(状态、运行时间、指标、工件)

GET

/jobs/{id}/artifacts

工件(limit)

POST

/jobs/{id}/artifacts

添加工件

GET

/metrics/compare

跨任务比较指标(job_ids、metric、aggregation)

GET

/dashboard

图表数据(job_ids、limit)

GET

/jobs/{id}/tail

日志尾部(stream、max_bytes、offset)

POST

/jobs/{id}/wait

等待事件

POST

/jobs/{id}/stop

停止任务

GET

/view

智能体视图(thread_id、limit)

GET

/deliveries

投递记录(job_id、status、limit)

GET

/deliveries/{id}/attempts

尝试历史

POST

/deliveries/{id}/mark

标记投递状态

POST

/deliveries/{id}/retry

重试投递

POST

/cleanup

清理(older_than_seconds、dry_run)

GET

/doctor

健康报告

GET

/health

无需认证的存活检测


智能体使用技巧

  1. 等待,而非轮询。使用 job_wait(job_id, filters=[...], timeout_seconds=...) 代替循环调用 job_status。守护进程会在匹配事件持久化后立即唤醒等待。

  2. 传递 since_event_id 到处理事件后的下一个 job_wait,避免重复处理旧事件。

  3. 为任务添加标签和线程信息。设置 origin_thread_id(启动任务的智能体线程)和 tags;使用 job_view(thread_id=...) 进行汇总。

  4. 向用户呈现情况时优先使用 job_view 而非 job_status — 它已按关注优先级排序。

  5. 让任务具备自描述能力。输出 AGENT_EVENT progress / checkpoint / metric 行(见上方使用AGENT_EVENT检测任务)。沉默的任务也能运行,但带检测的任务更容易推理。

  6. 对长任务使用唤醒目标。如果训练运行或长时间下载需要在检查点做出决策,添加带有 events: ["checkpoint", "failed", "completed"] 的 codex_thread 或 opencode_thread 目标,以便智能体被恢复而非轮询。

  7. 检查投递失败。job_delivery_attempts 显示租约/认领历史记录;job_retry_delivery 在修复原因后重新排队失败的任务。

  8. 在 job_start 上设置合理的 timeout_seconds,使挂起的命令变成 timeout(终止)状态而非永远运行;即使在守护进程重启后,运行器也会强制执行此超时。

  9. 使用 job_cleanup(older_than_seconds=..., dry_run=false) 清理旧状态,使 SQLite 存储和日志文件保持有限大小。

  10. 重新运行失败的任务,而非重建它们。job_rerun(job_id=...) 使用原始命令、环境变量、工作目录和唤醒目标重新启动 — 非常适合重试临时失败的下载或批处理。

  11. 用 job_status 查询"这个任务是什么?"。它现在返回命令、工作目录、环境变量和超时,因此你可以在不读取日志的情况下向用户解释任务。

  12. 按名称/标签过滤列表。job_list(name="train", tags=["gpu"]) 缩小日益增长的任务列表,无需翻阅所有内容。

  13. 使用 reverse=true 查看"最近发生了什么"。job_events(job_id, reverse=true, limit=20) 返回最新的事件优先,通过设置 since_event_id 为你所见的最旧 ID 可以进一步翻页。

  14. 任务独立于守护进程存活。运行器是分离的;任务在守护进程/MCP 重启后继续运行。如果恢复时运行器已消失,任务被标记为 orphaned(从不静默丢弃)。


示例

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

examples/long_job.py 是使用 vanth.agent_events 的小型参考任务。通过 job_start 启动它,然后在 vanth monitor 中观察。


故障排除

  • Unauthorized (401):~/.vanth/token 中的持有者令牌需与守护进程期望的一致。确认守护进程和客户端使用相同的 VANTH_HOME。

  • 第二个守护进程无法启动:另一个 vanthd 已拥有此 VANTH_HOME。每个主目录只能运行一个守护进程。

  • 任务卡在 running 后变为 orphaned:运行器进程已终止。检查 logs/<job_id>.runner.log 和心跳阈值。

  • 监控器中无图表:任务未输出 AGENT_EVENT metric 或 progress 行 — 添加它们(可选)。

  • OpenCode 唤醒超时:增加唤醒目标上的 timeout_seconds,使其超出预期的轮次长度。

  • 监控器显示为空/空白状态:确认 VANTH_HOME 指向守护进程的主目录,并且其中存在 jobs.sqlite。


开发

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

wheel 构建运行 hatchling 构建钩子(build-hooks/bundle_monitor.py),为主机平台编译 Go 监控器并将其打包到 vanth/monitor-bin/ 下,因此 vanth-monitor 在运行时无需 Go 工具链。构建 wheel 时 go 必须在 PATH 上;安装或运行时不需要它。Wheels 带有平台标签(py3-none-<platform>),因为它们包含原生二进制文件。

发布门自动化位于 scripts/ 中:

  • scripts/chaos_matrix.py — 繁重的合成工作负载和杀死/重启矩阵;

  • scripts/real_adapter_smoke.py — 可选实时 Codex/OpenCode 唤醒冒烟测试(设置 VANTH_SMOKE_CODEX_THREAD / VANTH_SMOKE_OPENCODE_SESSION);

  • scripts/generate_go_fixture.py — 重新生成 testdata/ 中的确定性 schema-v5 一致性测试数据;

  • scripts/demo_jobs.py — 为监控器启动演示任务(训练运行、快速任务、失败任务)。

限制(v1)

  • 交互式标准输入和 job_send 未实现;任务以标准输入关闭的方式运行(在命令上使用非交互式标志)。

  • 投递为至少一次;在适配器接受唤醒但 Vanth 记录成功之前崩溃是已记录且表面化的歧义情况。

  • 远程访问、TLS、多用户策略、配额、分布式工作器和自定义服务管理器不在范围内。

Related MCP Connectors

Related MCP Servers