How the AutoGPT Platform Credit Billing System Works: Architecture & Implementation

The AutoGPT Platform credit billing system treats credits as internal currency managed through atomic PostgreSQL transactions and Stripe integration, enabling manual top-ups, automatic refills, refunds, and billing portal management.

The AutoGPT Platform (Significant-Gravitas/AutoGPT) implements a sophisticated credit billing system that handles agent execution costs as an internal currency. This architecture combines PostgreSQL's atomic transaction capabilities with Stripe's payment infrastructure to ensure secure, race-condition-free credit management at scale. Understanding this implementation reveals how the platform balances complex financial operations with high-concurrency agent execution.

Core Architecture and Data Model

The credit system centers on two primary database tables and a modular Python class structure that separates ledger logic from payment processing.

Database Schema: Immutable Ledger and Balance Cache

All credit operations rely on two PostgreSQL tables defined in the backend data layer:

  • CreditTransaction: An immutable ledger logging every credit change, including top-ups, usage deductions, grants, and refunds
  • UserBalance: A cached current balance for fast reads, synchronized atomically with the transaction log via Common Table Expressions (CTEs)

The UserCredit Model

Located in autogpt_platform/backend/backend/data/credit.py, the UserCredit class (and its fallback BetaUserCredit) implements all credit logic, including spending, top-ups, refunds, auto-refill triggers, and Stripe billing portal integration. The get_user_credit_model function (lines 96-120) selects between production UserCredit and beta modes based on the LaunchDarkly feature flag ENABLE_PLATFORM_PAYMENT.

Atomic Transaction Processing

The system guarantees financial consistency through database-level locking mechanisms that prevent race conditions during concurrent operations.

The _add_transaction Method

The _add_transaction method (lines 359-426 in credit.py) serves as the single point of entry for all credit mutations. It executes a Common Table Expression (CTE) with FOR UPDATE locking on the UserBalance row, preventing race conditions during concurrent agent executions. This method handles ceiling protection, underflow prevention, and simultaneous updates to both the CreditTransaction log and UserBalance cache in one atomic database call.

Spending Credits During Agent Execution

When agent blocks execute, the spend_credits method creates negative transactions via _add_transaction, passing the execution cost as a negative amount with transaction_type=CreditTransactionType.USAGE. If the resulting balance falls below the user's configured auto-top-up threshold, the system automatically triggers request_auto_top_up (lines 158-165) to prevent service interruption.


# Inside spend_credits (UserCredit)

balance, _ = await self._add_transaction(
    user_id=user_id,
    amount=-cost,                     # negative → spend

    transaction_type=CreditTransactionType.USAGE,
    metadata=SafeJson(metadata.model_dump()),
)

Stripe Integration and Payment Flows

The platform leverages Stripe for payment processing while maintaining internal credit accounting to decouple usage metering from payment provider logic.

Manual Top-Up Workflow

The _top_up_credits method (lines 736-805) creates Stripe PaymentIntent or SetupIntent objects, storing pending transactions as inactive records in the database. The frontend initiates this through requestTopUp, which calls the backend checkout flow. Upon Stripe confirmation, fulfillCheckout activates the transaction via _enable_transaction, atomically updating the UserBalance and enabling the credits for immediate use.

Billing Portal Access

The create_billing_portal_session method (lines 226-233) generates Stripe Billing Portal URLs using stripe.billing_portal.Session.create. Users access this functionality through the /profile/credits page located at autogpt_platform/frontend/src/app/(platform)/profile/(user)/credits/page.tsx, which calls api.getUserPaymentPortalLink() to hit the GET /credits/manage endpoint defined in autogpt_platform/backend/backend/api/features/v1.py (lines 51-62).

Auto-Top-Up Configuration

Users configure automatic refills through the User.top_up_config JSON field. When spend_credits detects a balance below the configured threshold, it invokes top_up_credits automatically without user intervention. The frontend submits these configurations via updateAutoTopUpConfig, which updates the backend through the set_auto_top_up endpoint.

// Auto-refill form submit
const submitAutoTopUpConfig = (e) => {
  e.preventDefault();
  const form = e.currentTarget;
  const amount = Number(form.topUpAmount.value) * 100;
  const threshold = Number(form.threshold.value) * 100;
  updateAutoTopUpConfig(amount, threshold)
    .then(() => toast({ title: 'Auto top-up config updated!' }))
    .catch(toastOnFail('update auto top-up config'));
};

Refund and Dispute Management

The system handles financial reversals through structured workflows that maintain ledger integrity while complying with payment provider requirements.

Processing Refunds

The top_up_refund method (lines 610-654) creates CreditRefundRequest records. If the user's remaining balance covers the top-up amount, Stripe processes an automatic refund via stripe.Refund.create; otherwise, the system registers a manual request for administrator review. The frontend triggers this through refundTopUp in the refund modal interface.

// In RefundModal.tsx
const refundCredits = (txKey, reason) =>
  refundTopUp(txKey, reason)
    .then(amount => {
      if (amount > 0) { /* auto-approved */ }
      else { /* manual review */ }
    })
    .catch(toastOnFail('refund transaction'));

Handling Disputes

Stripe webhook events (charge.dispute.created, charge.dispute.closed) invoke handle_dispute and deduct_credits (lines 676-743). These methods adjust UserBalance records and trigger notification emails through the notification system to alert administrators and users of account adjustments.

Frontend Implementation

The credit management UI resides in autogpt_platform/frontend/src/app/(platform)/profile/(user)/credits/page.tsx, utilizing a custom useCredits hook to interact with the REST API endpoints defined in autogpt_platform/backend/backend/api/features/v1.py.

Opening the billing portal:

// Inside CreditsPage.tsx
const openBillingPortal = () =>
  api.getUserPaymentPortalLink()
    .then(portal => router.push(portal.url))
    .catch(toastOnFail('open billing portal'));

Initiating manual top-ups:

// Submit handler in CreditsPage.tsx
const submitTopUp = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  const amount = parseInt(new FormData(e.currentTarget).get('topUpAmount') as string) * 100;
  requestTopUp(amount).catch(toastOnFail('request top-up'));
};

Security and Feature Flags

The entire credit billing system is gated by the LaunchDarkly feature flag ENABLE_PLATFORM_PAYMENT. When disabled, the system falls back to BetaUserCredit, which provides fixed monthly refills without Stripe integration. All API routes enforce authentication through Security(requires_user), validating JWT tokens and extracting user_id for every credit operation to ensure users can only modify their own balances.

Summary

  • The AutoGPT Platform credit billing system uses atomic PostgreSQL transactions with row-level locking (FOR UPDATE) to prevent race conditions during concurrent agent executions.
  • Stripe integration handles payment intents, billing portals, and refunds while the platform maintains an internal CreditTransaction ledger in autogpt_platform/backend/backend/data/credit.py.
  • Auto-top-up functionality automatically refills credits when balances drop below user-defined thresholds stored in User.top_up_config.
  • The system supports full refund workflows and dispute handling through Stripe webhooks (refund.created, charge.dispute.*) and manual review processes.
  • Feature flags allow seamless switching between production billing (UserCredit) and beta credit models (BetaUserCredit).

Frequently Asked Questions

How does AutoGPT Platform prevent race conditions when multiple agents spend credits simultaneously?

The platform uses a PostgreSQL Common Table Expression (CTE) with FOR UPDATE locking in the _add_transaction method (lines 359-426 of autogpt_platform/backend/backend/data/credit.py). This locks the user's UserBalance row during the transaction, ensuring that concurrent credit deductions read the correct balance and preventing double-spending scenarios even under high concurrency.

What happens when a user's credit balance drops below the auto-top-up threshold during agent execution?

The spend_credits method automatically triggers request_auto_top_up (lines 158-165) when a usage transaction causes the balance to fall below the threshold defined in User.top_up_config. The system then creates a Stripe PaymentIntent via _top_up_credits to refill the account, allowing agent execution to continue uninterrupted once the payment processes.

How does the refund process work in the AutoGPT Platform credit system?

The top_up_refund method creates a CreditRefundRequest record and checks if the user's current balance covers the refund amount. If sufficient funds exist, it processes an immediate Stripe refund via stripe.Refund.create and deducts the credits atomically. If not, it registers a manual refund request for administrator review, ensuring the ledger remains balanced while complying with financial regulations.

Can users manage their payment methods without leaving the AutoGPT Platform interface?

Yes. The create_billing_portal_session method generates a Stripe Billing Portal session URL that users access through the /profile/credits page. While Stripe hosts the actual payment management interface, the seamless redirect and return URL configuration create an integrated experience. The frontend calls api.getUserPaymentPortalLink() which hits the GET /credits/manage endpoint to retrieve the session URL.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →