We’re moving from per-request to per-successful-call. Finance wants it on the first of the month. How bad is this?
STORM
Loading…
One moment.
STORM
One moment.
AI billing engineer
Storm is an AI billing engineer that lives in your Slack. Ask it in a thread — it reads your codebase, writes the meter, ships the billing configuration, and reconciles the month, end to end.
We’re moving from per-request to per-successful-call. Finance wants it on the first of the month. How bad is this?
Not bad. Three places emit the meter today, and two of them count a request before the handler returns — so retries and 5xx are billing right now.
Proposed rule: one unit per response with a 2xx status and a non-empty body. Retries against the same idempotency key count once.
- meter.record({ unit: "request" })
+ if (res.ok && res.bodyLength > 0) {
+ meter.record({ unit: "call", key: req.idempotencyKey })
+ }The rest of the thread below
The problem
It is the one system where every change needs an engineer, and no engineer wants to own it. So the change ships a quarter late, and what you charge slowly stops matching what you sold.
And then pricing changes again.
How it works
Storm reads the billing system you actually run — the emit sites in your code, the prices in your billing account, the usage in your warehouse — and then does the work in the thread where you asked for it.
Add Storm to Slack, then grant it your repository, your billing account, and your warehouse. Access is scoped per surface, revocable from Slack, and every action it takes is recorded against the request that asked for it.
It learns how you bill today rather than how you meant to: the emit sites in your code, the products and prices in your billing account, the usage tables in your warehouse, and the places those three already disagree.
Ask in a thread. It comes back with the rule in plain language, the diff, the migration, and a replay showing what the last thirty days would have billed under it. You approve in the thread, and nothing ships until you do.
Shipping is the start, not the end. It stays for the month — matching what the meter counted against what the invoices charged, and bringing you what disagrees before your customer finds it.
Why Storm
Four things it is built out of. Each one exists because billing punishes a general assistant in a specific way, and each one is why the engineer gets better at your system rather than starting over every thread.
Not a chat model with billing prompts. Every action the engineer can take is scoped to a surface you granted, replayed against real history before it runs, and held until a human approves it in the thread. Storm authors the rule; deterministic code evaluates it. No model assigns a price, a tier, or a usage class at runtime.
Meters, rate cards, plans, and the dependencies between them are held as a typed representation rather than as text re-read on every question. A price change is a change to that structure — so it can be diffed, checked against the contract, and replayed, and so the engineer knows what a change touches instead of guessing.
Every change teaches it something specific and permanent about your system: where the emit sites are, which retries were never billable, how a plan migration has to be sequenced around your close. That becomes a durable skill rather than context that dies with the thread — the engineer is worth more in month six than in week one.
Supervised fine-tuning and reinforcement learning from verifiable rewards, on billing-specific datasets. Verifiable is the operative word: billing has a right answer. The meter reconciles against the invoice or it does not, so the reward is the thing you actually care about rather than a judge’s opinion of a plausible-looking diff.
Built to handle ambiguous situations sensibly.
95%on Stripe's agent benchmark for billing integration and validation
Complete coverage
Not a category of work it specialises in — the whole surface a billing engineer owns, from the meter in your code to the question a customer asks about their invoice.
A thread, start to finish
What the work looks like in practice. The rule in plain language, the diff, the replay against real history, and a human approving it — all in one place, all before anything reaches a customer’s invoice.
We’re moving from per-request to per-successful-call. Finance wants it on the first of the month. How bad is this?
Not bad. Three places emit the meter today, and two of them count a request before the handler returns — so retries and 5xx are billing right now.
Proposed rule: one unit per response with a 2xx status and a non-empty body. Retries against the same idempotency key count once.
- meter.record({ unit: "request" })
+ if (res.ok && res.bodyLength > 0) {
+ meter.record({ unit: "call", key: req.idempotencyKey })
+ }Replayed the last thirty days against the new rule. Twelve accounts move down, one moves up because it retries far less than it looked like. Full per-account delta is in the thread.
PR is open with the migration and the backfill. Want me to ship it?
Ship it.
Merged and live. I’ll reconcile the meter against the invoices nightly and bring you anything that disagrees.
Questions
The work a billing engineer does. It reads your codebase to find where usage is emitted, writes and changes the meter, configures products and prices in your billing account, runs plan migrations and backfills, answers questions about why an invoice looks the way it does, and reconciles metered usage against issued invoices every month. You ask in a Slack thread; it comes back with a plan, a diff, and a replay.
Whatever you grant, and nothing else: typically your repository, your billing account, and the warehouse tables that carry usage. Access is scoped per surface rather than granted once, revocable from Slack, and every action is recorded against the request that asked for it, so the audit trail reads as a conversation rather than a log.
No. It writes the rule; deterministic code evaluates it. A model never assigns a price, a tier, or a usage class at runtime — it proposes a change, shows you the code and what that code would have billed against real history, and waits. Nothing reaches production without a human approving it in the thread.
The meter is keyed, not counted. Billable events are derived from an idempotency key you already have rather than generated at emit time, so a retry, a redelivery, or a replay of the same work resolves to the same unit instead of a second one. Changes are rehearsed against real history before they ship, which is where a double-count shows up as a delta rather than as an invoice.
In the thread where you asked. The proposal, the reasoning, the diff, the replay, and your approval are one continuous record, and the pull request it opens is an ordinary pull request your team reviews the way it reviews any other. There is no separate console you have to check to find out why a number moved.
No. Storm does not issue legal invoices, calculate tax, collect payment, or post accounting entries. It builds and operates the meter and the pricing logic that feed the system which does — your billing provider stays the system of record for money movement, and your finance stack stays the system of record for the books.
The one you already run. Storm works against your billing provider’s own API and your own code rather than replacing either, so a Stripe shop stays a Stripe shop. The metering layer is usually custom regardless of the provider, and that custom layer is the part Storm is built to own.
Your raw usage stays where it already is. The engineer reads what it needs to answer the question in front of it and writes back through the same interfaces your team uses; there is no requirement to ship a copy of your event stream anywhere to get a meter built. What each surface may read and write is scoped when you grant it and visible on the security page.
A coding agent writes the diff and stops. Billing does not stop at the diff — the change has to be replayed against real history, migrated without double-charging anyone mid cycle, reconciled against what actually got invoiced, and defended six months later when a customer disputes a line. Storm is built for the whole of that, and it stays after the pull request merges.
You find out before your customer does, because nothing ships unapproved and every change is rehearsed against real history first. When something does land wrong, the fix is an ordinary revert of an ordinary pull request, and the reconciliation pass is what surfaces the discrepancy rather than a support ticket.
Talk to us
We would love to have a conversation — about how you meter today, what breaks when pricing changes, and where the invoice and the contract stop agreeing. Not a pitch, and not a demo.