Drıftstack docs
Docs

Bundled LLM

Driftstack’s bundled LLM option lets customers run AI-driven agent sessions without their own Anthropic API key. Each agent turn counts a fixed amount against a monthly cap the customer controls (default $20).

Opting in, and the monthly cap (up to $100), are set by a person in the Settings page of the Driftstack dashboard. If there is an Anthropic key of your own — stored in the dashboard, or sent with a request in the x-byok-anthropic-api-key header — it is used instead of the bundled LLM.

The status read below is always available. Consent and budget enforcement surface as typed 402 responses at agent-session turn time (see below). If the bundled LLM is not available, a turn with no key of your own returns 502 byok-anthropic-required; the status read stays available.

Bundled billing is offered on the earlier API Builder and API Scale plans, and on Enterprise. On the earlier Team, Agency and API Starter plans the AI agent runs with your own Anthropic key only. Starter, Pro, Team and Scale run it on the AI credits they include each month, or on your own key. The Trial has no AI agent.

Get current status (settings + spend)

GET /v1/account/me/bundled-llm-status

Returns the consent flag, the cap and the month-to-date spend. Read it before an AI run to know whether a turn will be refused.

{
  "consent": true,
  "cap_cents": 2000,
  "used_this_month_cents": 450,
  "remaining_cents": 1550,
  "refused_count_this_month": 0,
  "month_started_at": "2026-05-01T00:00:00.000Z"
}

remaining_cents is max(0, cap_cents − used_this_month_cents). month_started_at is the UTC calendar-month boundary, so you can say when the budget resets without re-deriving it.

used_this_month_cents is the account’s total bundled-LLM spend, in cents, on agent-session turns since the start of the current UTC calendar month (month_started_at).

refused_count_this_month is a compatibility field and returns 0. Refusal events (402 BundledLlmBudgetExhausted) are not persisted as usage rows. Branch on remaining_cents <= 0 to drive a “you’ve hit the cap” message; that field is derived from real spend.

Requires broad read (or account_owner), because the response includes account-wide month-to-date spend and remaining budget.

Soft-cap enforcement

When the customer’s bundled-LLM spend reaches the cap, the agent session route refuses the turn with:

HTTP/1.1 402 Payment Required
Content-Type: application/problem+json

{
  "type": "https://errors.driftstack.dev/bundled-llm-budget-exhausted",
  "title": "Bundled-LLM monthly cap reached",
  "status": 402,
  "detail": "You've used $20.00 of your $20.00 monthly bundled-LLM budget. Raise the cap in the dashboard, up to the $100 maximum (it is changed there, not with an API key), supply your own Anthropic API key via PUT /v1/account/me/byok-anthropic-key, or wait for the next calendar month.",
  "spent_cents": 2000,
  "cap_cents": 2000
}

When the cap can still be raised, the detail says to raise it in the dashboard: the settings route is for the dashboard only and answers 403 to any API key, whatever its scopes.

The ways out:

  1. Raise the cap in the dashboard’s Settings page if it is below the $100 maximum
  2. Send your own Anthropic key in the x-byok-anthropic-api-key header, or store one in the dashboard’s Settings page
  3. Wait for the next calendar month

The SDK exposes the typed BundledLlmBudgetExhaustedError with .spent_cents / .cap_cents extension fields (Python: spent_cents / cap_cents; TS: spentCents / capCents; Go: SpentCents / CapCents).

When the deployment offers bundled-LLM but the customer hasn’t opted in (consent: false), the agent session route refuses with:

HTTP/1.1 402 Payment Required
Content-Type: application/problem+json

{
  "type": "https://errors.driftstack.dev/bundled-llm-consent-required",
  "title": "Bundled-LLM consent required",
  "status": 402,
  "detail": "This deployment offers bundled-LLM but your account has not opted in. Turn it on in the dashboard (the setting is changed there, not with an API key), or PUT /v1/account/me/byok-anthropic-key to bring your own Anthropic key (BYOK always wins)."
}

The SDK exposes the typed BundledLlmConsentRequiredError (no extension fields).

The detail says to turn it on in the dashboard: the settings route is for the dashboard only and answers 403 to any API key (its field is consent, not bundled_llm_consent). Opting in is done in the dashboard’s Settings page. On plans without bundled billing — every plan on offer, and the earlier Team, Agency and API Starter plans — this error does not mean “opt in”: opting in is refused on those plans. Add your own key instead — in the dashboard’s Settings page, or the x-byok-anthropic-api-key header on each message.

When consent is on but the account’s current plan no longer includes bundled billing (after a downgrade, for example), the turn returns 403 forbidden instead, asking you to upgrade or add your own key.

Branch on the problem type, not on the detail text: the detail is written for people and can change.

Models on bundled billing

Bundled billing runs the default model, Claude Sonnet 5.5, and the other models in the picker except Opus and Fable. Claude Opus models and Claude Fable 5.1 are available with your own Anthropic key only. When a session would run one of them on bundled billing — because the account has no key of its own — the request is refused with a 403:

HTTP/1.1 403 Forbidden
Content-Type: application/problem+json

{
  "type": "https://errors.driftstack.dev/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "Claude Opus 5 is available with your own Anthropic key. Add your key (PUT /v1/account/me/byok-anthropic-key, or the x-byok-anthropic-api-key header), or start a session with Claude Sonnet 5.5.",
  "requires_own_key": true,
  "model": "claude-opus-5"
}

This is checked when the session is created (for an account with no key of its own and bundled billing on) and again on every turn, because a session created with your own key moves to bundled billing if that key is removed or expires. A session using your own key keeps every model.

In the SDKs this is a ForbiddenError; read the flag from err.extensions.requires_own_key (TypeScript), err.problem["requires_own_key"] (Python) or Problem["requires_own_key"] (Go).

Errors

Status Type When
401 unauthorized missing or invalid bearer token
403 forbidden an Opus or Fable model on bundled billing (agent-session create or turn)
402 bundled-llm-budget-exhausted spend reached the cap; raise it (if below $100), BYOK, or wait
402 bundled-llm-consent-required deployment has bundled-LLM but the customer hasn’t opted in

The status read above does not return a 503. When bundled-LLM is not available on the deployment, the agent-session turn route returns 502 byok-anthropic-required for a turn with no key of your own; the status read keeps working.

Agent-session turns on bundled billing can also return 403 forbidden (the plan no longer includes bundled billing) and 429 rate-limited with retry_after_seconds: 5 (your account already has 3 turns running on bundled billing). No step ran, so wait for one to finish and send the same message again, Idempotency-Key and all. See Agent sessions — Errors.

Privacy + how turns are counted

  • On the earlier API Builder and API Scale plans, each agent turn counts a flat $0.10 against the customer-controlled monthly budget, whatever the model or token count. This budget is enforced by Driftstack but is not a separately itemized charge on your Stripe invoice today; Enterprise can use a contracted custom budget. The amount counted against the budget per turn is this flat value, not Driftstack’s actual provider cost. A turn refused before the model is called (a task the Acceptable Use Policy check refuses, or a session whose token budget is spent) counts nothing.
  • No prompt content is logged on Driftstack’s side beyond what customers can read in their own session transcripts.
  • Bundled-LLM consent does NOT grant Driftstack any rights to train models on customer prompts. The current bundled-LLM provider is Anthropic Claude; per their API terms, customer data is not used for training.