Budgets

AgentKavach supports three budget periods — daily, monthly, and total — enforced in-memory with sub-millisecond checks. Cost is the primary dimension exposed through the Budget object. Token and runtime caps are configured separately as per-run guardrails (see Guardrails).

Dimensions #

Threshold alerts evaluate independently per dimension. The dimensions the SDK actually evaluates:

DimensionUnitConfigured via
costUSDbudget=Budget.daily / .monthly / .total
tokens_totaltokensmax_tokens_per_run=...
durationmillisecondsmax_runtime_seconds=...

ℹ️ Per-dimension alerts

Bind a channel to a specific dimension by tagging the ChannelConfig with budget_type. The dispatcher only fires the channel when usage on that dimension crosses the threshold.

Budget.daily(limit) #

A daily budget resets at midnight UTC every day. Ideal for capping per-day spend on production agents.

ParameterTypeRequiredDefaultDescription
limitfloatYesUSD limit per day. Must be > 0.
python
from agentkavach import AgentKavach, Budget

guard = AgentKavach(
    provider="openai",
    api_key="ak_prod_...",
    llm_key="sk-...",
    budget=Budget.daily(50),        # $50/day
)

response = guard.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
)

print(f"Spent: ${guard.spent:.4f}")
print(f"Remaining: ${guard.remaining:.4f}")
print(f"Utilization: {guard.engine.utilization:.1%}")

Budget.monthly(limit) #

A monthly budget resets on the 1st of each month at midnight UTC. Best for teams with monthly cloud billing cycles.

ParameterTypeRequiredDefaultDescription
limitfloatYesUSD limit per month. Must be > 0.
python
guard = AgentKavach(
    provider="anthropic",
    api_key="ak_prod_...",
    llm_key="sk-ant-...",
    budget=Budget.monthly(500),     # $500/month
)

Budget.total(limit) #

A total budget is a lifetime cap that never resets. Once the limit is reached, the agent is permanently blocked until the budget is manually increased.

ParameterTypeRequiredDefaultDescription
limitfloatYesUSD lifetime limit. Must be > 0. Never resets.
python
guard = AgentKavach(
    provider="google",
    api_key="ak_prod_...",
    llm_key="AIza...",
    budget=Budget.total(1000),      # $1,000 lifetime cap
)

Budget.org_budget(limit, period) #

An organization-level budget that applies across all agents in your org. When any agent makes an LLM call, spend is counted toward the org budget pool. If the org-wide limit is hit, all agents are blocked — regardless of their individual budgets.

Org budgets coexist with per-agent budgets. Each agent can have its own individual budget and share the org pool. The most restrictive limit wins — if either budget is exceeded, the call is rejected.

ParameterTypeRequiredDefaultDescription
limitfloatYesUSD limit for the entire organization. Must be > 0.
periodstr | PeriodNo"daily"Budget period: "daily", "monthly", or "total". Defaults to "daily".
python
from agentkavach import AgentKavach, Budget

# Individual agent budget: $10/day per agent
# Org budget: $50/day across ALL agents
org_pool = Budget.org_budget(limit=50, period="daily")

guard = AgentKavach(
    provider="openai",
    api_key="ak_prod_...",
    llm_key="sk-...",
    agent_name="research-bot",
    budget=Budget.daily(10),        # per-agent: $10/day
    org_budget=org_pool,            # org-wide: $50/day
)

response = guard.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
)

# Spend is tracked against BOTH budgets
print(f"Agent spent: ${guard.spent:.4f}")
print(f"Agent remaining: ${guard.remaining:.4f}")

ℹ️ Most restrictive wins

When both an agent budget and an org budget are set, the agent is blocked as soon as either limit is reached. For example, if Agent A has a $10/day budget and the org has a $50/day budget, Agent A stops at $10 even if the org pool has room. Conversely, if the org pool hits $50, all agents stop even if their individual budgets have room.

Individual vs. Org Budgets #

AgentKavach supports two levels of budget enforcement that work independently or together:

FeatureIndividual BudgetOrg Budget
ScopeSingle agentAll agents in the org
Set via SDKbudget=Budget.daily(10)org_budget=Budget.org_budget(50)
Set via YAMLagents.<name>.budget.dailyorg_budget.limit / org_budget.period
Set via DashboardSettings → Agent BudgetsSettings → Organization Budget
Set via APIPOST /v1/agents/<name>/budgetsPOST /v1/org/budgets
EnforcementBlocks only this agentBlocks ALL agents in the org
Ingest rejection429 budget_exceeded429 org_budget_exceeded

Example: Both budgets together

python
from agentkavach import AgentKavach, Budget

# Org-wide cap: $50/day across all agents
org = Budget.org_budget(limit=50, period="daily")

# Each agent gets its own limit PLUS the shared org cap
research = AgentKavach(
    provider="openai",
    api_key="ak_prod_...",
    llm_key="sk-...",
    agent_name="research-bot",
    budget=Budget.daily(20),    # individual: $20/day
    org_budget=org,             # shared: $50/day
)

support = AgentKavach(
    provider="anthropic",
    api_key="ak_prod_...",
    llm_key="sk-ant-...",
    agent_name="support-bot",
    budget=Budget.daily(15),    # individual: $15/day
    org_budget=org,             # shared: $50/day
)

# research-bot stops at $20 (individual limit)
# support-bot stops at $15 (individual limit)
# Both stop if combined org spend hits $50

Checking Budget State #

You can inspect the current budget state at any time:

python
# Current spend in the active period
guard.spent          # e.g. 12.34

# Remaining budget
guard.remaining      # e.g. 37.66

# Utilization as a fraction (0.0 to 1.0)
guard.engine.utilization  # e.g. 0.2468

What Happens When Budget Runs Out #

When the budget is exhausted, AgentKavach follows a deterministic sequence:

  1. BudgetExceededError is raised before the LLM call is made.
  2. You never pay for a call that exceeds your budget.
  3. The on_kill callback fires if configured.
  4. All subsequent guard.create() calls raise immediately.
  5. Fail-open: internal AgentKavach errors never block LLM calls — only BudgetExceededError propagates.
python
from agentkavach.exceptions import BudgetExceededError

try:
    response = guard.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )
except BudgetExceededError as e:
    print(f"Budget exhausted: {e}")
    # e.spent, e.limit, e.period available

ℹ️ Near-zero latency

Budget checks run in-memory (~0.1ms). No network calls, no latency.