Skip to main content
Glama

vanth

エージェント向けイベント駆動型バックグラウンドジョブ。

Vanthは、Model Context Protocol(MCP)インターフェースを持つlocalhostバックグラウンドジョブデーモンです。非対話型のシェルコマンドをデタッチして実行し、その出力を永続的にキャプチャし、オプションのAGENT_EVENT構造化イベントを解析してプログレスバー、メトリクス系列、チェックポイントに変換し、ジョブの注意が必要なときにCodexまたはOpenCodeセッションを起動できます。1台のマシン上の1人の信頼されたユーザ向けに作られています。

  • 任意のコマンド: ダウンロード、画像/音声処理、ETL、MLトレーニング — シェルで実行できるものなら、Vanthはデタッチして実行し、追跡できます。

  • 永続性: ジョブとイベントはSQLite(WAL、busy-timeout)に保存され、デーモン、MCP、マシンの再起動後も存続します。

  • イベントファースト: エージェントはログをポーリングする代わりに、job_waitで意味のあるイベントを待ちます。

  • 注意喚起: 永続的な少なくとも1回の配信により、ジョブが人間やエージェントの注意を必要とするときにCodexスレッドまたはOpenCodeセッションを再開します。

  • ターミナルダッシュボード: ネイティブGoのmonitorは、ジョブ、メトリクス、プロットのライブW&B-LEETスタイルのダッシュボードをレンダリングします。

v1の対象外: リモートネットワークアクセス、TLS、マルチユーザーテナンシー/RBAC、クォータ、対話型stdin、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がスタンドアロンツールとしてインストールされます(ホイールにはネイティブ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

そして3つ目のターミナルで、ライブで確認:

uv run vanth-monitor

コマンドラインエントリポイント

コマンド

目的

uv run vanth

MCP stdioサーバー(デーモンへのブリッジ); status / doctor / restart サブコマンドも提供

uv run vanthd

バックグラウンドHTTPデーモン

uv run vanth-monitor

ライブターミナルダッシュボード(Goバイナリ、ホイールにバンドル)

uv run vanth-codex-notify

配信アダプター: ウェイクペイロードをstdinから読み取り、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

コマンドが非0で終了

timeout

コマンドがtimeout_secondsを超過; ランナーが終了

cancelled

job_stopが発行され、プロセスツリーが実際に終了された

orphaned

ランナーが予期せず死亡(クラッシュ); 黙って削除されることはない

ランナーはデーモンの再起動を超えてもtimeout_secondsを強制します。リカバリ時、ランナーがいないrunningジョブは、停止が要求された場合はcancelled、そうでなければorphanedとマークされます — 決してゾンビのrunning行のままにはなりません。


MCPサーバーのインストール

vanthはMCP stdioサーバーです。デーモンと通信し、まだ実行されていない場合は初回使用時に自動的に起動します。

ワンショットセットアップ

ツールをインストールした後、1つのステップでマシン上のMCPクライアントに接続します:

uv tool install vanth
vanth setup

vanth setupはインストールされているクライアント(opencode、Codex、およびClaude Code / Cursorなどの一般的なmcpServersスタイルのクライアント)を検出し、見つけたものを表示し、各設定ファイルに触れる前にバックアップ(.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
    }
  }
}

ソースチェックアウトからは、裸のvanthの代わりにuvを直接使用:

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

接続とツールを確認:

opencode mcp list

ClaudeスタイルのMCPクライアント(mcpServers)

公開ホイール:

{
  "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スクリプトが構造化イベントをstdout(またはstderr)に出力でき、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で出力します(flushは重要です);

  • 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ツール)

ツール

目的

jus_b_sttart `}ジョブをデ lタッチさ↑たジョブとして起動

jov_b_rerun `,元のコマンド/env/cwd/ターゲットでジョブを再実行

job_wait ブロックして一致す↑るイベント(また↑タイムアウト)を待つ — ジョブを待つ推奨方法

job_status 1つのジョブのステータス、コマンド、env, progress, 最終イベント、リンケージ、タグ

job_list 最近のジョブ、status / thread_id / name / tags でフィルタ可能

job_view エージェント向けのサマリー、注意優先度でソート

job_events ジョブの構造化イベント(since_event_idで前方、またはreverseで最新優先)

job_tail 制限付きstdout/stderrログテール(バイトオフセット付き)

jov_metrics_query 保存されているスカラーメトリクス系列(損失、acc, progress.percent, ...)を読む

job_metric_compare ジョブ間で1つのメトリクを比較(最新/平均/最小/最大/合計/カウント)

job_run_summary 1回の呼び出しで「うまくいったか?」— ステータス、実行時間、進捗、メトリクス、アーティファクト

job_artifact_add アーティファクト(チェックポイント、CSV、出力)をジョブに付加

job_artifacts ジョブに付加されたアーティファクトを一覧表示

job_dashoard 任意のレンダラー向けダウンサンプリングされたチャートデータビュー

job_deliveries ジョブのウェイク配信、statusでフィルタ可能

job_mark_delivery 配信のステータスを手動設定

job_retry_delivery 失敗した配信を再キューイングしてディスパッチ

job_delivery_attempts} 1つの配信の試行/リース履歴

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_second、notes、 run(著者、ホスト名、OS、Pythonバージョン、CPU/GPU、gitリポジトリ/ブランチ/コミット)、 runtime_seconds、進ちょっく、最しょのべンと、スレッドリンク、タグ、終了コドを返します。 これはエジェンとが「このが何をしているか?」に答える最速の方法です — そしてW&Bでのランの概と同様です。

notes="..."をjob_startに渡すとラに注釈を付けることができ(「このランを特別にするものは?」)、job_rerun`で保持され、モニターに表示されます。

job_rerun — 失したジョブを再実行

job_rerun(job_id="job_...")

ジョブを元のコマンド、cwd、env、timeout、name、tags、origin thread、wake targetsで再実行します — 新しい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)

1つのジョブの保存された系列を、メトリック名ごとにグループ化して返します。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")

ジョブ間で1つのメトリックを比較します(例:シードや設定間の val_loss)。aggregation は latest、mean、min、max、sum、または count です。結果には、ジョブごとの値と最初/最後のポイントが含まれます。これは W&B スタイルの「どの実行が勝ったか?」というプリミティブです。

job_run_summary — うまくいったか?

job_run_summary(job_id="job_...")

1回の呼び出しで、ステータス、名前、実行時間、終了コード、最新の進捗、メモ、メトリックごとの概要(最新/最初/最小/最大/カウント)、および添付されたアーティファクトを返します。これはエージェントが完了したジョブを報告するための最速の方法です。

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/クラウドダッシュボード)がレンダリングできるようにします。


ウェイクターゲット(ジョブが注意を必要とするときにエージェントを起動)

ジョブが一致するイベントを発行すると、デーモンは永続的な配信を作成し、アダプターを通じてディスパッチします。配信は最低1回です。各ペイロードには重複排除のための 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が成功を記録する前にクラッシュした場合、配信は再クレームされて再試行されます。これは、正確に1回の配信としてクレームされるのではなく、reclaimed 試行として表面化されます。


デーモンの実行

フォアグラウンド(開発または診断用):

uv run vanthd

ログイン時に開始するオプション:

  • Windows: デーモンは、他のスタートアップコマンドとともにユーザーのスタートアップフォルダ(startup_commands.bat)から起動されます。タスクスケジューラのアクションテンプレートも deploy/vanthd.cmd にあります。

  • Unix: deploy/vanthd.service はsystemdユーザーサービスです。

VANTH_HOME ごとに1つのデーモンのみを有効にします。同じホームに対する2番目のデーモンは、即座に終了します(OSレベルのロック)。デーモンはループバック(127.0.0.1 / ::1 / localhost)のみにバインドします。非ループバックの VANTH_DAEMON_HOST は拒否されます。

セキュリティ

  • すべてのデータルートには Authorization: Bearer <token> が必要です。トークンはホームごとに生成され、ログに記録されることはありません。GET /health は認証されていない唯一のルートです(スーパーバイザー向けの安価な生存確認プローブ)。

  • デーモン起動時に、状態ディレクトリは所有者に再制限されます:Unixでは chmod 0700/0600、WindowsではACL継承を無効にし、icacls を使用して所有者、SYSTEM、管理者のみに許可します。これにより、他のアカウント(例:ユーザープロファイルから読み取り権限を継承するサンドボックス/CIユーザー)がトークンやジョブごとのenv/specデータを読み取ることをブロックします。

  • Windowsでは、ソケット SO_REUSEADDR が無効になっているため、2番目のデーモンが同じポートでファントムリスナーになることはありません。バインドに失敗すると、ホームロックが解放され、クリーンに終了します。

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

クライアントがデーモンに到達するURL

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マイグレーションです。既存のデータベースの最初のマイグレーションの前に、タイムスタンプ付きのバックアップが backups/ 以下にSQLiteのバックアップAPIを介して書き込まれます(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_status をループする代わりに job_wait(job_id, filters=[...], timeout_seconds=...) を使用してください。デーモンは、一致するイベントが永続化された時点で待機を即座に起こします。

  2. since_event_id を渡す ことで、イベントを処理した後の次の job_wait で古いイベントを再処理しないようにします。

  3. ジョブにタグとスレッドを付けること。 origin_thread_id(ジョブを起動したエージェントスレッド)と tags を設定し、job_view(thread_id=...) を使って要約します。

  4. ユーザーに状況を提示するときは、job_status よりも job_view を優先すること。 すでに注意優先度でソートされています。

  5. ジョブを自己記述的にすること。 AGENT_EVENT progress / checkpoint / metric 行(上記参照)を出力します。静かなジョブでも動作はしますが、追跡されたジョブのほうがはるかに理解しやすいです。

  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 が同じであることを確認してください。

  • 2つ目のデーモンが起動しない:another vanthd already owns this VANTH_HOME。1つのホームには1つのデーモンが設計上の制約です。

  • ジョブが 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

ホイールビルドでは、hatchling ビルドフック(build-hooks/bundle_monitor.py)が実行され、Go モニターをホストプラットフォーム用にコンパイルし、vanth/monitor-bin/ の下にバンドルします。これにより、vanth-monitor は実行時に Go ツールチェーンを必要としません。ホイールのビルド時には go が PATH に存在する必要がありますが、インストールや実行時には不要です。ホイールはプラットフォームタグ付き(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/ 内の決定論的スキーマ v5 適合フィクスチャを再生成

  • scripts/demo_jobs.py — モニター用のデモジョブ(トレーニング実行、クイックタスク、失敗タスク)を起動

制限事項(v1)

  • 対話型 stdin と job_send は実装されていません。ジョブは stdin が閉じられた状態で実行されます(コマンドには非対話型フラグを使用してください)。

  • 配信は at-least-once(最低1回)です。アダプターがウェイクを受け入れた後、Vanth が成功を記録する前にクラッシュが発生した場合は、文書化され表面化した曖昧さが生じます。

  • リモートアクセス、TLS、マルチユーザーポリシー、クォータ、分散ワーカー、カスタムサービス管理は対象外です。

Related MCP Connectors

Related MCP Servers