Skip to main content

予算管理が重要な理由

AIエージェントがループ内で有料APIを呼び出すと、コストがすぐに膨らむ可能性があります。予算管理を使用することで:
  • セッションごとの総支出に上限を設定できます
  • ドメインごとの上限を設定できます(例:api.weather.com でセッションあたり最大100 sats)
  • 各支払い前にコールバックを受け取れます
  • いつでも完全な支出レポートを取得できます

グローバル予算

import { L402Client, BlinkWallet } from "l402-kit";

const client = new L402Client({
  wallet: new BlinkWallet(process.env.BLINK_API_KEY!, process.env.BLINK_WALLET_ID!),
  budgetSats: 500, // max 500 sats total this session
});
402レスポンスに priceSats フィールドが含まれており、残りの予算を超過する場合、クライアントは支払いを行う前に BudgetExceededError をスローします — satoshiは消費されません。

ドメインごとの予算

const client = new L402Client({
  wallet,
  budgetSats: 2000,
  budgetPerDomain: {
    "api.weather.com": 100,
    "api.finance.com": 500,
  },
});
ドメインごとの上限はグローバル上限とは独立してチェックされます — 支払いを続行するには両方を通過する必要があります。

コールバック

const client = new L402Client({
  wallet,
  budgetSats: 1000,
  onSpend: (sats, url) => {
    console.log(`✓ Paid ${sats} sats → ${url}`);
    // log to your telemetry, update a dashboard, etc.
  },
  onBudgetExceeded: (url, sats) => {
    console.warn(`✗ Blocked: ${sats} sats requested by ${url} — budget exhausted`);
    // alert, notify Slack, etc.
  },
});
onBudgetExceeded / on_budget_exceededBudgetExceededError がスローされる直前に呼び出されます — ロギングやアラートに役立ちます。

支出レポート

const report = client.spendingReport();

if (report) {
  console.log(`Total spent: ${report.total} sats`);
  console.log(`Remaining:   ${report.remaining} sats`);
  console.log("By domain:", report.byDomain);
  // { "api.weather.com": 42, "api.finance.com": 105 }

  for (const tx of report.transactions) {
    console.log(`  ${tx.ts}  ${tx.sats} sats  ${tx.url}`);
  }
}
spendingReport() は予算が設定されていない場合、null / None を返します。

BudgetExceededError の処理

import { BudgetExceededError } from "l402-kit";

try {
  const res = await client.fetch("https://api.example.com/premium");
} catch (err) {
  if (err instanceof BudgetExceededError) {
    console.log(`Need ${err.required} sats, only ${err.remaining} remaining`);
    // gracefully degrade — return cached data, skip this step, etc.
  }
}

並行処理に関する注意事項

予算制限が重要な場合、並行する Promise.all 呼び出しで1つの L402Client インスタンスを共有しないでください。BudgetTracker.check()record()await(Lightning Network の支払い)によって分離されています。異なるエンドポイントへの2つの並行した client.fetch() 呼び出しは、どちらかが支出を記録する前に、両方が予算チェックを通過する可能性があります — つまり、合計コストが一時的に予算上限を1回の支払い分超過する可能性があります。安全なパターン — 順次呼び出し:
for (const url of urls) {
  const res = await client.fetch(url); // awaited one at a time
}
リスクのあるパターン — 並列呼び出し:
// Both may pass budget.check() before either calls budget.record()
const results = await Promise.all(urls.map(url => client.fetch(url)));
並列ワークロードの緩和策: 並行支払い1回分の超過を吸収するために、budgetSats を保守的に設定してください(例:実際の上限の80%)。厳密な制限が必要な場合は、呼び出しを順次処理してください。

全オプションリファレンス

オプションTypeScriptPythonデフォルト説明
グローバル予算budgetSatsbudget_sats無制限セッションの最大 sats
ドメインごとbudgetPerDomainbudget_per_domain{}ドメイン → 最大 sats のマップ
支出フックonSpendon_spend各支払い後に呼び出される
超過フックonBudgetExceededon_budget_exceededスロー前に呼び出される