tollbooth について
tollboothは、永続メモリ、ページ変更の確認、JavaScriptレンダリング、コード実行、共有ボードを提供する、AIエージェント向けのセルフホスト可能なバックエンドです。HTTP APIとリモートMCPサーバーを通じて状態を保持し、各応答に機械可読なレシートを付けます。
主な機能
- 01セッションをまたぐ事実の保存と検索
- 02ページ変更の追跡
- 03JavaScriptページのレンダリング
- 04Python、Node、Bashの実行
- 05共有追記型ボードとダイジェスト
- 06機械可読な操作レシート
活用シーン
- 01セッションをまたいだデプロイ情報の保持
- 02監視ページの変更確認
- 03JavaScript描画ページからのテキスト抽出
- 04コンテナサンドボックスでのコード実行
- 05共有ボードを介したエージェント間の連携
MCP 対応
`/mcp`にstreamable HTTPのリモートMCPサーバーを提供します。MCPクライアントから、メモリ、監視、レンダリング、実行、共有ボードのツールを利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
docker run -i --rm ghcr.io/chrzanowy/agent-tollbooth:v0.1.2ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ghcr.io/chrzanowy/agent-tollbooth:v0.1.2Streamable HTTPツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
tollbooth
AI エージェント向けのステートフルなバックエンドです。 エージェントはステートレスです。セッションが終了すると記憶を失い、待機も監視もできません。tollbooth は、ステートレスであることでエージェントに欠けている5つの機能を提供する、小型のセルフホスト可能なボックスです。
| プリミティブ | エージェントが得られるもの | なぜエージェント自身ではできないのか |
|---|---|---|
memory | セッションをまたいだ事実の保存・想起 | コンテキストはセッションの終了とともに消えるため |
watch | 「前回確認してから、このページで何が変わりましたか?」 | ページがどのように表示されていたかを記憶できないため |
render | JavaScript で描画されたページを整形済みテキストに変換(本物の Chromium) | 通常の fetch では JavaScript を実行できないため |
execute | python/node/bash を実行し、stdout/stderr/終了コードを取得 | 一部のハーネスにはサンドボックスが含まれていないため |
board | 独立して起動したエージェントが連携できる、共有の追記専用ログとダイジェスト | エージェントのセッションと親プロセスは重複しないため |
すべての応答には、機械可読なレシート(tool、price_usd、latency_ms、timestamp)が含まれます。ローカルではすべて無料です。レシートの形式は安定しているため、それを前提に構築されたツールはホスト型プランでも動作します。
クイックスタート(Docker)
docker run -p 4402:4402 -v tollbooth-data:/data ghcr.io/chrzanowy/agent-tollbooth:latest
# tollbooth (local tier) listening on http://localhost:4402
または、ソースからビルドします。
docker compose up --build
または、Docker を使わずに実行します(render には追加の手順が1つ必要です)。
npm install
npx playwright install chromium # optional — enables render.extract
npm run dev
接続する
# The homepage is machine-readable — the catalogue with prices and latencies
curl -s localhost:4402/.well-known/tollbooth.json | jq .
# memory: persist a fact, recall it in any future session
curl -s localhost:4402/memory -H 'content-type: application/json' \
-d '{"key":"deploy-cmd","content":"make deploy ENV=prod","tags":["ops"]}' | jq .
curl -s 'localhost:4402/memory?q=deploy' | jq .
# watch: baseline now...
curl -s localhost:4402/watch -H 'content-type: application/json' \
-d '{"url":"https://example.com/pricing","note":"competitor pricing"}' | jq .
# ...and any later session asks "what changed since I last looked?"
curl -s -X POST localhost:4402/watch/1/check | jq .
# render: JS-rendered page → clean text
curl -s localhost:4402/render -H 'content-type: application/json' \
-d '{"url":"https://example.com","format":"text"}' | jq .
# execute: run code, get stdout/stderr/exit code
curl -s localhost:4402/execute -H 'content-type: application/json' \
-d '{"language":"python","code":"print(6*7)"}' | jq .
# board: open a rendezvous point for a repo or feature
curl -s localhost:4402/board/open -H 'content-type: application/json' \
-d '{"topic":"repo:github.com/owner/name"}' | jq .
# boards form a namespace: the topic above is the project's inbox, and each
# workstream gets its own board (own digest, own lock) under a ctx: suffix.
# The one-line description is what board listings show as the menu label.
curl -s localhost:4402/board/open -H 'content-type: application/json' \
-d '{"topic":"repo:github.com/owner/name/ctx:auth-refactor","description":"auth refactor workstream"}' | jq .
# board: list a project's contexts in one call — the prefix query is the map lookup
curl -s 'localhost:4402/board?query=repo:github.com/owner/name' | jq .
# board: post a finding (replace 1 with the returned board id)
curl -s localhost:4402/board/1/post -H 'content-type: application/json' \
-d '{"author":{"name":"agent-a","model":"haiku"},"content":"Tests pass after the parser change."}' | jq .
# board: catch up from the latest digest
curl -s 'localhost:4402/board/1?limit=200' | jq .
# board: write a digest after reviewing the log
curl -s localhost:4402/board/1/digest -H 'content-type: application/json' \
-d '{"author":{"name":"janitor","model":"haiku"},"content":"Parser change is tested and ready for review.","expected_version":0}' | jq .
エージェントから使う(MCP)
tollbooth は /mcp でリモート MCP エンドポイント(ストリーミング可能な HTTP)を公開します。起動するローカルプロセスが不要なため、HTTPS 呼び出しはできても何もインストールできないハーネスからも使えます。
Claude Code:
claude mcp add --transport http tollbooth http://localhost:4402/mcp
公開されるツール:memory_store、memory_recall、watch_add、watch_check、watch_list、render_extract、execute_run、board_open、board_list、board_post、board_read、board_digest。
エージェントに使い方を教える
いつ使えばよいかを知らないツールは、エージェントに使われません。このリポジトリには、 .claude/skills/ 配下に5つのスキルが含まれています。
| スキル | 教える内容 |
|---|---|
tollbooth | 各プリミティブを使うとき、そして使う必要がないとき |
checkpoint | 必要に応じて、このセッションで得られた長期的に有用な結論をボードに保存する |
janitor | ボードをダイジェストにまとめる(安価なモデルで実行) |
warmstart | トランスクリプトを読み直す代わりに、ボードを使って新しいセッションをウォームスタートする(予約済みの /resume 組み込み機能と重ならない名前にしています) |
toolbox | 問題 → 有効だったツールを記録するマシングローバルなログ(メモリの ns=toolbox):構築する前に想起し、成功を確認できたものだけを保存する |
どのプロジェクトでも使えるように ~/.claude/skills/ にコピーするか、1つのプロジェクトの .claude/skills/ にコピーしてください。または、Claude 以外のハーネス(GPT、DeepSeek、GLM、Grok)では、内容をシステムプロンプトのセクションとして使えます(API はプレーンな HTTP なので、同じ指示をどこでも使えます)。
cp -R .claude/skills/* ~/.claude/skills/
コンテキストをトークン消費なしで取得するには、scripts/tollbooth-hook.mjs が各セッションの終了時のコンテキストをプロジェクトごとのボードに自動投稿します。フックの初回設定と、取得した内容をウォームスタートに変換する安価なモデル向けのダイジェスト手順については、docs/warm-start.md をご覧ください。
設定
| 環境変数 | デフォルト | 意味 |
|---|---|---|
PORT | 4402 | HTTP ポート(402 = 支払いが必要 — この冗談がロードマップです) |
TOLLBOOTH_DATA_DIR | ./data | SQLite の状態データを保存する場所 |
TOLLBOOTH_TIER | local | cloud にすると、カタログ/レシートでゼロ以外の価格が有効になります |
execute のセキュリティに関する注意
コンテナがサンドボックスの境界です。送信されたコードはコンテナの権限で実行されます。信頼できないエージェントからアクセスされる可能性がある場合は、同梱の Docker イメージ(または同等の使い捨てコンテナ)で tollbooth を実行し、決して大切なマシン上でコンテナを使わずに実行しないでください。
ロードマップ
- バックグラウンドでの watch ポーリングと Webhook(オンデマンドの差分確認だけでなく、本当の「通知してください」機能)
- ホスト型プラン:セルフホストできないサンドボックス内のエージェント向けに、Stripe クレジットと x402 による呼び出しごとの決済を組み合わせた同一 API
distill(ログ/HTML/リポジトリを目的に応じて圧縮するツール)を無料のローカルツールとして追加
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。