Files

8.8 KiB
Raw Permalink Blame History

Genesys Cloud AI — Token Calculator

A Calculator — a reusable vendor-pricing master (see docs/Calculator_Pattern_V1-00.md) — built on the Mercury Notebook Deliverable Pattern. 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:

Source Published What it gives
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 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 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

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