Dokümanlar menüsü
Bütçe & kota (402)
Organizasyon başına token/maliyet limiti zorlar: yazma yolunda limit aşılırsa yeni run/stream/workflow isteği 402 alır (resume serbest); limitler Studio'dan yönetilir.
Ne işe yarar / ne zaman kullanılır#
Birden çok organizasyona aynı agent'ı sunuyorsanız, bir organizasyonun kontrolsüz token/maliyet tüketimi diğerlerini etkilememeli ve faturanızı patlatmamalı. Bütçe/kota bunu yazma yolunda (yeni run/stream/workflow isteklerinde) zorlar: organizasyonun kullanımı journal'dan (recordRunUsage ile artımlı sayılır) tanımlı limiti (token veya USD) aşarsa istek 402 ile reddedilir. Askıdaki işin devamı (resume — ör. bekleyen tool onayı ya da suspend edilmiş workflow) bu kapıdan etkilenmez, aksi halde aşan organizasyonda hiçbir askıdaki iş asla bitirilemezdi. Limitler journal'da (__budget__:*) yaşar — Studio'dan canlı değiştirilebilir, host'u yeniden deploy etmeye gerek kalmaz; host config (RestApiOptions.budgets) yalnız fallback'tir.
Kurulum / import#
Ayrı bir alt-paket gerekmez; kapı @gnldev/server'ın createRestApi'sine gömülüdür, birincil primitifler @gnldev/durable'dan gelir:
import { createGnl } from '@gnldev/durable';
import { createRestApi } from '@gnldev/server';
// To enforce it directly (for non-HTTP paths):
import { checkBudget, assertBudget, getOrgUsage, readBudget, isBudgetExceeded, BudgetExceededError } from '@gnldev/durable';Adım adım kullanım#
En yaygın kullanım: createRestApi'ye org ile birlikte budgets.default fallback limiti verin — journal'da henüz özel bir __budget__ yoksa bu limit uygulanır:
// org: every organization gets an isolated journal (exactly-once is inherited); budgets: the fallback limit —
// the __budget__ document written from Studio OVERRIDES it and returns 402 to the organization that exceeds it.
const DEFAULT_TOKEN_LIMIT = Number(process.env.GNL_DEFAULT_TOKEN_LIMIT ?? 100);
app.route('/api', createRestApi(config, {
title: 'SWAPI Pro',
auth,
org: {},
budgets: { default: { tokenLimit: DEFAULT_TOKEN_LIMIT } },
}));
// call again with a different runId -> 402 once 100 tokens are exceededOrganizasyon bazlı farklı limitler için perOrg kullanılır (etkin limit her zaman journal > perOrg[id] > default sırasıyla çözülür):
budgets: {
default: { tokenLimit: 100_000 },
perOrg: { 'acme-corp': { usdLimit: 25 } },
}Aşım anında istemci JSON gövdesiyle 402 alır:
{ "error": "budget/quota exceeded — the new run was refused", "usage": { "runs": 3, "tokens": 142, "costUsd": 0 }, "limit": { "tokenLimit": 100 } }Kalan kotayı/kullanımı sorgulamak için hazır /usage ucu vardır (aynı kapsam çözümlemesini kullanır: organizasyon header'ı ya da bağlı kimlik):
GET /usage
Headers: x-gnl-org: acme-corp
→ { "org": "acme-corp", "usage": { "runs": 3, "tokens": 142, "costUsd": 0 }, "limit": { "tokenLimit": 100 }, "exceeded": true }@gnldev/server HTTP dışındaki yollarda (@gnldev/queue worker, @gnldev/scheduler cron, @gnldev/a2a, doğrudan runDurable/createGnl gömme) kota otomatik zorlanmaz — kendi run öncesi kontrol noktanızda assertBudget'i çağırmanız gerekir:
import { assertBudget, BudgetExceededError } from '@gnldev/durable';
try {
await assertBudget(reader, { orgId, fallback: { tokenLimit: 100_000 } });
// ... start the run here
} catch (e) {
if (e instanceof BudgetExceededError) {
// build your own 402 / refusal response from e.check.usage and e.check.limit
}
throw e;
}API referansı#
RestApiOptions.budgetscreateRestApi'nin bütçe fallback opsiyonu: { default?, perOrg? } — journal'daki __budget__ bunu ezer.
checkBudgetEtkin limiti (journal > fallback) okuyup kullanımla kıyaslar; { exceeded, usage, limit } döner (async).
assertBudgetcheckBudget çağırır, aşımda BudgetExceededError fırlatır — run başlamadan önce host-dışı yollarda çağrılır.
getOrgUsageOrganizasyonun (veya paylaşılan kök alanın) toplam runs/tokens/costUsd'unu döner; artımlı __usage__ sayacını kullanır (O(1)).
readBudgetJournal'daki bütçe dokümanını okur: önce __budget__:<orgId>, yoksa __budget__:default.
isBudgetExceededSaf fonksiyon: OrgUsage ile BudgetLimit karşılaştırıp true/false döner.
BudgetLimitusdLimit? / tokenLimit? alanlarına sahip limit tanımı.
BudgetExceededErrorassertBudget aşımda fırlatır; check (BudgetCheck) alanında usage+limit taşır.
recordRunUsageRun TAMAMLANINCA maliyetini __usage__ sayacına ekler (idempotent — aynı runId ikinci kez sayılmaz).
createBoundedUsageCacheSınırlı (LRU) UsageCostCache üretir — çok organizasyonlu kurulumlarda önbelleğin sınırsız büyümesini önler.
runId ile gelen bir resume isteği (bekleyen tool onayı veya suspend edilmiş workflow'un devamı) journal'da zaten iz bıraktığından kapıdan otomatik geçer — aşan bir organizasyonda askıdaki iş asla kilitlenmez. Journal listRuns desteklemiyorsa kota zorlanamaz (fail-open) ve host konsola uyarı basar.cost-observability sayfasına, organizasyon izolasyonunun temelini anlamak için multi-organization sayfasına, limitleri Studio'dan düzenlemek için studio-inspector sayfasına bakın.