Skip to content

Configuration

Admin hub

Path: /admin/config/ai/ai-metering (permission: administer ai metering). Links to: Dashboard by User, Dashboard by Role, AI Usage Log, Metering Settings, Drupal AI Settings (core ai provider configuration), Permissions, and, for the current user, a Personal usage link if they hold view own ai metering usage.

Model pricing source

Path: Settings form, "Model pricing source" section (open by default).

  • A Pricing source select lets you choose between the PricingSource plugins: litellm (LiteLLM public cost map, 100+ models) and models_dot_dev (models.dev community API). Third-party modules can add more by implementing PricingSourceInterface (typically extending PricingSourceBase) with a @PricingSource(id, label) annotation.
  • A "Sync now from source" button triggers ModelPricingService::syncFromSource() against whichever source is active; the same sync is available from the command line via drush ai-metering:sync-pricing.
  • The form shows the last sync date/time and the count of synced models.

Manual pricing overrides

Path: Settings form, "Manual pricing overrides (USD per token)" section (collapsed by default).

Per-model input/output USD-per-token fields for a small built-in list of common models (Anthropic Haiku/Sonnet/Opus, OpenAI GPT-4o/GPT-4o mini). A manual entry is never overwritten by a pricing sync; syncs only add or update entries that have no manual override.

Quota alerts (email and webhook)

Path: Settings form, "Quota alert emails" section (open by default; the fieldset title predates the webhook channel but now covers both).

Alerting is a two-layer system: - AlertService decides whether an alert fires: once per threshold crossing per user per month, when tokens_used transitions from below to at-or-above the threshold. It never fires twice for the same crossing. - AlertChannel plugins decide how the alert is delivered. Every enabled channel receives every alert; a delivery failure in one channel is logged and never blocks the others or the AI call that triggered it.

Two channels ship out of the box:

Channel Plugin ID Enabled when Delivery
Email email alerts.emails is non-empty One email per configured recipient via the core mail manager.
Webhook webhook alerts.webhook_url is set A JSON POST with a human-readable text key (renders as-is in Slack/Teams incoming webhooks) plus structured fields: event, username, uid, threshold_pct, pct_used, tokens_used, budget. 5-second timeout.

Settings-form fields: - Global alert threshold (%) — default 75. Per-user overrides can be set inline from Dashboard by User. - Alert recipient emails (one per line) — leave empty to disable the email channel. - Send quota alerts to a webhook (checkbox) + Webhook URL — the URL field is only required/visible when the checkbox is checked. Validation rejects anything that is not an absolute http(s) URL, and rejects localhost, loopback, private, and reserved-range addresses to close off SSRF against internal services. - Email user when Ollama fallback activates / Email admin when Ollama fallback activates — separate notification toggles (default: both on) for the moment a user's quota is exceeded and the fallback provider takes over, independent of the threshold-crossing alert above.

Adding a channel: implement AlertChannelInterface (isEnabled(), send(array $alert)), typically by extending AlertChannelBase, and annotate the class @AlertChannel(id: "...", label: @Translation("...")) in src/Plugin/AlertChannel/. No core patch required.

Quota defaults and retention

Path: Settings form, "Quota defaults" section (collapsed by default).

  • Default monthly token quota per user — default 100,000.
  • Raw usage log retention (days)usage_retention_days; default 0 (keep raw rows forever). See Monthly rollup and retention purge for what this actually deletes and when.
  • Additional local provider IDs — one per line; calls from these provider IDs are recorded as local/free on top of the built-in local set (ollama, lmstudio, localai, koboldcpp). Use this when, for example, an openai-compatible provider plugin is actually pointed at a local Ollama or LM Studio endpoint.
  • Summarization output/input ratio and Translation output/input ratio — used to pre-estimate output tokens for these two operation types before the call is dispatched (defaults 0.20 and 1.10 respectively).
  • Fallback provider when quota is exceeded / Fallback model — e.g. provider ollama, model llama3.2:latest. Leave the provider empty to block the call with an error instead of rerouting.

Default quota by role

Path: Settings form, "Default quota by role" section (collapsed by default).

One numeric field per configurable role (the anonymous and authenticated roles are excluded from the list). A value of 0 means "inherit the global default" for that role. If a user holds multiple roles, the highest configured budget wins. An individual per-user override, set from Dashboard by User, always takes precedence over any role default.

LiteLLM proxy integration

Path: Settings form, "LiteLLM proxy integration (optional)" section (collapsed by default).

Purely for sites that already route AI calls through a self-hosted LiteLLM proxy: an enable checkbox, the proxy base URL, and a master API key (rendered as a password field; leaving it empty on save keeps the previously stored key). When enabled, the litellm-user-spend and litellm-report Drush commands pull authoritative spend data straight from the proxy instead of the local usage log.

Currency display

Path: Settings form, "Currency display" section (collapsed by default).

  • Display currency — USD, CAD, EUR, GBP, or AUD, JPY.
  • Exchange rate cache TTL (seconds) — default 3600.
  • Manual fallback rates — one field per non-USD currency, used only when the Frankfurter API is unreachable.

See Multi-currency setup for the full mechanics.