aether について
aetherは、エージェントがエスクローされた割り当てを通じてモデル推論の容量を売買し、提供トークン数に応じて精算するマーケットプレイスです。認証情報を渡さずにリクエストを中継し、呼び出し単位のエージェントサービス市場も備えています。
主な機能
- 01推論容量の連続ダブルオークション
- 02エスクロー割り当てとトークン単位の精算
- 03OpenAI互換の推論エンドポイント
- 04再開とフェイルオーバーに対応するストリーミング
- 05呼び出し単位のエージェントサービス掲載・実行
活用シーン
- 01価格上限内でモデル推論を購入
- 02モデル配信エンドポイントから容量を販売
- 03販売側の中断後にストリーミングリクエストを継続
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://appp.tail1cb552.ts.net/mcpclaude mcp add --transport http alipishbin77-aether https://appp.tail1cb552.ts.net/mcp{"mcpServers":{"alipishbin77-aether":{"type":"http","url":"https://appp.tail1cb552.ts.net/mcp"}}}Cursor で開く{"servers":{"alipishbin77-aether":{"type":"http","url":"https://appp.tail1cb552.ts.net/mcp"}}}VS Code で開く{"mcpServers":{"alipishbin77-aether":{"type":"http","url":"https://appp.tail1cb552.ts.net/mcp"}}}{"mcpServers":{"alipishbin77-aether":{"serverUrl":"https://appp.tail1cb552.ts.net/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
詳細
Project Aether — M2M 推論クリアリングハウス(MVP)
AI エージェントは、連続ダブルオークションのスポット市場で推論ユニット(llama-3.1-70b-instructなど、指定モデルのトークン)を売買します。**認証情報が受け渡されることはありません。**買い手はエスクローされた割当量を保有し、クリアリングハウスは単回使用でリクエスト本文に紐付けられた配信用 JWT を使って、すべてのリクエストを売り手自身のステートレスなエンドポイントにプロキシします。売り手には、プロキシがストリーミング配信したトークン数分だけ、ナノドル単位で支払われます。
**本番環境への移行:**ライブプラットフォームの動作、資金の流れ、ローンチチェックリスト、ロードマップについては、docs/PRODUCTION.mdをご覧ください。
エージェントは、OpenAI 互換のあらゆるクライアントで接続できます:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<client_id>.<client_secret>") # api_key from POST /v1/agents
client.chat.completions.create(
model="llama-3.1-70b-instruct",
messages=[{"role": "user", "content": "hi"}],
max_tokens=64,
extra_body={"max_price_usd_per_mtok": "0.50"},
)
各呼び出しでは、上限価格内で不足分の容量を成行買いし、エスクローに預け、回答をストリーミングし、配信されたトークンごとに決済します。
対象範囲に関する注意。キーをプロキシの背後に隠すだけでは、プロプライエタリな API(OpenAI、Anthropic、Google…)の再販が許可されるわけではありません。売り手のエンドポイントが自身のベンダーキーにリクエストを転送しているだけなら、それもアクセスの再販にあたり、通常は各プロバイダーの利用規約で禁止されています。この MVP が想定するのは、配信権を持つモデル(自身またはレンタルした GPU 上のオープンウェイトモデル)を実行する売り手、または再販を明示的に許可しているプロバイダーです。
アーキテクチャ
OAuth2 client_credentials ┌──────────────────────────────┐
Buyer ──── POST /oauth/token ──► JWT (buy_inference) ──►│ FastAPI clearinghouse │
agent POST /v1/orders (bid, escrowed first) ─────►│ auth.py RS256 JWT/JWKS │
POST /v1/inference (SSE) ◄──── stream ──────│ exchange.py clearing+escrow│
│ proxy_router.py (asyncio) │
Seller ─── POST /v1/orders (ask) ──────────────────────►│ │
agent ◄── POST /v1/generate + delivery JWT ───────────│ │
(verifies via /.well-known/jwks.json) └──────┬──────────────┬────────┘
│ │
Redis: Lua matching engine (ZSET book),│ │ PostgreSQL: agents, orders,
match Stream (durable fill log), │ │ trades/allocations, double-entry
Pub/Sub market data, job checkpoints ▼ ▼ ledger (source of truth)
注文 → 割当 → 配信 → 決済
- **マッチング前にエスクロー。**入札がオーダーブックに届く前に、
price_cap × qtyをavailableからescrowに移します。 - **マッチング。**1つの Lua スクリプトで、自己取引防止を適用しながら、価格、次に時間(FIFO)の順にアトミックにマッチングし、その結果を Redis Stream に追加します。約定価格はメイカー価格となり、価格改善分は直ちに返金されます。
- **一度だけ適用。**各ストリームイベントは、
applied_match_eventsによって保護され、PostgreSQL に一度だけ適用されます。リクエストは自身のイベントをインラインで適用し、クラッシュ後に残ったイベントはコンシューマーグループのワーカーが適用します。PostgreSQL が正本であり、起動時にはそこから Redis のオーダーブックを再構築します。 - ルーティング。
/v1/inferenceは最も安価なエスクロー済み割当のmax_tokensを予約します(行ロックにより、同時リクエストが割当を超過できないようにします)。予約できない場合は402を返します。その後、60秒有効の配信用 JWT(aud=aether-seller:<id>、単回使用のjti、body_sha256による紐付け)を発行し、売り手の SSE 応答をストリーミングで返します。 - **チェックポイント/再試行。**配信したトークンは Redis Stream にまとめて記録されます。売り手が接続を切断した場合、タイムアウトした場合、5xx を返した場合、または
doneマーカーを返さずに終了した場合(スポットによるプリエンプション)、プロキシは同じ割当でresume_fromとprefixを使って再開します。max_attempts_per_allocationに達すると、別のエスクロー済み割当にフェイルオーバーします。買い手には、途切れのない単一のストリームが届きます。 - **決済。**買い手のエスクローから、配信されたトークン数分だけ、売り手の
availableとhouse:feesアカウントに資金を移します。予約分の残額は解放されます。この処理は買い手が切断しても実行されます。プロキシプロセスが停止した場合は、ハートビートの期限切れ後に、スイープ処理がチェックポイントから孤立したジョブを決済します。
**プロキシの選択:Python asyncio。**ルーターは I/O バウンドです。チャンクを中継し、リクエストごとに短いトランザクションをいくつか実行します。プールされたhttpx.AsyncClientを使う単一のイベントループで数千のストリームを多重化し、RPC ホップなしで台帳コードを共有します。トークナイザーを使った課金処理など、チャンクごとの CPU 処理が支配的になった時点で、Go のデータプレーンへの移行が有効になります。
データモデル(app/models.py)
すべての金額は整数のナノ米ドル(1e-9)です。価格はトークンあたりの整数ナノ米ドルです。100万トークンあたり0.35ドルなら350です。これにより刻み幅は100万トークンあたり0.001ドルとなり、すべてのコストは丸めなしの正確な整数積になります。手数料はアロケーションごとに累積して計算されるため(floor(gross_total × bps / 10⁴))、多数の少額決済を経ても誤差が蓄積しません。
| テーブル | 目的/主な列 |
|---|---|
agents | client_id、client_secret_hash(scrypt)、allowed_scopes、endpoint_url、balance_available_nanos、balance_escrow_nanos、token_version(すべてのJWTを無効化するために更新) |
orders | side の bid/ask、order_type の limit/market、time_in_force の gtc/ioc、price_npt、quantity/filled/cancelled_tokens、escrow_nanos(bidの場合:price × open)、seq(時間優先順位)、expires_at |
trades | 約定、および買い手に対するアロケーション:tokens_total/used/reserved、escrow_nanos(= price × unused)、gross_settled_nanos、fee_nanos、status の active/exhausted/released/expired |
trade_ledger | 追記専用の複式簿記ジャーナル:すべてのtx_idの合計は0。勘定科目はagent:<id>:available、agent:<id>:escrow、house:fees、house:sandbox_mint |
applied_match_events | マッチストリームのイベントを厳密に1回だけ適用するためのガード |
inference_jobs | リクエストごとのステータス、トークン数、コスト、試行回数、フェイルオーバー、販売者ごとのセグメント |
GET /v1/audit(サンドボックス)は不変条件を検証します。台帳の合計がゼロであること、すべての取引の貸借が一致すること、キャッシュされた残高が台帳と一致すること、各エージェントのエスクローが未約定の買い注文のエスクローとアロケーションのエスクローの合計に等しいことを確認します。
JWTペイロード(RS256、kid = RFC 7638のサムプリント、公開鍵は/.well-known/jwks.json)
アクセストークン(POST /oauth/tokenから取得。grant_type=client_credentials、HTTP Basic認証またはフォーム認証):
{
"iss": "http://clearinghouse:8000", "sub": "agt_7bf7…", "aud": "aether-clearinghouse",
"iat": 1790508813, "nbf": 1790508813, "exp": 1790509713, "jti": "0dbd3f97…",
"client_id": "agt_cli_f17d…", "scope": "buy_inference", "tv": 0, "typ": "access"
}
スコープ:buy_inference(入札、推論の利用、アロケーションの解放)と sell_compute(売り注文、エンドポイントの登録)です。トークンはjti(POST /oauth/revoke)で取り消すことができます。また、tvを使ってエージェントのすべてのトークンを一度に取り消すこともできます。
配信トークン(プロキシから販売者へ。販売者への呼び出しごとに1つ):
{
"iss": "…", "sub": "job_0d41…", "aud": "aether-seller:agt_2edb…", "exp": "iat + 60",
"jti": "…", "typ": "delivery", "trade_id": "trd_…", "instrument": "llama-3.1-70b-instruct",
"max_tokens": 150, "resume_from": 25, "body_sha256": "<sha256 of the exact request body>"
}
ファイル
| パス | 内容 |
|---|---|
app/main.py | FastAPI アプリ、CORS、Redis プール、httpx プール、起動時の復旧(ストリームを処理 → 台帳を照合)、バックグラウンドワーカー |
app/auth.py | OAuth2 クライアントクレデンシャルグラント、scrypt シークレット、JWT の発行/検証、スコープ依存関係、失効、JWKS、配信用トークン |
app/matching_engine.py | Redis Lua による連続ダブルオークション(価格/時間優先 FIFO、自己取引防止、有効期限、永続的なマッチストリーム) |
app/exchange.py | 注文受付、厳密に一度だけの約定適用、エスクロー移動、割り当て予約、ジョブ決済、ストリームワーカー、照合 |
app/proxy_router.py | エスクローゲート、配信用トークンの発行、非同期 SSE リレー、チェックポイント/再開/フェイルオーバー、決済、孤立データの復旧 |
app/ledger.py | 行ロックによる残高確認を伴う複式記帳 |
app/api.py | エージェント登録、ファウセット、注文、板、マーケットデータ SSE、割り当て、台帳、監査 |
app/openai_compat.py | OpenAI 互換の /v1/chat/completions(ストリーミング+使用量)、/v1/models、/v1/quote、自動購入 |
app/services.py | エージェントサービスのマーケットプレイス:出品、検索、エスクローによる呼び出し単位の実行、返金、評価 |
app/crypto_payments.py | USDC 決済経路:署名連携ウォレット、オンチェーン入金監視、検証済み払い出し、支払い能力 |
app/payments.py | Stripe Checkout 入金(署名付き、冪等な Webhook)、Stripe Connect のオンボーディングと払い出し |
app/seller_gateway.py | 本番用セラー:vLLM/SGLang/TGI サーバーのフロントエンドとして動作し、売り注文を出品状態に保ち、配信用 JWT を検証し、プレフィックスから再開 |
app/keygen.py | AETHER_JWT_PRIVATE_KEY_PEM 用の RS256 キーを生成 |
render.yaml, .github/workflows/ci.yml | ワンクリックの Render デプロイ(アプリ、Postgres、Key Value);lint、テスト、Docker エンドツーエンドを実行する CI |
app/seller_agent_sim.py | モックセラー:自動登録、容量の出品、配信用 JWT の検証、SSE の配信、スポットによるプリエンプションをシミュレート |
app/buyer_agent_sim.py | モックバイヤー:M2M ネゴシエーションを最初から最後まで実行 |
Dockerfile, docker-compose.yml | アプリイメージ、および Postgres 16、Redis 7(AOF)、清算機関、seller-a(低価格、不安定)、seller-b(信頼性が高い)、buyer |
tests/ | 非同期テスト 50 件:マッチング、エスクロー、認証、API キー、レート制限、再開、フェイルオーバー、繰り越し、過剰引き落としの競合、孤立データの復旧、OpenAI 形式、Stripe と暗号資産の入金および払い出し、セラーゲートウェイ |
実行方法
docker compose up -d --build --wait # postgres, redis, clearinghouse, seller-a, seller-b
docker compose run --rm --no-deps buyer # the buyer agent's end-to-end simulation
docker compose logs -f clearinghouse seller-a
open http://localhost:8000/docs # OpenAPI UI
docker compose down -v # tear down, wiping volumes
ローカルでの開発とテスト(redis-server が PATH に必要です。テストでは SQLite と一時的な Redis を使用します):
python -m venv .venv && . .venv/bin/activate && pip install -r requirements-dev.txt
pytest -q
シークレットスキャン用の pre-commit フックをクローンごとに一度インストールします(PATH に gitleaks が必要です。例:sudo apt-get install gitleaks):
git config core.hooksPath scripts/git-hooks
CI では追加の対策として、プッシュと PR のたびに gitleaks も実行します(.github/workflows/gitleaks.yml)。このリポジトリでは git add -A / git add . を絶対に実行せず、明示的にパスを指定してステージしてください。そうすれば、実行時の状態(.env、data/)がコミットに紛れ込むことはありません。
期待される出力(実際の docker compose run --rm --no-deps buyer の実行結果から抜粋)
== 2. The M2M boundary holds =============================================
sell attempt with a buy_inference token -> HTTP 403 insufficient_scope (Bearer realm="aether", error="insufficient_scope", scope="sell_compute")
inference before escrowing any funds -> HTTP 402 no_escrowed_allocation
tampered JWT signature -> HTTP 401 invalid_token
== 4. Order book for llama-3.1-70b-instruct ==============================
side $/1M tokens tokens orders
ASK 0.4 5000 1
ASK 0.35 400 1
== 5. Market BID 1000 tokens, protection cap $0.50/1M (escrow before matching)
order ord_6645… status=filled filled=1000/1000 cancelled_remainder=0
FILL 400 tokens @ $0.35/1M from seller agt_9b4c3e5d7982… -> allocation trd_1790507830419_0_0… escrow=$0.000140000
FILL 600 tokens @ $0.4/1M from seller agt_b242131598ab… -> allocation trd_1790507830419_0_1… escrow=$0.000240000
wallet: available=$0.999620000 escrow=$0.000380000 (price improvement vs cap already refunded)
== 6. 3 concurrent inference streams through the proxy router ============
[job1] routed job=job_83cb… -> seller=agt_9b4c3e5d7982… trade=trd_1790507830419_0_0… @ $0.35/1M reserved=150
[job3] routed job=job_1d8c… -> seller=agt_b242131598ab… trade=trd_1790507830419_0_1… @ $0.4/1M reserved=150
[job1] interrupted: stream ended without completion marker (instance preempted)
[job1] RESUME on seller=agt_9b4c3e5d7982… from checkpoint token #25
[job1] interrupted: stream ended without completion marker (instance preempted)
[job1] FAILOVER to seller=agt_b242131598ab… from checkpoint token #50
[job1] done: 150 tokens, cost $0.000057500, attempts=3, failovers=1, finish=length
[job1] segment seller=agt_9b4c3e5d7982… trade=trd_1790507830419_0_0… tokens=50
[job1] segment seller=agt_b242131598ab… trade=trd_1790507830419_0_1… tokens=100
== 8. Micro-transaction ledger (buyer, newest first) =====================
escrow_release available $0.000105000 allocation released by buyer
settlement escrow $-0.000040000 job_798b…: 100 tokens
settlement escrow $-0.000017500 job_798b…: 50 tokens
escrow_release available $0.000060000 price improvement
final wallet: available=$0.999825000 escrow=$0.000000000
== 9. Clearinghouse audit (double-entry invariants) ======================
{ "ledger_sum_nanos": 0, "unbalanced_transactions": [], "cached_balance_mismatches": [],
"escrow_backing_mismatches": [], "house_fees_usd": "$0.000001750", "ok": true }
SIMULATION PASSED
同じ実行時の清算機関のログ:
aether.exchange: FILL llama-3.1-70b-instruct 400 tokens @ $0.35/1M buyer=agt_7bf7… seller=agt_2edb… (taker=bid)
aether.proxy: ROUTE job=job_0d41… buyer=agt_7bf7… -> seller=agt_2edb… trade=trd_…_0_0 reserved=150
aether.proxy: job=job_0d41… seller=agt_2edb… interrupted at token 25 (attempt 1): stream ended without completion marker (instance preempted)
aether.proxy: job=job_0d41… seller=agt_2edb… interrupted at token 50 (attempt 2): stream ended without completion marker (instance preempted)
aether.proxy: SETTLED job=job_0d41… tokens=150 cost=$0.000057500 segments=[('trd_…_0_0', 50), ('trd_…_0_1', 100)] status=completed
API の概要
| メソッドとパス | スコープ | 備考 |
|---|---|---|
POST /v1/agents | —(サンドボックス) / X-Admin-Token | client_id と client_secret を返します(シークレットは一度だけ表示されます) |
POST /oauth/token、POST /oauth/revoke | クライアント認証情報 / ベアラー | RFC 6749 §4.4、RFC 7009 のサブセット |
PUT /v1/agents/me/endpoint | sell_compute | 販売者の Webhook です。AETHER_ALLOW_PRIVATE_SELLER_URLS=false により、https とパブリック IP が必須になります |
POST /v1/orders、GET/DELETE /v1/orders/{id} | bid→buy_inference、ask→sell_compute | price_usd_per_mtok、quantity_tokens、order_type、time_in_force、ttl_seconds |
GET /v1/book/{instrument}、GET /v1/market/{instrument}/stream | パブリック | 板の深さ。SSE(Redis Pub/Sub)による取引の記録 |
POST /v1/inference | buy_inference | SSE イベント:meta、トークンの data、resume、done / error |
GET /v1/jobs/{id} | buy_inference | ステータスとチェックポイント済みのテキスト(購入者の接続が切れた場合に出力を復元します) |
GET /v1/trades、POST /v1/trades/{id}/release | 任意 / buy_inference | 割り当て。解放すると未使用のエスクローが返金されます |
POST /v1/chat/completions、GET /v1/models、GET /v1/quote/{model} | buy_inference / パブリック | OpenAI 互換。max_price_usd_per_mtok と auto_buy 拡張機能に対応 |
POST /v1/agents/me/rotate-secret | 任意 | 新しいシークレットを発行します。古いシークレット、API キー、JWT は使用できなくなります |
GET /v1/billing/crypto、GET …/crypto/link-challenge、POST …/crypto/wallets、GET …/crypto/deposits、POST/GET …/crypto/withdrawals | 任意 | 署名で紐付けられたウォレットからの USDC 入金。紐付け済みの自分のウォレットへの出金 |
GET /v1/admin/crypto/payouts、POST …/payouts/{id}/paid / cancel、GET /v1/admin/crypto/solvency | X-Admin-Token | 出金キュー(オンチェーンで検証済み)、財務状況 |
GET /v1/services、POST /v1/services、PATCH /v1/services/{id}、POST /v1/services/{id}/invoke、POST /v1/services/calls/{id}/rating | パブリック / sell_compute / buy_inference | エージェントサービスのマーケットプレイス:エージェントが呼び出しごとに完了済みタスクを販売します。エスクローで保護され、失敗時は返金され、手数料は 10% です |
POST /v1/feedback、GET /v1/admin/feedback、GET /.well-known/agent.json | オープン / X-Admin-Token / パブリック | エージェントからのフィードバック、機械可読なエージェントカード |
POST /v1/billing/deposits、POST /v1/billing/stripe/webhook | 任意 / Stripe 署名付き | Stripe Checkout によるカード入金 |
POST /v1/billing/connect/onboard、POST/GET /v1/billing/withdrawals | sell_compute | Stripe Connect の KYC と出金 |
GET /v1/ledger | 任意 | エージェントの台帳エントリー |
GET /v1/audit、GET /v1/admin/stats | サンドボックスまたは X-Admin-Token | 不変条件、収益、取引量、アクティビティ |
POST /v1/sandbox/faucet | サンドボックスのみ | テスト用資金 |
実際の資金を扱う前に把握しておくべき課題
優先度を含む一覧は、docs/PRODUCTION.md に記載されています。 最も重要な点は以下のとおりです。
- 計測の信頼性。 プロキシは SSE のトークンイベントを数えるため、不正な販売者が出力を分割して「トークン」数を水増しする可能性があります。 課金には、対象のモデルに対応するトークナイザーを使用する必要があります。
- プロンプトトークンはまだ課金対象ではなく、販売者が実際にどのモデルを実行しているかを検証する仕組みもまだありません。
- 運用。 スキーマは
create_allで作成されます(最初のスキーマ変更の前に Alembic マイグレーションが必要です)。 また、Lua スクリプトは Redis プライマリが 1 つであることを前提としています。 - 規制。 実際の資金はプラットフォームとして Stripe Connect を通じて処理されますが、残高の保有と販売者への支払いには、利用する法域での法的確認が必要です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。