Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Credit System Architecture

StatusUpdatedCovered Files
🟢 Stable2026-02-21creditService.ts, QuotaService.ts, entitlements.ts, usageTracking.ts, organizations.ts

Overview

The credit system controls how AI agent runs are budgeted, consumed, and billed. It uses a reserve → consume → release pattern backed by Firestore transactions for atomicity, ensuring that concurrent agent runs never overdraw an organization’s balance.
┌─────────────────────────────────────────────────────────┐
│                    Organization                         │
│  subscription.features.agentCreditsPerMonth: 1000       │
│  usageMetrics.agentCreditsUsedThisMonth: 450            │
│  agentCreditsReserved: 50 (active reservations)         │
│  agentCreditsPurchased: 200 (one-time top-ups)          │
│                                                         │
│  Available = (1000 + 200) - 450 - 50 = 700              │
└─────────────────────────────────────────────────────────┘

Key Components

CreditService

File: src/features/billing/services/creditService.ts Extends BaseService<Organization>. All mutation methods use runTransaction() for atomic reads and writes.
MethodPurposeTransaction?
reserveCredits(orgId, amount, agentRunId)Check balance, create reservation, increment agentCreditsReservedYes
consumeCredits(orgId, reservationId, actualAmount)Deduct from reservation, increment agentCreditsUsedThisMonth, decrement agentCreditsReservedYes
releaseCredits(orgId, reservationId)Return uncommitted credits, decrement agentCreditsReservedYes
getCreditBalance(orgId)Read-only balance calculationNo
addPurchasedCredits(orgId, packSize, stripePaymentIntentId?)Add one-time credit top-up, emit CREDITS_PURCHASEDYes

QuotaService

File: src/features/billing/services/QuotaService.ts Enforces tier-based limits across all resource types. For agent credits, it checks:
  • Monthly credit allocation vs. consumed
  • Emits QUOTA_WARNING at 80% and 90% thresholds
  • Emits QUOTA_EXCEEDED when limit is reached

Entitlements

File: src/config/entitlements.ts Defines per-tier agent limits in TierLimits:
LimitPotentialProfessionalUltimate
maxAgentCreditsPerMonth1001,00010,000
maxConcurrentAgents1310
maxAgentStepsPerRun520Unlimited
maxAgentTokenBudgetPerRun50,000200,000Unlimited
maxAgentRunsPerMonth10200Unlimited
agentRunsPerHour320100
Feature gates for agent capabilities:
FeatureMin TierDescription
AGENT_BASICProfessionalSingle-step agent runs
AGENT_MULTI_STEPProfessionalMulti-step agent workflows
AGENT_AUTONOMOUSUltimateAutonomous agent execution
AGENT_ORCHESTRATIONUltimateAgent-to-agent coordination

Credit Lifecycle Visual

Credit Lifecycle

1. Reservation

Before an agent run starts, credits are reserved to prevent overspend from concurrent runs.
startRun()


creditService.reserveCredits(orgId, budget, runId)

    ├─ Transaction reads org doc
    ├─ Calculates: available = monthlyLimit - used - reserved
    ├─ Validates: budget ≤ available
    ├─ Increments agentCreditsReserved on org doc
    └─ Creates CreditReservation subcollection doc
CreditReservation fields:
  • id, organizationId, agentRunId
  • amount — credits reserved
  • consumedAmount — credits actually used so far
  • statusactive | consumed | released | expired
  • expiresAt — auto-release after 1 hour (safety net)

2. Consumption

After each agent step, actual credits are deducted from the reservation:
executeStep()


creditService.consumeCredits(orgId, reservationId, creditsUsed)

    ├─ Transaction reads reservation doc
    ├─ Validates: creditsUsed ≤ remaining in reservation
    ├─ Increments consumedAmount on reservation
    ├─ Increments usageMetrics.agentCreditsUsedThisMonth on org
    └─ Decrements agentCreditsReserved on org

3. Release

On run completion (success, failure, or cancellation), unused credits are returned:
completeRun() / failRun() / cancelRun()


creditService.releaseCredits(orgId, reservationId)

    ├─ Transaction reads reservation doc
    ├─ Calculates: uncommitted = amount - consumedAmount
    ├─ Sets reservation status to 'released'
    └─ Decrements agentCreditsReserved on org by uncommitted

Balance Calculation

CreditBalance {
  total:          monthlyAllocation + purchasedExtra
  used:           agentCreditsUsedThisMonth
  reserved:       agentCreditsReserved (active reservations)
  available:      max(0, total - used - reserved)
  purchasedExtra: agentCreditsPurchased (one-time packs)
}

Credit Packs (Top-Ups)

Organizations can purchase additional credits as one-time packs via addPurchasedCredits(). These are added to agentCreditsPurchased on the organization document and factored into the balance calculation. The method emits a CREDITS_PURCHASED event for analytics and audit trail.

Firestore Data Model

organizations/{orgId}
  ├─ subscription.features.agentCreditsPerMonth  ← Monthly allocation
  ├─ usageMetrics.agentCreditsUsedThisMonth      ← Consumed this period
  ├─ agentCreditsReserved                        ← Active reservation total
  ├─ agentCreditsPurchased                       ← One-time pack total
  └─ creditReservations/{reservationId}          ← Subcollection
       ├─ amount, consumedAmount, status
       ├─ agentRunId
       ├─ _createdAt, _expiresAt (Firestore Timestamps)
       └─ expiresAt (ISO string for queries)

Event Emissions

EventEmitterWhen
CREDITS_CONSUMEDAgentExecutionServiceAfter each step consumes credits
CREDITS_EXHAUSTEDQuotaServiceMonthly credit limit reached
CREDITS_PURCHASEDCreditServiceOne-time pack purchased
QUOTA_WARNINGQuotaService80% or 90% of monthly limit used
QUOTA_EXCEEDEDQuotaServiceMonthly limit exceeded

Cost Model per Tool

Each agent tool has a fixed credit cost per invocation:
ToolCreditsRationale
query_documents2RAG retrieval, low compute
scan_expense3Single image analysis
generate_journal5Structured text generation
analyze_compliance8Multi-document analysis
forecast_budget10Statistical + AI projection
generate_report15Multi-section narrative generation

Monthly Reset

Credits reset at the beginning of each billing cycle:
  • usageMetrics.agentCreditsUsedThisMonth → 0
  • agentCreditsReserved → 0 (expired reservations cleaned up)
  • agentCreditsPurchased carries over until consumed

Maintenance

Update this document when:
  • Adding new credit pack sizes or pricing tiers
  • Changing tool credit costs
  • Modifying the reservation TTL or expiration logic
  • Adding new quota-enforced resource types