# Genesys Cloud AI — Token Calculator

A **Calculator** — a reusable vendor-pricing master (see
[`docs/Calculator_Pattern_V1-00.md`](../../docs/Calculator_Pattern_V1-00.md))
— built on the
[Mercury Notebook Deliverable Pattern](../../docs/Mercury_Notebook_Pattern_V1-00.md).
It prices what Genesys Cloud AI **costs to run**, from the vendor's own
published rate card. Unlike a TEI study it computes no benefits and no NPV:
its "numbers" are a run-rate, a per-feature breakdown, and a range.

The Mercury stage is the screen you share with a client while you size their
AI footprint together; the consultant run-book, the verification gate, and the
machine-readable appendix live backstage and export as LLM input for a
downstream business case.

## The anchor: the vendor's published rate card

The meters are Genesys' own, transcribed verbatim into
[`genesyscalc/ratecard.py`](genesyscalc/ratecard.py):

| Source | Published | What it gives |
|---|---|---|
| [Genesys Cloud tokens model](https://help.genesys.cloud/articles/genesys-cloud-tokens-model/) | **2026-07-12** | 20 token meters, the free monthly allowance, the highest-tier rule, the Copilot exclusion |
| [Genesys Enhanced TTS pricing](https://help.genesys.cloud/articles/genesys-enhanced-tts-pricing/) | **2026-05-22** | $/million characters — **not** token-metered |

That file is **immutable**. When Genesys republishes, re-anchoring is a
deliberate act with its own protocol — see *Re-anchoring* below.

### Four published rules the obvious arithmetic gets wrong

Each is enforced in the engine, pinned by a test, and reported in the
notebook's warnings rather than silently applied:

1. **The 15-second per-call round-up.** *"Genesys rounds up each call to the
   next 15-second increment."* Applied per call and then summed — averaging
   first understates the bill. A 40-second average bills as 45 (+12.5%); a
   5-second bot greeting bills as 15 (3× its duration).
2. **The free monthly allowance.** 250 tokens named / 350 concurrent, which
   *"renew each month and do not carry over"* — so it is a real deduction, and
   an unused remainder is discarded, never banked.
3. **The highest-tier rule.** *"Genesys bases charges on the highest tier
   (price) resource…"* — so the deflection shares are a **partition**, not
   overlapping rates. An interaction is charged once, at the highest tier it
   touched. Summing tiers independently over-bills.
4. **Copilot covers Supervisor summaries.** Enabling Agent Copilot makes AI
   Summary & Insights free; billing both double-charges.

## What the client sees (the stage)

The **published rate card** as the vendor prints it, then three KPI cards
(token cost, text-to-speech, total run-rate with a $/interaction figure), the
allowance shown as the deduction it is, a per-feature cost breakdown, the
list-price → negotiated walk, text-to-speech as its own clearly separated
line, an adoption scenario range, and a tornado of what actually moves the
number.

Text-to-speech is **never** folded silently into the token subtotal: the grand
total always shows tokens and TTS as two labelled components.

You drive it from the sidebar — licence model, currency, token price and
concession, the three deflection shares, average bot seconds, and a
per-feature enable. Every change re-renders the numbers (Mercury re-runs the
cells below the widgets).

## Where the content lives: in the notebook

Two tagged cells of
[`notebooks/genesys_token_calculator.ipynb`](notebooks/genesys_token_calculator.ipynb)
carry everything a consultant edits — **in Jupyter, never in a `.py` file**:

- **`topic-bank`** — the **feature catalogue**: each priced capability's
  client-facing title, what it does for them, and the sizing question to ask.
  The `key` slugs must match published meter keys (a test pins this), and they
  are stable identities the widgets, notes and JSON export all key off.
- **`engagement-data`** — the client facts: volumes by channel, headcount,
  licence model, and the **negotiated** commercial terms (contracted rate,
  concession). **Illustrative placeholders in this master**; filled in the
  engagement copy.

The published **rates** are deliberately *not* content — nobody in this repo
authors them, and editing them is forbidden. They are the vendor's record, so
they live in the engine as an anchor. See the Calculator Pattern for the full
boundary.

`genesyscalc/` holds **code only** — the meter schema, the anchor, and the
arithmetic. The test suite reads the tagged cells straight out of the notebook
(no kernel) and pins content shape, so `pytest` guards the catalogue exactly
as shipped.

## Layout

```
notebooks/genesys_token_calculator.ipynb  # THE deliverable — content + data + presentation
                                          #   tagged: topic-bank · engagement-data ·
                                          #   presentation ×8 · gate · data-appendix
genesyscalc/                # the engine — code only, no content, mypy --strict
  ratecard.py               #   THE VERBATIM ANCHOR — published meters, 2026-07-12
  meters.py                 #   schema: Confidence, LicenceModel, MeterBasis, Tier, Meter, TokenPrice
  usage.py                  #   volumes → units → tokens (round-up, tier partition, Copilot rule)
  billing.py                #   tokens → dollars (ceil, allowance, price, concession)
  tts.py                    #   the NON-token line — own source, own rounding, EOS/EOL
  model.py                  #   orchestration: CalculatorInputs → CalculatorResult
  sensitivity.py            #   sweeps + tornado data (no plotting)
  appendix.py               #   the machine-readable JSON payload
  staging.py                #   stage/backstage detection (+ backstage_md)
scripts/export_report.py    # execute once → exports/*.html + LLM-ready *.md
tests/                      # rate-card tripwire, hand-checked arithmetic, content pins, staging
exports/                    # generated report sources (never committed)
```

## Run

```bash
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

mercury --working-dir .                # serve the stage (share this screen)
jupyter lab                            # analyst view
pytest                                 # rate card + engine + content + staging pins
mypy                                   # strict
jupyter nbconvert --to notebook --execute --inplace notebooks/genesys_token_calculator.ipynb
python scripts/export_report.py        # exports/*.html + *.md for the LLM handoff
```

The `.md` export opens with a generated preamble (what the document is, the
engagement line, **which rate card produced the numbers**) and ends with the
**Model state (JSON)** block — the machine source of truth, carrying
`rate_card.source_date`. A cost figure without its rate-card date is not
auditable.

## Re-anchoring — when Genesys republishes

The rate card is a *living* anchor: immutable until the vendor changes it,
then updated deliberately. Never partially re-anchor, and never bump the date
without the pins.

1. Diff the published table against `genesyscalc/ratecard.py`.
2. Update the meters **and** `RATE_CARD_SOURCE_DATE` in the same edit.
3. Update the pins in `tests/test_rate_card.py` in the same commit.
4. Re-execute the notebook; update the gate's live-state pins if the defaults moved.
5. Report the cost moves honestly.
6. **Show-first** — the user sees the rate diff and the KPI move before it lands.

`tests/test_rate_card.py` is the tripwire: it pins all 20 rows by exact
feature wording *and* exact rate string, so a silent transcription drift or an
un-noticed republication breaks the build rather than quietly moving a
client-facing number.

## Extending

New or reshaped catalogue content is an edit to the notebook's `topic-bank`
cell in JupyterLab, then re-run the notebook (the **gate** recounts the
catalogue and checks every key against the published meters) and re-pin
`tests/test_catalogue.py`. New *logic* goes in `genesyscalc/` with pins in
`tests/`, **before** the notebook section that renders it.

## Non-goals

- **Not a business case.** No benefits, no NPV, no payback, no ROI, no P&L. If
  a client needs those, that is a **Study** — see [`studies/`](../../studies/).
  A calculator that grows a benefit model has stopped being a calculator.
- **Not contractual pricing.** A planning model at list rates unless a
  contracted rate is entered. Genesys quotes; this estimates.
- **Not a platform TCO.** Genesys Cloud CX seat licensing is out of scope —
  this prices the **AI** meters and Enhanced TTS only.

**Running this for a client?** Don't fill client data into this master —
copy the directory out of Palladium, stamp it
`YYYYMM_Client_Genesys_Token_Calculator`, provision a fresh venv there, fill
the `engagement-data` cell in the copy, and treat the copy as confidential
(CLAUDE.md § Confidentiality). A test in this master fails if a client name
lands in `engagement-data` here.
