Sayay

npm @carloscortezcloud/sayay-guard · PyPI sayay

Per-user budget guardrails for AI agents. Set daily/monthly/session limits. Actions: allow → warn → degrade → block.

SayayGuard

The main guard class. Create once per application, check before each LLM call.

import { SayayGuard, MemoryStorage } from '@carloscortezcloud/sayay-guard';

const guard = new SayayGuard({
  storage: new MemoryStorage(),        // Required: where spend data lives
  budget: {                           // Required: at least one limit
    dailyUsd: 5.0,                        // $5/day per user
    monthlyUsd: 50.0,                     // $50/month per user
    sessionCredits: 0.50,                // $0.50 per session (optional)
  },
  thresholds: {                       // Optional: custom thresholds
    warn: 0.80,                          // Warn at 80% (default)
    degrade: 0.95,                       // Degrade at 95% (default)
  },
});

Methods

guard.check(userId, costUsd)

Check if this spend is allowed. Call BEFORE each LLM request.

const decision = await guard.check('user-123', 0.01);
// → { action: 'allow', remaining: 4.99 }
// → { action: 'warn', remaining: 0.95, reason: '80% of daily budget used' }
// → { action: 'degrade', remaining: 0.25, reason: 'Budget low' }
// → { action: 'block', remaining: 0, reason: 'Daily budget exceeded' }
guard.record(userId, costUsd)

Record the actual cost after the LLM call completes.

await guard.record('user-123', 0.003); // actual cost

Budget Configuration

FieldTypeDescription
dailyUsdnumberMax USD per user per day (resets at midnight UTC)
monthlyUsdnumberMax USD per user per month (resets 1st of month)
sessionCreditsnumberMax USD per session (resets at session boundaries)

Guard Actions

allow

Proceed with LLM call

Below 80%
warn

Proceed but warn user/admin

80% – 95%
degrade

Auto-switch to cheaper model

95% – 100%
block

Refuse the LLM call

100% exceeded

Storage Backends

Sayay supports pluggable storage. Built-in options:

MemoryStorage

In-memory. Best for development, single-process, or stateless deployments. Data is lost on restart.

KVStorage

Cloudflare KV. Works across Workers. Affordable, eventually consistent.

SayayStorage

Implement this interface for Redis, D1, DynamoDB, or any custom backend.

interface SayayStorage {
  getSpend(userId: string): Promise<{daily: number, monthly: number, session: number}>;
  addSpend(userId: string, costUsd: number): Promise<void>;
}

Integration with Tinkuy

Pass the guard to the Agent constructor — it automatically checks before and records after each LLM call.

const agent = new Agent({
  router: new StyrRouter({ /* ... */ }),
  guard: new SayayGuard({
    storage: new MemoryStorage(),
    budget: { dailyUsd: 5.0 },
  }),
  tools: [myTool],
  systemPrompt: 'You are a FinOps assistant.',
});

// Guard is auto-invoked on each LLM call in the loop
// If action === 'block', the agent stops with an error
// If action === 'degrade', Tinkuy skips expensive models