From 7676e99ce6729be9d30856e135a4907f3a8272b0 Mon Sep 17 00:00:00 2001 From: Siarhei Harbuz Date: Tue, 28 Jul 2026 17:58:41 +0300 Subject: [PATCH] docs: refactor budgets --- docs/user-guide/budget-management/index.md | 148 +++++++++++++-------- 1 file changed, 93 insertions(+), 55 deletions(-) diff --git a/docs/user-guide/budget-management/index.md b/docs/user-guide/budget-management/index.md index ca88b39f..b88078ac 100644 --- a/docs/user-guide/budget-management/index.md +++ b/docs/user-guide/budget-management/index.md @@ -43,15 +43,13 @@ Each budget belongs to one of three independent categories: | **CLI** | Requests from codemie-code, codemie-claude, and other CLI agents to non-premium models | | **Premium Models** | Any requests to premium models — regardless of source: both UI and CLI | -:::info -Only one budget is charged per request: +Only one budget is charged per request. The category is resolved automatically by request type: -- Premium model → Premium Models budget (regardless of whether the source is UI or CLI) -- Non-premium model + CLI request → CLI budget -- Non-premium model + UI request → Platform budget - ::: +- Premium model → **Premium Models** (regardless of source: UI or CLI) +- Non-premium model + CLI request → **CLI** +- Non-premium model + UI request → **Platform** -Category is resolved automatically per request. If a project budget exists for the resolved category, it takes precedence over the user's global budget. +For details on how project membership affects category resolution, see [Budget Priority](#budget-priority). ## Budget Parameters @@ -95,32 +93,61 @@ For details on roles, see [Roles & RBAC](../../admin/security/roles-rbac). ### Budget Priority -``` -User request - │ - ▼ -Is the model premium? -(LITELLM_PREMIUM_MODELS_ALIASES) - │ - ┌────┴──────────────────────────────┐ - │ YES │ NO - ▼ ▼ -Premium Models budget Request source? -(regardless of source) │ - ┌──────────┴──────────┐ - │ CLI │ Web UI - ▼ ▼ - CLI budget Platform budget +
{ + const svg = e.currentTarget.querySelector('svg'); + if (svg) { + const serialized = new XMLSerializer().serializeToString(svg); + const blob = new Blob([serialized], {type: 'image/svg+xml'}); + window.open(URL.createObjectURL(blob)); + } + }} +> + +```mermaid +flowchart LR + A([User request]) --> B{"Premium model?
LITELLM_PREMIUM_MODELS_ALIASES"} + + B -->|YES| C[premium_models] + B -->|NO| D{Request source?} + + D -->|CLI| E[cli] + D -->|Web UI| F[platform] + + C & E & F --> G{"In a project with
ANY budget configured?"} + + G -->|NO| H["1. Personal budget
2. Default budget
3. ❌ Blocked"] + G -->|YES| I{"Base category
in project_scopes?"} + + I -->|YES| J[Project budget ✅] + I -->|NO| K{"Project has
Platform budget?"} + + K -->|YES| L[Project Platform budget] + K -->|NO| M[Personal / Default
Platform budget] + + H & J & L & M --> Z([Budget enforcement
LiteLLM Proxy]) ``` +
+ For each category, the first matching budget is applied in the following priority order: 1. **Project budget** — if the user's project has a budget configured for this category 2. **Personal budget** — if the user has a personal budget explicitly assigned for this category 3. **Default budget** — if neither project nor personal budget is assigned -:::info -If the user has no project budget for a given category — the personal or default budget applies, as if there were no project. +**Project context** applies when the user belongs to a project that has at least one budget configured. In this case, all requests are resolved within the project — regardless of category: + +- If the project covers the resolved category → the project budget is used +- If the project does not cover the resolved category → falls back to the project's Platform budget +- If the project has no Platform budget either → personal or default Platform budget is used + +If the project has no budgets configured at all, personal and default budgets apply as normal. + +:::note +The Platform budget acts as the universal fallback within a project. If a project has only a Platform budget, CLI and premium model requests are also charged against it. To track each category independently, configure a dedicated budget for each category on the project. ::: ### Personal Budgets @@ -191,14 +218,14 @@ The **Project members** table includes a **Budget Allocations** column showing e This is the key parameter that controls how the budget is distributed among members. -**Enforce member spend limits = off** (default) +**Enforce member spend limits = Disabled** (default) The budget acts as a shared team pool. Individual shares are calculated and stored in CodeMie, but no per-user hard limit is enforced in LiteLLM: - One member may spend $5, another $50 — nobody is blocked until the team collectively exhausts the full limit - If a member has a personal budget (e.g. $20), it is still irrelevant — the shared project limit applies to the whole team -**Enforce member spend limits = on** +**Enforce member spend limits = Enabled** Each member receives a hard individual limit in LiteLLM: @@ -223,8 +250,8 @@ The member is switched to fixed allocation mode. Their amount is locked, and the | Enforce member spend limits state | Override behavior | | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| **On** | Override sets a hard personal limit in LiteLLM. The remaining budget is recalculated and redistributed among members without an override | -| **Off** | Override records the calculated share in CodeMie DB, but no real per-user restriction exists — all members work through the shared project pool | +| **Enabled** | Override sets a hard personal limit in LiteLLM. The remaining budget is recalculated and redistributed among members without an override | +| **Disabled** | Override records the calculated share in CodeMie DB, but no real per-user restriction exists — all members work through the shared project pool | To remove an override — click **Clear Override** → the member returns to equal distribution and the remaining budget is recalculated. @@ -278,29 +305,39 @@ Use the **Budget** filter and **Search** field to quickly locate users by budget ### Basic Scenarios -| # | Configuration | Platform | CLI | Premium | -| --- | ------------------------------------------------------ | ------------------------------------------------- | -------------------------- | -------------------- | -| 1 | Default Platform budget only | ✅ Default Platform (individual counter per user) | ❌ Blocked — no CLI budget | ❌ Blocked | -| 2 | Default Platform + CLI + Premium | ✅ Default Platform | ✅ Default CLI | ✅ Default Premium | -| 3 | Personal Platform only | ✅ Personal Platform | ❌ No CLI budget | ❌ No Premium budget | -| 4 | Personal Platform + default CLI | ✅ Personal Platform | ✅ Default CLI | ❌ No Premium budget | -| 5 | Project Platform + personal Platform | ✅ Project (priority) | ❌ No CLI budget | ❌ No Premium budget | -| 6 | Project CLI + default Platform + CLI | ✅ Default Platform | ✅ Project CLI (priority) | ❌ No Premium budget | -| 7 | Project with no budget for category + default Platform | ✅ Default Platform | ❌ No CLI budget | ❌ No Premium budget | -| 8 | All three defaults + personal Premium | ✅ Default Platform | ✅ Default CLI | ✅ Personal Premium | +| # | Budget | Platform request | CLI request | Premium model request | +| --- | ---------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------- | +| 1 | Default: Platform only | ✅ Default Platform (individual counter per user) | ❌ Blocked — no CLI budget | ❌ Blocked — no Premium budget | +| 2 | Default: Platform + CLI + Premium | ✅ Default Platform | ✅ Default CLI | ✅ Default Premium | +| 3 | Personal: Platform only | ✅ Personal Platform | ❌ No CLI budget | ❌ No Premium budget | +| 4 | Personal: Platform, Default: CLI | ✅ Personal Platform | ✅ Default CLI | ❌ No Premium budget | +| 5 | Default: Platform + CLI + Premium, Personal: Premium | ✅ Default Platform | ✅ Default CLI | ✅ Personal Premium (priority over default) | +| 6 | Project: Platform only | ✅ Project Platform (priority) | ✅ Project Platform (fallback — no project CLI budget) | ✅ Project Platform (fallback — no project Premium budget) | +| 7 | Project: CLI only | ✅ Project CLI (fallback — no project Platform budget) | ✅ Project CLI (priority) | ✅ Project CLI (fallback — no project Premium budget) | +| 8 | Project: Premium only | ✅ Default Platform (no project Platform budget → global fallback) | ✅ Default Platform (no project CLI or Platform → global fallback) | ✅ Project Premium (priority) | +| 9 | Project: Platform + CLI + Premium | ✅ Project Platform | ✅ Project CLI | ✅ Project Premium | +| 10 | Project: no budgets configured | ✅ Personal Platform / Default Platform (if configured, otherwise ❌) | ✅ Personal CLI / Default CLI (if configured, otherwise ❌) | ✅ Personal Premium / Default Premium (if configured, otherwise ❌) | +| 11 | Personal: Platform, Project: Platform | ✅ Project Platform | ✅ Project Platform (fallback — no CLI budget) | ✅ Project Platform (fallback — no Premium budget) | + +### Project context and category fallback + +In rows 6–9 and 11, the user is in a project context (project has at least one budget configured). Personal and default budgets are bypassed for all categories — **except** when the project has no Platform budget at all (row 8 — Premium-only project), in which case global personal/default Platform budget is used as the final fallback. The **Platform budget is the universal fallback hub** within a project: if a project lacks a budget for the resolved category (CLI or Premium), the request falls back to the project Platform budget. Row 10 applies when the user is in a shared project with no budgets configured at all — the system treats it as if there is no project. + +### Personal space + +A personal space is technically a project (`project_type = personal`, `name = user@email`). When no project budget is assigned to it (typical case), it behaves identically to the "No project" context (rows 1–5). Row 11 shows the non-typical case where an admin has explicitly assigned a project budget to a user's personal space. ### Webhooks and Workflows LLM usage triggered by a Webhook or Workflow is charged to the budget of the user who created the integration. -:::info -**Key takeaways:** +### Key takeaways - If no budget exists for a category — requests for that category are blocked -- Configuring only a default Platform budget means users will not be able to use CLI -- Project budget has the highest priority and always overrides personal and default budgets -- When a project budget is active, the user's personal budget is not affected and is not charged - ::: +- Budgets for Platform, CLI, and Premium Models categories are independent. Configuring a Platform budget does not automatically cover CLI or premium model requests — each category must be configured separately. +- Project budget has the highest priority and overrides personal and default budgets — but only when the project has at least one budget configured. If the project has no budgets at all, personal and default budgets apply normally. +- When a project budget is active, the user's personal and default budgets are not affected and are not charged. +- ⚠️ **Platform budget is the universal fallback within a project context.** If a project has budgets for some categories but not others, requests to uncovered categories fall back to the project's Platform budget — not to personal or default budgets. The only exception is a Premium-only project (no Platform budget configured): in this case both Platform and CLI requests fall back to personal/default Platform budget, as the system always resolves uncovered categories through the Platform fallback path. To track each category separately within a project, configure Platform, CLI, and Premium Models budgets on the project explicitly. ## Spending Data Update Frequency @@ -383,15 +420,16 @@ This is not a bug. Enforcement precision is bounded by `LITELLM_CUSTOMER_CACHE_T ## Recommendations -| Goal | Recommendation | -| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Getting started | Create default budgets for all three categories (Platform, CLI, Premium) — otherwise users without a personal budget will be blocked in uncovered categories | -| Team cost control without blocking individual members | Create a project budget with **Enforce member spend limits = off** — the overall limit is controlled at the team level without blocking individual members | -| Strict per-user control within a project | Enable **Enforce member spend limits** — each member receives a fixed quota with blocking on overspend | -| VIP users / team leads | Use Override with **Enforce member spend limits** enabled to individually increase a specific member's quota | -| Adding new members to a project | After adding members, run a manual **Rebalance** — the budget is not recalculated automatically on member addition | -| Premium models | Create a separate default Premium Models budget and specify the model list in the platform configuration | -| Emergency unblocking | **Reset Budget** on the user card — resets the spending counter (Maintainer only) | +| Goal | Recommendation | +| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Getting started | Create default budgets for all three categories (Platform, CLI, Premium) — otherwise users without a personal budget will be blocked in uncovered categories | +| Team cost control without blocking individual members | Create a project budget with **Enforce member spend limits = Disabled** — the overall limit is controlled at the team level without blocking individual members | +| Strict per-user control within a project | Enable **Enforce member spend limits** — each member receives a fixed quota with blocking on overspend | +| VIP users / team leads | Use Override with **Enforce member spend limits** enabled to individually increase a specific member's quota | +| Adding new members to a project | After adding members, run a manual **Rebalance** — the budget is not recalculated automatically on member addition | +| Premium models | Create a separate default Premium Models budget and specify the model list in the platform configuration | +| Emergency unblocking | **Reset Budget** on the user card — resets the spending counter (Maintainer only) | +| Accurate per-category cost tracking within a project | Configure a **dedicated budget for each category** (Platform, CLI, Premium Models) on the project. Without all three budgets, requests to categories that are not configured fall back to the project Platform budget — making it impossible to distinguish platform, CLI, and premium model costs in project analytics | ## Platform Limitations @@ -401,7 +439,7 @@ The following summarizes known constraints in the current version of the budgeti - One budget per category per project - The category of a budget cannot be changed if there are active user assignments — all assignments must be removed first - Budget ID is generated automatically from the name and cannot be edited after creation -- Budget creation, modification, and deletion require the Maintainer role; Project Admin cannot manage budgets +- Budget creation and modification require the Maintainer role; Project Admin cannot manage budgets - No global platform-wide spending cap across all projects - Direct budget configuration via the LiteLLM API is not recommended — it may cause unpredictable platform behavior - When a project budget is recreated, the LiteLLM spending counter resets; historical spend in analytics (Elasticsearch) is preserved