Priya Raghunathan
Why was I charged $70.97 on 12 March?
Design system
Nineteen sections, ten primitives and eighteen colours, each rendered here from the same file the theme ships.
Tokens
Swatches read live from src/theme.css, so this page recolours with the theme.
--font-text · Public Sans · self-hosted, OFL 1.1
Relay closes routine billing tickets
--font-mono · JetBrains Mono · self-hosted, OFL 1.1
stripe.subscriptions.retrieve · sub_1P7dK2 · 212 ms · +17m04s · $70.97
rounded-themed · --radius 0.625rem
rounded-md · the nested step down, 6px
Hairlines never carry structure alone. Every bordered surface also changes background by at least 1.14:1, which is why the border token is tuned for calm rather than contrast.
The eighteenth colour is --shadow-color. Relay is flat material and ships no shadows, so the token is declared and never spent.
Primitives
Sections never import each other, so anything shared lives in components/ui.
src/components/ui/*.tsx
ui/button
ui/badge
ui/section-heading
The boundary
Written down before you switch it on, and enforced in code.
ui/tool-call
Billing policy §3 · match 0.91
ui/chat-turn · three roles, one streaming
Why was I charged $70.97 on 12 March?
That charge is the mid-cycle switch to Studio, and
Drafting a reply
Refund approved and the plan moves back on 1 April.
ui/mode-toggle · one of the theme’s two client islands
ui/wire-figure renders the two .wire.json graphs in the agent-flow and scope-ledger frames below; ui/logo, ui/container and ui/page-hero render there too
Sections
Each renders with the content it ships with, and nothing here is a placeholder.
src/components/agent-hero.tsx
Billing queue
Proration, invoice copies and card declines, answered from live Stripe data with the policy section cited.
Zendesk ZD-4821
There is a $70.97 charge on my card from 12 March. I pay $39 a month. What is this?
sub_1P7dK2 · Studio · $149.00/mo
The $70.97 is the mid-cycle switch to Studio on 12 March: $96.13 for the twenty days left, less
Drafting a reply
src/components/outcome-band.tsx
65%
Of billing tickets closed without a human
Our billing queue went from 340 tickets a week to 118 reaching a person.
The same ticket runs through the transcript, the log and the flow diagram on the product page.
src/components/how-it-works.tsx
How it runs
Three steps, and the third is the one your team cares about.
Relay opens the Stripe subscription, the invoice lines and your accounts table before it writes a word. No answer is composed from the ticket text alone.
Every reply names the help-center section it came from. If no section matches above 0.8 confidence, Relay does not send.
Refunds over $50, cancellations and disputes go to a named person with the four facts already gathered and a reply drafted.
src/components/boundary-grid.tsx
The boundary
Written down before you switch it on, and enforced in code rather than in a prompt.
Answered from your data, sent without waiting for anyone.
Every time, with the research attached and a reply drafted.
src/components/integrations.tsx
Connected systems
Read access where it needs it, write access in five places, all listed.
Subscriptions, invoices, charges. Writes credits up to $50 and payment retries.
A read replica of your accounts and entitlements tables. Relay never holds a write credential.
Reads the ticket thread, posts the reply or leaves it as a draft for review.
Per-inbox. Relay can be switched on for billing and left off for everything else.
Reads the conversation, replies in-app, and keeps the assignment when it escalates.
Posts every handoff into the channel that owns the account, with the facts inline.
src/components/conversation-thread.tsx
One ticket
The same ticket the hero opens, played out to the handoff that closes it.
Zendesk ZD-4821 · Coilbook
There is a $70.97 charge on my card from 12 March. I pay $39 a month. What is this?
sub_1P7dK2 · Studio · $149.00/mo
$96.13 Studio, less $25.16 unused Solo
That charge is the switch to Studio on 12 March. Stripe bills the new plan for the twenty days left in the period and credits the same twenty days you had already paid on Solo, so the invoice is $96.13 minus $25.16.
From 1 April it settles at $149.00 a month on the normal date. Your $39 payments were the old plan and have stopped.
That makes sense, thank you. Can I have the $70.97 back and go to Solo? We are not using the extra seats.
blocked · above the $50 ceiling
A refund of this size needs a person. I have passed the thread to Dana Okonjo with the invoice, the plan history and a reply drafted, and told Priya someone will answer today.
Refund approved and the plan moves back to Solo on 1 April. Priya sees $70.97 returned within five working days.
src/components/tool-timeline.tsx
The run log
What Relay touched, in what order, and what came back, with nothing hidden behind a spinner.
src/components/agent-flow.tsx
The decision
One check decides whether a billing ticket ends with Relay or with a person.
trigger
Ticket arrives
A billing question lands in the queue with the customer's account id attached.
lookup
Read the account
Four reads before a word is drafted: Stripe, the accounts replica, the help center, and the ticket's own thread.
check
Does it clear policy?
Two tests in the tool layer, run before every send: the help center match scores 0.8 or better, and no money moves past $50.
clears · 65%
step
Relay answers
ZD-4821 cleared here at +1.44s. The reply cites the policy section it came from, and a credit up to $50 can go with it.
step
Ticket closes
The run keeps every call, input and rule that allowed it for 13 months.
trigger
The customer asks again
ZD-4821 came back at 09:31 wanting the charge refunded, so the same loop ran a second time and met the same check.
returns to Read the account
blocks · 35%
handoff
A person takes it
The second check stopped ZD-4821: a $70.97 refund against a $50 ceiling.
handoff
Dana gets the brief
Four facts and a drafted reply: the account, the charge, the payment history, and the rule that stopped it.
Ticket arrives
trigger · starts the run
A billing question lands in the queue with the customer's account id attached.
Read the account
lookup · after Ticket arrives · also after The customer asks again
Four reads before a word is drafted: Stripe, the accounts replica, the help center, and the ticket's own thread.
Does it clear policy?
check · after Read the account
Two tests in the tool layer, run before every send: the help center match scores 0.8 or better, and no money moves past $50.
Relay answers
step · after Does it clear policy? · branch clears (65%)
ZD-4821 cleared here at +1.44s. The reply cites the policy section it came from, and a credit up to $50 can go with it.
Ticket closes
step · after Relay answers
The run keeps every call, input and rule that allowed it for 13 months.
The customer asks again
trigger · after Ticket closes
ZD-4821 came back at 09:31 wanting the charge refunded, so the same loop ran a second time and met the same check.
A person takes it
handoff · after Does it clear policy? · branch blocks (35%)
The second check stopped ZD-4821: a $70.97 refund against a $50 ceiling.
Dana gets the brief
handoff · after A person takes it
Four facts and a drafted reply: the account, the charge, the payment history, and the rule that stopped it.
src/components/handoff-panel.tsx
The handoff
The account, the charge, the rule that stopped it, and a reply ready to send.
Handed to Dana Okonjo
billing on-call · 09:31Hi Priya, I have approved the $70.97 back to your card and moved you to Solo from 1 April. The refund lands within five working days.
Stopped by refund.ceiling, not by a hunch.
src/components/guardrails.tsx
Guardrails
Your security review will ask these four questions, so here are the answers first.
The ceiling is a number in your config, checked in the tool layer before the call is made. A prompt cannot argue with it.
Below 0.8 match against your help center, Relay drafts and escalates instead of sending. The threshold is yours to move.
Account data comes from a read replica. There is no path from Relay to a row in your primary database.
Each call is logged with the ticket, the inputs and the rule that allowed it, kept 13 months and exportable as CSV.
src/components/scope-ledger.tsx
Access
Three of these eight scopes can write, and only one of the three moves money.
trigger
Eight scopes are held
Six systems, one credential each: a restricted Stripe key, a read-only replica role, an OAuth app per inbox, and one Slack bot token.
check
Can the scope write?
The credential decides, not the prompt. A read-only role cannot be talked into a write.
reads · 5 of 8
lookup
Five only read
Stripe subscriptions and invoices, the accounts replica, the help center and the ticket thread. Nothing they touch changes.
writes · 3 of 8
step
Three can write
One reply per ticket, one handoff message, and account credits. Every write is scoped to a single object.
check
Does the write move money?
Two of the three writes only post text. The third is the only path from Relay to your balance.
words · 2 of 3
step
Two post text
helpdesk.replies.write posts one reply on one ticket. slack.handoff.write posts into the one channel that owns the account.
money · 1 of 3
limit
One moves money, capped at $50
stripe.credits.write is checked against the ceiling in the tool layer, before the call is made.
handoff
The refund goes to a person
ZD-4821 asked for $70.97 against the $50 cap, so the scope was never used and Dana Okonjo answered instead.
Eight scopes are held
trigger · starts the run
Six systems, one credential each: a restricted Stripe key, a read-only replica role, an OAuth app per inbox, and one Slack bot token.
Can the scope write?
check · after Eight scopes are held
The credential decides, not the prompt. A read-only role cannot be talked into a write.
Five only read
lookup · after Can the scope write? · branch reads (5 of 8)
Stripe subscriptions and invoices, the accounts replica, the help center and the ticket thread. Nothing they touch changes.
Three can write
step · after Can the scope write? · branch writes (3 of 8)
One reply per ticket, one handoff message, and account credits. Every write is scoped to a single object.
Does the write move money?
check · after Three can write
Two of the three writes only post text. The third is the only path from Relay to your balance.
Two post text
step · after Does the write move money? · branch words (2 of 3)
helpdesk.replies.write posts one reply on one ticket. slack.handoff.write posts into the one channel that owns the account.
One moves money, capped at $50
limit · after Does the write move money? · branch money (1 of 3)
stripe.credits.write is checked against the ceiling in the tool layer, before the call is made.
The refund goes to a person
handoff · after One moves money, capped at $50
ZD-4821 asked for $70.97 against the $50 cap, so the scope was never used and Dana Okonjo answered instead.
stripe.subscriptions.read
Stripe
Restricted API key
Plan, period and the proration lines behind a charge
stripe.invoices.read
Stripe
Restricted API key
Invoices, charges and receipts
stripe.credits.write
Stripe
Restricted API key
Account credits capped at $50, the only scope that moves money
postgres.accounts.read
Postgres replica
Read-only replica role
Entitlements, seat counts and trial end dates
docs.search
Help center
Public URL, no key
Published articles, for the citation on every reply
helpdesk.threads.read
Zendesk · Front · Intercom
OAuth app, per inbox
The ticket thread and its history
helpdesk.replies.write
Zendesk · Front · Intercom
OAuth app, per inbox
One reply per ticket, sent or left as a draft
slack.handoff.write
Slack
Bot token, one channel
The handoff message, in the channel that owns the account
Five systems accept a write. The accounts replica is read only, and no scope reaches your primary database.
src/components/audit-record.tsx
Audit
A blocked call keeps the same fields as a sent one, so nothing is missing.
13 months
Kept on every row
Exported as CSV from the console, or read through the audit API with a scoped key.
Processed in eu-west-1. Three sub-processors: the model provider, the cloud host and the error store.
The seven other rows from this run are on the run log. Read all eight
src/components/pricing-table.tsx
Plans
A ticket Relay hands to a person still cost you that person, so it is not billed.
$290per month
500 closed tickets a month
$0.60 per ticket after that
$890per month
2,500 closed tickets a month
$0.42 per ticket after that
Customannual
Unmetered closed tickets
Priced against last quarter's volume
$0
For every ticket Relay hands to a person. Escalations are the ones that still cost you a salary, so they are not on the invoice.
src/components/price-estimator.tsx
Your volume
Move the slider to the tickets you close in a month and the plan follows the number.
Coilbook, the account in the run log, closes about 950 a month.
Cheapest plan
$560a month on Starter
$0.59 per closed ticket
Tickets Relay hands to a person are not counted, so this is the whole invoice.
src/components/support-desk.tsx
Where to write
Each one states who reads it and how long you wait, because that is the product's own claim.
Invoices, proration and anything Relay escalated to a person on your queue.
Dana Okonjo, billing on-call
Connecting Stripe and a helpdesk, moving a ceiling, tuning the 0.8 threshold.
The engineer who built your connector
Scopes, sub-processors and the DPA. Most of it is already written down.
Answered against the scope ledger
Relay sent something it should not have, or stopped sending at all.
The on-call engineer, not a queue
31 min
Median reply on billing, last quarter
Measured from the message arriving to a person answering it, not to an autoresponder. The slowest 5% took under four hours.
Scopes, retention and the sub-processor list are on the security page.
src/components/faq.tsx
Questions
The answers a support lead needs before they will let an agent near the queue.
Only account credits up to $50, and only when your config allows it. Anything above the ceiling goes to a person with the draft written. The ceiling can be set to zero on day one.
Every reply names the policy section it used, so a wrong answer is traceable to a wrong document. The weekly report lists each reply a customer pushed back on, and you can move the confidence threshold up until it stops.
About an hour. You connect Stripe read keys and one helpdesk, point Relay at your help center, and set the refund ceiling. You approve its first 50 replies before it sends on its own.
It reads the ticket, the Stripe record and a read replica of your accounts table. Nothing is used for training, and the audit log records every field it touched.
There is an HTTP integration for anything with a webhook and a reply endpoint. Zendesk, Front and Intercom are the ones we maintain directly.
Ceilings, thresholds and escalation routes are per-rule config rather than a prompt. Teams with annual contracts usually route those accounts to a person and let Relay take the monthly ones.
src/components/cta.tsx
Connect Stripe and one helpdesk, approve its first 50 replies, then let it send.
src/components/ui/page-hero.tsx
Inside a run
Ticket ZD-4821 arrived at 09:14 and closed at 09:38.