Platform Economics
The economics subsystem enforces rate limits, quotas, and funding lanes per user per request. Cost is reserved before execution and committed on success, released on failure.
Economics Flow
Key Concepts
| Concept | Description |
|---|---|
| Plan | Quota policy identity — defines requests/second, concurrency limits, and token quotas per class of users (anonymous, registered, paid, privileged). |
| Funding Lane | Subscription budget (monthly USD) · wallet credits · project budget. Determines which funding source covers the request. |
| Reservation | Cost reserved before execution begins. Committed on completion, automatically released on failure or EconomicsLimitException. |
Rate Limit Layers
-
1
Gateway layer
Requests/second throttling at Ingress. Configurable per tenant via
gateway.yaml. Enforces backpressure before tasks are enqueued. -
2
Economics layer
Per-user quotas (daily/monthly requests, concurrent sessions, hourly token budgets). Enforced by the economics subsystem at execution time.
BaseEntrypointWithEconomics for automatic enforcement. Always re-raise EconomicsLimitException unchanged.
Bundle Economics & Rate Limiting
from kdcube_ai_app.apps.chat.sdk.solutions.chatbot.entrypoint_with_economic import (
BaseEntrypointWithEconomics
)
@agentic_workflow(bundle_id=BUNDLE_ID)
class MyBundle(BaseEntrypointWithEconomics):
@property
def configuration(self):
return {"economics": {"reservation_amount_dollars": 2.0}, ...}
Default Quota Policies
| User Type | Concurrent | Req/Day | Req/Month | Tokens/Hour |
|---|---|---|---|---|
anonymous | 1 | 2 | 60 | 150k |
free | 2 | 100 | 30k | 500k |
payasyougo | 2 | 200 | 6k | 1.5M |
admin | 10 | unlimited | unlimited | unlimited |
EconomicsLimitException unchanged. The base report_turn_error() handles this correctly — never catch it silently.Payment Integration (Stripe)
Stripe handles all external payment flows: wallet top-ups (one-time credits), recurring subscriptions, refunds, and subscription cancellations. Project budgets are never topped up directly from Stripe events — only by admin actions or the subscription rollover job.
Webhook Flow
-
1
Checkout
User initiates a wallet top-up or subscription via
POST /api/economics/stripe/checkout/topupor.../subscription. The API creates a Stripe Checkout Session and returns a redirect URL. -
2
Stripe fires webhook
On payment completion Stripe sends an event to
POST /api/economics/webhooks/stripe. The handler verifies the HMAC signature, checks idempotency viaexternal_economics_events(keyed by Stripe event ID), and applies the change. -
3
Reconcile job
A cron-driven reconcile job (
STRIPE_RECONCILE_CRON) catches missed webhooks by fetching Stripe events ordered ascending bycreatedtimestamp from a Redis-stored watermark. All replay is idempotent.
Webhook Events Handled
| Event | Action |
|---|---|
payment_intent.succeeded | Top up wallet (lifetime credits) for wallet_topup kind |
invoice.paid | Top up subscription period budget; update subscription record |
refund.created / refund.updated | Finalize wallet refund pending event |
checkout.session.completed | Write stripe_subscription_id to DB (prevents race with invoice.paid) |
customer.subscription.updated | Sync subscription status and next_charge_at |
customer.subscription.deleted | Mark subscription canceled; rollover unused balance to project budget |
Subscription Plans & Funding Lanes
Each subscription plan in the subscription_plans table maps to a Stripe product via stripe_price_id. When invoice.paid fires, the handler tops up the user's subscription period budget (the funding lane for that billing cycle). On period end the rollover job moves unused balance into the project budget funding lane.
Wallet top-ups credit the lifetime credits funding lane directly. Refunds debit lifetime credits and issue a Stripe refund against the original payment_intent_id.
Key Configuration
| Setting | Source | Purpose |
|---|---|---|
services.stripe.secret_key | secrets.yaml | Stripe API key (sk_live_ or sk_test_) |
services.stripe.webhook_secret | secrets.yaml | Webhook signing secret (whsec_) |
STRIPE_RECONCILE_ENABLED | .env | Enable the reconcile cron job |
STRIPE_RECONCILE_CRON | .env | Cron schedule (default 45 * * * *) |
bypass_throttling_patterns | GATEWAY_CONFIG_JSON | Exclude ^.*/webhooks/stripe$ from rate limiting |
bypass_throttling_patterns. Without this, high-volume webhook bursts during reconcile catch-up may be throttled and Stripe will retry, causing duplicate processing attempts.Usage Reporting & Aggregations
The OPEX subsystem provides pre-computed accounting aggregates on top of raw usage events. These aggregates power the OPEX API endpoints and avoid rescanning event logs on every request.
Aggregate Levels
| Level | Storage Path | Breakdown |
|---|---|---|
| Hourly | analytics/<tenant>/<project>/accounting/hourly/YYYY/MM/DD/HH/total.json | Service, provider, model |
| Daily | analytics/.../daily/YYYY/MM/DD/total.json | Service, provider, model + per-user (users.json) + per-agent (agents.json) |
| Monthly | analytics/.../monthly/YYYY/MM/total.json | Service, provider, model; includes days_covered / days_missing |
| Yearly | analytics/.../yearly/YYYY/total.json | Service, provider, model; includes months_covered / months_missing |
Usage Event Types
Raw events are written under accounting/<tenant>/<project>/<YYYY.MM.DD>/<service_type>/. Each event carries a service breakdown with service (llm, embedding, ...), provider (anthropic, openai, ...), and model identifiers, plus token counts and a cost basis.
OPEX API Endpoints
| Endpoint | Backed By | Description |
|---|---|---|
GET /accounting/opex/total | Daily aggregates + raw gap-fill | Global usage totals with cost estimate for a date range |
GET /accounting/opex/users | Daily users.json | Per-user usage and cost breakdown |
GET /accounting/opex/agents | Daily agents.json | Per-agent usage and cost breakdown |
GET /accounting/opex/conversation | Raw events (prefix-optimized) | Per-conversation usage |
GET /accounting/opex/turn/* | Raw events (prefix-optimized) | Per-turn and per-turn-per-agent usage |
Cost Breakdown Example
// GET /accounting/opex/total?tenant=home&project=demo&date_from=2025-11-01&date_to=2025-11-21
{
"event_count": 1234,
"cost_estimate": {
"total_cost_usd": 123.45,
"breakdown": [
{ "service": "llm", "provider": "anthropic", "model": "claude-sonnet-...", "cost_usd": 78.90 },
{ "service": "embedding", "provider": "openai", "model": "text-embedding-3-small", "cost_usd": 44.55 }
]
}
}
Aggregation Scheduling
A nightly scheduler (driven by OPEX_AGG_CRON, default 0 3 * * * in Europe/Berlin) computes daily and monthly aggregates for yesterday. Cross-instance deduplication uses a Redis lock (acct:agg:{tenant}:{project}:{date}, TTL 4 hours).
Manual Backfill
# Backfill a date range
curl -X POST \
"http://localhost:8010/accounting/opex/admin/run-aggregation-range?start_date=2025-01-01&end_date=2025-01-10"