# 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.