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
| Status | Updated | Covered Files |
|---|
| 🟢 Stable | 2026-02-21 | creditService.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.
| Method | Purpose | Transaction? |
|---|
reserveCredits(orgId, amount, agentRunId) | Check balance, create reservation, increment agentCreditsReserved | Yes |
consumeCredits(orgId, reservationId, actualAmount) | Deduct from reservation, increment agentCreditsUsedThisMonth, decrement agentCreditsReserved | Yes |
releaseCredits(orgId, reservationId) | Return uncommitted credits, decrement agentCreditsReserved | Yes |
getCreditBalance(orgId) | Read-only balance calculation | No |
addPurchasedCredits(orgId, packSize, stripePaymentIntentId?) | Add one-time credit top-up, emit CREDITS_PURCHASED | Yes |
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:
| Limit | Potential | Professional | Ultimate |
|---|
maxAgentCreditsPerMonth | 100 | 1,000 | 10,000 |
maxConcurrentAgents | 1 | 3 | 10 |
maxAgentStepsPerRun | 5 | 20 | Unlimited |
maxAgentTokenBudgetPerRun | 50,000 | 200,000 | Unlimited |
maxAgentRunsPerMonth | 10 | 200 | Unlimited |
agentRunsPerHour | 3 | 20 | 100 |
Feature gates for agent capabilities:
| Feature | Min Tier | Description |
|---|
AGENT_BASIC | Professional | Single-step agent runs |
AGENT_MULTI_STEP | Professional | Multi-step agent workflows |
AGENT_AUTONOMOUS | Ultimate | Autonomous agent execution |
AGENT_ORCHESTRATION | Ultimate | Agent-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
status — active | 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
| Event | Emitter | When |
|---|
CREDITS_CONSUMED | AgentExecutionService | After each step consumes credits |
CREDITS_EXHAUSTED | QuotaService | Monthly credit limit reached |
CREDITS_PURCHASED | CreditService | One-time pack purchased |
QUOTA_WARNING | QuotaService | 80% or 90% of monthly limit used |
QUOTA_EXCEEDED | QuotaService | Monthly limit exceeded |
Each agent tool has a fixed credit cost per invocation:
| Tool | Credits | Rationale |
|---|
query_documents | 2 | RAG retrieval, low compute |
scan_expense | 3 | Single image analysis |
generate_journal | 5 | Structured text generation |
analyze_compliance | 8 | Multi-document analysis |
forecast_budget | 10 | Statistical + AI projection |
generate_report | 15 | Multi-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