---
title: Built-in AI helpers (how they're powered — paid cloud vs free BYO key)
---

# Built-in AI helpers (how they're powered — paid cloud vs free BYO key)

## What it is

Omniscio runs a set of small **built-in AI helpers** in the background — session titles,
AI suggestions, reply drafts, the daily digest, email summaries, and similar utility calls.
These are separate from your **coding sessions** (which run on your own Claude / Codex / other
accounts) and from your **prepaid `jls_sk_` API keys** (see [api-keys.md](api-keys.md)). They are
cheap utility-model calls that keep the app's small conveniences working.

## Where to find it

Two places matter, and neither has a screen of its own. Your own **OpenRouter key** — the thing
that makes the helpers run on your account — is entered in **Settings → Accounts & Providers →
API Keys**, and your plan together with your live usage and next reset date is on
**Settings → Plan & Usage**. The helpers themselves just run in the background.

## How it behaves

### How they're powered (plan-gated, since 2026-07-20)

The helpers are powered differently depending on your plan, decided **per call** in this order:

1. **Your own key always wins.** If you've entered your **OpenRouter key** (Settings → Accounts &
   Providers → API Keys → **"Your OpenRouter key"**, an `sk-or-…` value) — or you have a configured
   Anthropic API-key account — the helpers run **directly on your key**. This is true on **any**
   plan, free or paid, and your call is never rerouted through Omniscio's infrastructure.
2. **Paid plan, no own key → Omniscio's cloud.** On a paid plan (Pro / Team / Enterprise), and
   signed in, the helpers run through **Omniscio's company-paid cloud gateway** — no key of your own
   needed. This is the built-in-AI benefit that comes with a paid subscription.
3. **Free plan, no own key → the helpers pause.** On the free plan with no key of your own, the
   helpers **pause** and surface a **"Built-in AI helpers are paused"** card in the inbox. The rest
   of the app keeps working; only the built-in AI helpers wait until you add an OpenRouter key.
   There is **no** silent fallback onto Omniscio's cloud (that's the paid benefit) and no bundled key.

Signed-out or an unrecognized plan is treated as **free** (bring your own key) — conservative, so
the company cloud is never handed to an unverified plan.

### What the limit actually is

The allowance is a **money** ceiling per user per month, not a request count — `PER_USER_MONTHLY_USD_BY_TIER`
in [paid-offering.ts](../../src/shared/paid-offering.ts), enforced by the gateway:

| Plan       | Monthly built-in-AI allowance |
| ---------- | ----------------------------- |
| Free       | `$0`                          |
| Pro        | `$0`                          |
| Team       | `$0`                          |
| Enterprise | `$0`                          |

**As of 2026-08-25 that allowance is `$0` on every plan** (owner decision — no free company-funded AI
budget on any tier). In practice this means the built-in helpers always run on **your own key**:
general in-app AI declines with a 402 and falls back to your OpenRouter/Anthropic key or your prepaid
credit. Three safety-net features — the inbound-email security screen, the keyless Ask-Omniscio help
and the new-user onboarding sessions — are exempted from the per-user cap in the gateway (up to a
small daily allowance per person) and still run on the shared company pool.

**Session titles are included in every paid plan (since 2026-09-30).** On Pro, Team or Enterprise
with no key of your own, titles run on Omniscio's cloud even though the allowance is `$0` — about
$0.0002 a title. The per-person daily limit and the company-wide caps still apply. On the free plan
with no key of your own, a session is titled from its first words instead.

The meter still resets at the first instant of the next **UTC** month, and two company-wide ceilings
sit above the whole lane: a monthly cap on this internal lane and a `$3,000`/month Cloud Billing
budget. Your live usage and reset date are on **Settings → Plan & Usage**.

> **Read the lane cap from the code, never from a number typed into a page.** The two ceilings do
> different jobs and are easy to conflate:
>
> - the lane cap is a **hard stop** — over it the lane 402s and calls fall back to your own key. Its
>   shipped value is `DEFAULT_GLOBAL_MONTHLY_USD` in
>   [company-ledger.ts](../../gateway/gateway/company-ledger.ts).
> - the Cloud Billing budget is **alert-only** — it emails and never halts spend. Its value is
>   `GATEWAY_BUDGET_MONTHLY_USD` in [deploy.sh](../../gateway/deploy.sh).
>
> **On the lane cap's current value:** the owner has deliberately set it ABOVE the Cloud Billing
> budget, so in practice the alert fires long before anything hard-stops. The mechanism is still
> armed — it is the only fail-closed money stop in the footprint — it simply no longer binds.
> This page previously quoted a `$150`/month figure and then a `$300`/month one, both now stale;
> with the cap set that high, any concrete number here would go stale again, which is why this page
> states the shape and points at the declaration instead.

> A missing tier entry means **uncapped**, not "no allowance" — which is exactly why every tier is
> listed explicitly at `$0` rather than removed. Never delete a tier's entry to express "this tier
> gets nothing"; that silently makes it unlimited.

### The client-side daily safety net (a runaway brake, not your budget)

Separately from the gateway's per-user **monthly** ceiling above, the shared helper path carries a
**client-side daily net**: once a helper has spent **$25 in one local-midnight day** under its own
label, that helper stops calling and resumes the next day. Session titles, suggestion chips, reply
drafts, hub/app/skill descriptions and the other small assists all run through the one shared path,
so this is the net under all of them.

Read what it is before treating it as a budget. The constant describes itself as *"a safety net, not
a tuning knob"* and is **deliberately high** — normal use of these helpers is cents a day, so the
net exists to stop a genuine runaway (a supervisor loop re-firing on a stuck session all day), not
to meter you. It is counted **per label, per cost source**, summed across accounts, and it is **not**
the per-user spend ceiling: when a helper routes through the company gateway, the authoritative
per-user ceiling is enforced server-side there and answers 402 *before* the call is forwarded. This
is also a different limit from the two "helpers stopped" cards below, which are about the monthly
allowance.

### The two "helpers stopped" cards are different

One inbox row (dedupKey `pooled-ai-monthly-limit`), but two honest messages — they must never be
swapped, because only one of them involves anything actually being spent:

- **"Built-in AI helpers are paused"** (`no-plan-allowance`) — the free-plan pause above. Nothing was
  consumed and no allowance ever existed, so this card never says an allowance was "used". It offers
  both routes out: upgrade, or paste your own key.
- **"Monthly AI allowance used"** (`allowance-exhausted`) — a real gateway 402. A genuine allowance
  ran out; the card names the reset date, and the amount too **when there is a real one to name**.
  Because every tier sits at `$0` today, the amount is omitted rather than printed — a card reading
  "you have used your $0" would be the same species of lie these two variants exist to prevent.

Both name the helpers that stopped (session titles, suggested replies, Plain Speak summaries, the
daily digest, email summaries) and confirm your Claude coding sessions, projects, inbox and
automations are unaffected. The button opens **Settings → Plan & Usage**. The tier behind the copy is
read with `currentEffectiveCachedTier()`, so signed-out and lapsed-paid users both get the free
card with its upgrade path — see
[internal-ai-gateway-routing-contract.md](../../.claude/memory/contracts/internal-ai-gateway-routing-contract.md) I9.

#### The card lands at most once a month

The allowance is monthly, so the notice is too — it cannot reach the user more than once per billing
period, which takes two separate caps because the producer fires constantly by design (every helper
that touches the spent pool 402s and calls it):

- **Within an app run** — a once-per-run latch in `pooled-ai-limit-notice.ts`. Without it each 402
  coalesced into the live row, and because `bumpDedupCount` touches `updated_at` while the inbox
  lists `ORDER BY updated_at DESC`, the same card re-floated to the top all day.
- **Across restarts and dismissals** — a 30-day floor on `pooled-ai-monthly-limit` in the
  [central alert cadence registry](../../src/shared/alert-reraise-throttle.ts). On the generic 24h
  default a dismissed card came back the next day, every day, for the rest of the month.

Past 30 days it re-raises normally: a monthly cap must not become permanent silence, because the
pool resets and the user is entitled to hear about the new month's.

### Adding your OpenRouter key (free plan)

Create a key at [openrouter.ai/keys](https://openrouter.ai/keys), then paste it into **Settings →
Accounts & Providers → API Keys → "Your OpenRouter key"**. It's stored encrypted like every other
credential (never synced in plaintext, never sent to the renderer or a CLI export). Once saved, the
built-in helpers run on your OpenRouter account — Omniscio maps each helper's model to its OpenRouter
equivalent automatically, so you don't pick models. Your key takes priority the moment it's set.

### The old "Route internal AI through the cloud (test)" toggle is gone

Through mid-2026 an **experimental toggle** ("Route internal AI through the cloud (test)") let you
flip the helpers between the bundled keys and your cloud account. That toggle has been **removed** —
routing is now decided by your **plan**, not a manual switch, so there's nothing to toggle. Paid
plans get the cloud automatically; free plans bring a key. (The old setting name
`routeInternalAiThroughGateway` still exists internally as an inert default and is no longer
user-facing.)

### If you haven't added an API key yet (new installs)

The **first time** a helper can't run because **no usable Anthropic API key is saved**, you get one
inbox card that says exactly that — **"Add an API key to turn on AI helpers"** — with an **Add API
key** button that opens Settings → Accounts and scrolls straight to the Anthropic key box. It does
_not_ blame a provider outage, because nothing is down: the key was simply never added. A
`claude login` account alone is not enough here — the Messages API these helpers use doesn't accept
OAuth tokens, so they need a key even when your coding sessions are signed in and running fine.

You get **one** card, not a stream: it's raised at most once per app run and coalesced under a single
dedup key, so dismissing it sticks. Everything else keeps working while it's up, and it **clears
itself** the moment the helpers succeed after you paste your key.

Before this shipped, the Messages-API helpers refused _silently_ on a keyless install — no card, no
explanation, nothing to click — and the only card you could eventually get came from an unrelated
code path and blamed a temporary outage.

### If the main AI provider has a bad stretch

The built-in helpers run on a cheap, shared AI provider. If that provider has a rough patch
(an outage, or its account running low), you might briefly see an **"AI features are using a
backup provider"** notice in your inbox. Nothing is broken — the helpers automatically shift to
a backup so titles and suggestions keep working; they may just be a little slower or, now and
then, a touch less polished. The notice **clears itself** once the main provider recovers, and
there's nothing you need to do. (And if the AI titler can't reach any provider at all, a new
session simply gets a short title made from your first message instead of a smart one.)

## For agents

- The routing decision funnels through one pure function,
  [`resolveGatewayRouting`](../../src/main/services/gateway-routing.ts) (+ its raw-fetch twin
  `resolveProviderFetchTarget`), and the `chat()` wiring in
  [`llm-provider-service.ts`](../../src/main/services/llm-provider-service.ts). Both callers pass the
  tier; a free tier makes the gateway resolve to `null` (direct path).
- **Tier source** is `getCachedAuth()?.tier` — the Firebase-verified plan claim, un-forgeable
  client-side. It is read **fail-safe to free**: any error, or a background subprocess where auth is
  unreachable, resolves to "free" (no company gateway) so a free/unidentifiable user is **never
  billed to the company pool**.
- A free-plan BYOK OpenRouter key **forces `provider='openrouter'`** and maps a pinned model
  (e.g. a Groq or bare-Anthropic id) to its OpenRouter slug via `toOpenRouterModelId`, so a helper
  that pinned a non-OpenRouter model still resolves.
- The free-no-key pause reuses the existing
  [`pooled-ai-limit-notice`](../../src/main/services/ai/pooled-ai-limit-notice.ts) inbox alert and
  throws the existing `AnthropicFallbackUnavailableError` so the helper pauses cleanly.
- **The "no key saved" card has ONE owner, reached from TWO detectors.**
  [`ai-no-api-key-notice.ts`](../../src/main/services/ai/ai-no-api-key-notice.ts) owns the
  `ai-helpers-no-api-key` dedup key, its copy, and a raised-once-per-run latch (the refusal fires on
  every keyless call, so an unlatched raiser would stamp the card "×2,431"). Its two callers:
  - `ai-suggestion-service.resolveCredentialFor` — **the immediate path.** Both
    `"This feature requires an Anthropic API key"` branches call `notifyAiHelpersNeedApiKey()`.
    This return happens _before_ the circuit breaker, so it recorded no failure, opened no circuit,
    and raised nothing — the silent dead end. One notify per refusal is repo-wide enforced by
    [`ai-no-api-key-refusal-notifies.test.ts`](../../tests/unit/lint/ai-no-api-key-refusal-notifies.test.ts).
  - [`ai-call-guard.ts`](../../src/main/services/ai/ai-call-guard.ts) — **the breaker path.** On a
    circuit open it probes `resolveApiKeyForAiFeatures()` and defers to the same owner when nothing
    resolves, instead of raising `ai-suggestion-service-outage`. The probe fails safe to the outage
    copy, so an unreadable config never accuses the user of skipping setup.

  Raising either variant retires the other (contradictory diagnoses never co-exist), and recovery
  clears both and re-arms the latch. The one-click **Add API key** button is a registry row in
  [`alert-actions/accounts.ts`](../../src/shared/alert-actions/accounts.ts) targeting the
  `api-key-setup` card (inbox-alert-contract I20).

- The daily digest follows the same rule — a free user's digest requires **their own** key
  (see [daily-digest-credential-contract.md](../../.claude/memory/contracts/daily-digest-credential-contract.md)).
- **A dead/dry primary provider is surfaced even behind the fallback.** Because a failed cheap
  call succeeds via the Anthropic fallback, a sustained primary-provider outage is otherwise
  invisible; a per-provider health signal in `llm-provider-service.ts` counts cheap failures
  BEFORE the fallback and, after 5 in a row that ALSO persist for ~3 min (a brief burst that
  self-heals inside the window is suppressed — no card flash), raises the self-clearing,
  confidentiality-safe "backup provider" notice (`ai-provider-degraded:<provider>`) + an operator
  `ai_provider_degraded` metric log. For a keyless PAID user, session titles also get a company-gateway Haiku backstop
  when the cheap provider is down — its breaker open, or the cheap call hit a definitive
  non-timeout failure (title-gen-recovery I5/I6; the gateway-routing
  "unmask" §).
- Full invariants (I1–I9), including the plan gate and BYOK precedence:
  [internal-ai-gateway-routing-contract.md](../../.claude/memory/contracts/internal-ai-gateway-routing-contract.md).

> This is **distinct** from the spawn-session **company-credit** path (the Omniscio credits row of a
> model family's supply list, the user-prepaid `/v1` lane) — a different billing model, where the
> order of that family's list decides whether your key or your credits pay first.

## Related

What each plan includes, and how to change it, is on the [plan and billing](plan-billing.md) page.
The coding accounts these background helpers are separate from are on the [API keys](api-keys.md)
page, and the daily digest — one of the helpers named here — has its own credential and source
rules on the [Daily Digest](daily-digest.md) page.
