359 lines
11 KiB
Python
359 lines
11 KiB
Python
"""THE VERBATIM ANCHOR — Genesys Cloud tokens model, as published.
|
|
|
|
Transcribed from
|
|
https://help.genesys.cloud/articles/genesys-cloud-tokens-model/
|
|
**last updated 2026-07-12**. Feature names and rate strings below are the
|
|
article's own wording, character for character.
|
|
|
|
VERBATIM — DO NOT EDIT. A vendor republication is a deliberate
|
|
**re-anchoring**, not a patch (docs/Calculator_Pattern_V1-00.md):
|
|
|
|
1. diff the published table against this file
|
|
2. update the meters AND bump 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
|
|
5. report the cost moves honestly
|
|
6. Show-first — the user sees the rate diff before it lands
|
|
|
|
Never partially re-anchor; never bump the date without the pins.
|
|
|
|
Negotiated or contracted values NEVER land here. They are the overlay, and
|
|
they live in the notebook's ``engagement-data`` cell — this file is the
|
|
vendor's record, not the client's deal.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .meters import LicenceModel, Meter, MeterBasis, Tier
|
|
|
|
RATE_CARD_SOURCE: str = "https://help.genesys.cloud/articles/genesys-cloud-tokens-model/"
|
|
RATE_CARD_SOURCE_DATE: str = "2026-07-12"
|
|
|
|
# Every meter below is published on the same page on the same date, so the
|
|
# source pair is spelled out once here and passed explicitly. Explicit beats
|
|
# a splat: this file is diffed against the article by eye.
|
|
_URL = RATE_CARD_SOURCE
|
|
_DATE = RATE_CARD_SOURCE_DATE
|
|
|
|
|
|
#: The published meter table, verbatim. Twenty rows, in the article's order.
|
|
METERS_VERBATIM: tuple[Meter, ...] = (
|
|
Meter(
|
|
key="bots_voice",
|
|
feature="Bots (Voice)",
|
|
published_rate="17 minutes per token",
|
|
basis=MeterBasis.VOICE_MINUTES,
|
|
rate=1.0 / 17.0,
|
|
tier=Tier.BOT,
|
|
unit_label="bot minutes",
|
|
note=(
|
|
"Genesys rounds up each call to the next 15-second increment "
|
|
"(clarified 2026-07-12)."
|
|
),
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="bots_digital",
|
|
feature="Bots (Digital)",
|
|
published_rate="51 sessions per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 51.0,
|
|
tier=Tier.BOT,
|
|
unit_label="sessions",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="virtual_agent",
|
|
feature="Virtual Agent",
|
|
published_rate="0.5 tokens per Virtual Agent interaction",
|
|
basis=MeterBasis.TOKENS_PER_UNIT,
|
|
rate=0.5,
|
|
tier=Tier.VIRTUAL_AGENT,
|
|
unit_label="interactions",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="agentic_virtual_agent",
|
|
feature="Agentic Virtual Agent",
|
|
published_rate="1.2 tokens per interaction",
|
|
basis=MeterBasis.TOKENS_PER_UNIT,
|
|
rate=1.2,
|
|
tier=Tier.AGENTIC_VIRTUAL_AGENT,
|
|
unit_label="interactions",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="agent_copilot_named",
|
|
feature="Agent Copilot [named]",
|
|
published_rate="40 tokens per user",
|
|
basis=MeterBasis.PER_USER_PER_MONTH,
|
|
per_user_named=40.0,
|
|
per_user_concurrent=60.0,
|
|
unit_label="users",
|
|
note="Enabling Copilot makes Supervisor summaries and insights free.",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="agent_copilot_concurrent",
|
|
feature="Agent Copilot [concurrent]",
|
|
published_rate="60 tokens per user",
|
|
basis=MeterBasis.PER_USER_PER_MONTH,
|
|
per_user_named=40.0,
|
|
per_user_concurrent=60.0,
|
|
unit_label="users",
|
|
note="The concurrent-licence face of the same meter.",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="ai_scoring",
|
|
feature="AI Scoring",
|
|
published_rate="20 evaluations per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 20.0,
|
|
unit_label="evaluations",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="ai_translate",
|
|
feature="AI Translate",
|
|
published_rate="2 translations per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 2.0,
|
|
unit_label="translations",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="ai_summary_and_insights",
|
|
feature="AI Summary and Insights",
|
|
published_rate="50 summaries/insights per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 50.0,
|
|
unit_label="summaries",
|
|
note=(
|
|
"Free when Agent Copilot is enabled — see "
|
|
"COPILOT_COVERS_SUMMARY_RULE."
|
|
),
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="apple_messages_for_business",
|
|
feature="Apple Messages for Business",
|
|
published_rate="400 inbound or outbound messages per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="messages",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="facebook_messenger",
|
|
feature="Facebook Messenger",
|
|
published_rate="400 messages per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="messages",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="instagram_direct_messaging",
|
|
feature="Instagram Direct Messaging",
|
|
published_rate="400 messages per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="messages",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="whatsapp_messaging",
|
|
feature="WhatsApp Messaging",
|
|
published_rate="400 messages per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="messages",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="x_direct_messaging",
|
|
feature="X Direct Messaging",
|
|
published_rate="400 messages per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="messages",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="genesys_cloud_social",
|
|
feature="Genesys Cloud Social",
|
|
published_rate="400 social post ingestions per channel per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="post ingestions",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="social_post_responses",
|
|
feature="Social Post Responses",
|
|
published_rate="400 outbound messages per channel per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 400.0,
|
|
unit_label="outbound messages",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="predictive_routing",
|
|
feature="Predictive Routing",
|
|
published_rate="17 routes per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 17.0,
|
|
unit_label="routes",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="speech_and_text_analytics_named",
|
|
feature="Speech and Text Analytics [named]",
|
|
published_rate="30 tokens per user",
|
|
basis=MeterBasis.PER_USER_PER_MONTH,
|
|
per_user_named=30.0,
|
|
per_user_concurrent=45.0,
|
|
unit_label="users",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="speech_and_text_analytics_concurrent",
|
|
feature="Speech and Text Analytics [concurrent]",
|
|
published_rate="45 tokens per user",
|
|
basis=MeterBasis.PER_USER_PER_MONTH,
|
|
per_user_named=30.0,
|
|
per_user_concurrent=45.0,
|
|
unit_label="users",
|
|
note="The concurrent-licence face of the same meter.",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="genesys_cloud_copilot",
|
|
feature="Genesys Cloud Copilot",
|
|
published_rate="20 AI actions per token",
|
|
basis=MeterBasis.UNITS_PER_TOKEN,
|
|
rate=1.0 / 20.0,
|
|
unit_label="AI actions",
|
|
note="Genesys Cloud knowledge queries are not charged.",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
)
|
|
|
|
|
|
#: Published as included at no token cost. Shown on stage as explicit $0
|
|
#: lines — a zero the vendor put in writing is a finding, not an omission.
|
|
ZERO_RATED_VERBATIM: tuple[Meter, ...] = (
|
|
Meter(
|
|
key="predictive_engagement",
|
|
feature="Predictive Engagement",
|
|
published_rate="No charge for token usage",
|
|
basis=MeterBasis.ZERO_RATED,
|
|
unit_label="interactions",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
Meter(
|
|
key="knowledge_queries",
|
|
feature="Genesys Cloud knowledge queries",
|
|
published_rate="no charge for Genesys Cloud knowledge queries",
|
|
basis=MeterBasis.ZERO_RATED,
|
|
unit_label="queries",
|
|
source_url=_URL,
|
|
source_date=_DATE,
|
|
),
|
|
)
|
|
|
|
|
|
#: "Named organizations receive 250 tokens; concurrent organizations receive
|
|
#: 350 tokens" per month.
|
|
FREE_TOKENS_PER_MONTH: dict[LicenceModel, int] = {
|
|
LicenceModel.NAMED: 250,
|
|
LicenceModel.CONCURRENT: 350,
|
|
}
|
|
|
|
#: "These tokens renew each month and do not carry over to future months."
|
|
ALLOWANCE_CARRIES_OVER: bool = False
|
|
|
|
#: "Genesys rounds up each call to the next 15-second increment."
|
|
#: Clarified in the 2026-07-12 revision. Applied PER CALL, then summed.
|
|
VOICE_BOT_ROUNDUP_SECONDS: int = 15
|
|
|
|
#: The published highest-tier rule, verbatim. Renders on stage.
|
|
HIGHEST_TIER_RULE: str = (
|
|
"In cases where an interaction uses multiple AI resources, such as bot "
|
|
"flows, virtual agents, and agentic virtual agents, Genesys bases charges "
|
|
"on the highest tier (price) resource that Genesys Cloud uses during the "
|
|
"interaction."
|
|
)
|
|
|
|
#: The published Copilot exclusion, verbatim. Renders on stage.
|
|
COPILOT_COVERS_SUMMARY_RULE: str = (
|
|
"if you enable Agent Copilot simultaneously, then Supervisor Copilot "
|
|
"summaries and insights do not consume tokens"
|
|
)
|
|
|
|
#: List price per token. The article points to the pricing hub and cites
|
|
#: "USD 1.00 to JPY 120 per token by currency".
|
|
LIST_PRICE_BY_CURRENCY: dict[str, float] = {"USD": 1.00, "JPY": 120.0}
|
|
|
|
|
|
#: Every meter by key — the consumption table plus the zero-rated lines.
|
|
METERS: dict[str, Meter] = {
|
|
m.key: m for m in METERS_VERBATIM + ZERO_RATED_VERBATIM
|
|
}
|
|
|
|
|
|
def meter(key: str) -> Meter:
|
|
"""Look up a published meter, with a useful error when the key is wrong."""
|
|
try:
|
|
return METERS[key]
|
|
except KeyError:
|
|
raise KeyError(
|
|
f"{key!r} is not a published Genesys meter. Known keys: "
|
|
f"{', '.join(sorted(METERS))}"
|
|
) from None
|
|
|
|
|
|
def per_user_meter(licence: LicenceModel, family: str) -> Meter:
|
|
"""The Copilot / STA meter face matching ``licence``.
|
|
|
|
``family`` is ``"agent_copilot"`` or ``"speech_and_text_analytics"``.
|
|
Both rates live on both faces, so this is presentation sugar — it picks
|
|
the row whose published wording matches the licence being modelled.
|
|
"""
|
|
return meter(f"{family}_{licence.value}")
|
|
|
|
|
|
def rate_card_rows() -> list[dict[str, str]]:
|
|
"""The published table as display rows, in publication order."""
|
|
return [
|
|
{
|
|
"Feature": m.feature,
|
|
"Published rate": m.published_rate,
|
|
"Confidence": m.confidence.icon,
|
|
"Source": m.source_date or "",
|
|
}
|
|
for m in METERS_VERBATIM + ZERO_RATED_VERBATIM
|
|
]
|