AWS Builder Center
Billy: an AWS bill explainer that tells you how worried to be first

Billy: an AWS bill explainer that tells you how worried to be first

Paste a confusing line from your AWS bill and get a CALM, WATCH or ACT verdict in seconds, then one fix and what it costs per month. Built with Strands Agents and Amazon Bedrock, running on AWS Lambda.

Billy: an AWS bill explainer

What Your Agent Does

Everyone who has used AWS for a side project knows the feeling. An email arrives, the bill is higher than yoPaste a confusing line from your AWS bill and get a CALM, WATCH or ACT verdict in seconds, then one fix and what it costs per month. Built with Strands Agents and Amazon Bedrock, running on AWS Lambda.u expected, and the line items read like a secret code: USE1-NatGateway-Hours, USE1-DataTransfer-Out-Bytes, USE1-ElasticIP:IdleAddress. You don't know if this is a $3 mistake or a $300 one, and you don't know which page in the console to open first.
Billy is a small chat agent for exactly that moment. You paste the scary line from your bill, or an AWS error message, and Billy answers in plain English.
Every reply has the same three parts, always in the same order:
  1. A verdict first. CALM (nothing to fix), WATCH (worth a look this week) or ACT (fix today, money is leaking), shown as a three-step meter with one short sentence.
  2. What it is, and one fix. One or two sentences on what the charge really is, then a single fix with the exact console path or CLI command. One fix, never a list of ten.
  3. The money line. "Per month: $33.48 now, $0 after the fix", with numbers that come from a tool, not from the model guessing.
A small panel on the side adds up what you could save across the conversation, per month and per year.
Billy is for students, indie developers and anyone running a small AWS account without a FinOps team. Those are the people most likely to leave a NAT gateway running for a month, and the least likely to know what that line on the bill means.

How You Built It

Billy runs entirely on AWS and has three parts.
The agent: Strands Agents SDK + Amazon Bedrock. The agent is written in Python with the open source Strands Agents SDK. The model is DeepSeek V3.2 on Amazon Bedrock, called through the Bedrock Converse API that Strands uses under the hood.
Four tools the agent can call:
  • pick_verdict: decides CALM, WATCH or ACT from plain rules. ACT is $10 or more wasted per month, or a security risk. WATCH is any smaller waste, or an error that blocks your work. CALM is everything else. The model passes in the numbers, and the code makes the call, so the same bill line always gets the same verdict.
  • hourly_to_monthly: turns an hourly price into a monthly and yearly cost. In an early test the model did this math in its head and got two m5.large instances wrong, so now every hourly price must go through this tool.
  • ec2_on_demand_price: calls the AWS Price List API (pricing:GetProducts) live, to get the real on-demand price for any EC2 instance type and region.
  • known_bill_surprises: a hand-written list of the charges that catch people out most often (NAT gateways, idle public IPv4 addresses, old EBS snapshots and volumes, data transfer, CloudWatch Logs ingestion, idle load balancers, KMS keys, Secrets Manager), each with a plain-English explanation and one fix.
Hosting: AWS Lambda + Function URL. One Python AWS Lambda function does everything. GET / serves the chat page, and POST /chat runs the agent. A Lambda Function URL gives it a public HTTPS link without API Gateway. The whole stack is one AWS SAM template, deployed with sam deploy.
Memory: Amazon S3. Strands has a built-in S3SessionManager. Each browser gets a random session ID, and the conversation is saved in a private Amazon S3 bucket. If you come back and say "ok I deleted it, what about this other line?", Billy remembers what you already fixed. A lifecycle rule deletes sessions after 30 days, because nobody wants their bill history kept forever.
The page is a single HTML file with no build step. It reads the agent's reply and turns the VERDICT: line into the meter and the Per month: line into the big before-and-after numbers.
Key decisions and challenges:
  • Picking the model. I started with Amazon Nova 2 Lite because it is fast. When I tested it on real bill lines, it often skipped the verdict tool and picked the level on its own, so the verdicts were right only 2 out of 5 times on the tricky cases. Amazon Nova Pro did the same. DeepSeek V3.2 called the tool 5 out of 5 times. It is about two seconds slower per reply, but a wrong verdict defeats the whole point of Billy, so I switched. Bedrock made this a one-line change: the model ID is a SAM parameter.
  • One fix, not ten. Early answers were long lists of "you could also…". For a stressed person that is worse than nothing, so the prompt allows exactly one fix with at most three steps.
  • Usage types are not resource names. The model once told me to "find the NAT gateway named USE1-NatGateway". That label is a usage type, not a name, so I added a rule for it.
  • AWS errors count too. At first Billy turned away AccessDeniedException as "not about billing". Errors are just as stressful as bills, so they are now in scope.
  • Friendly failures. Every error path returns a human sentence ("I tripped over something on my side. Your message is safe, try sending it again.") and a Try again button, never a stack trace.

The Experience

The one thing I did to make Billy enjoyable is put the verdict first.
When you look at a bill you didn't expect, the first question in your head is not "what is a NAT gateway?". It is "how bad is this?". Most tools, and most chatbots, make you read three paragraphs before you find out. Billy answers that question with its first word, as a CALM / WATCH / ACT meter at the top of every reply, and only then explains.
The money line finishes the job. "$33.48 now → $0 after the fix" turns a scary unknown into a small task with a clear end.
A few smaller touches support it:
  • The first screen shows three real bill lines you can click, so you see a full answer before you have typed anything.
  • While Billy thinks, the little meter lights up CALM, WATCH, ACT in turn, instead of a generic spinner.
  • A note on the side reminds you never to paste access keys. A bill line is all Billy needs.
How I know it worked: I wrote a small test script (tests/eval.py) that sends 12 real-looking bill lines and errors to the live agent and checks every reply:
CheckResult
Reply starts with a verdict12 / 12 (the off-topic weather question correctly gets no verdict)
Reply ends with a "Per month" line12 / 12
Reply is under 150 words12 / 12
Verdict level matches what I expected10 / 12
Median reply time5.1 seconds
The two misses were an idle Elastic IP ($3.72 a month), which got ACT where I expected WATCH, and an AccessDeniedException, which got CALM where I expected WATCH. Both are on the "less scary" side of the scale, so they are not great, but they don't cause panic either. Before the pick_verdict tool, the same test got only 8 / 12 levels right and AWS errors were turned away completely, so moving the decision out of the model and into code made the biggest difference.

Proof It Works

Try pasting one of these:
  • USE1-NatGateway-Hours 744 Hrs $33.48
  • USE1-ElasticIP:IdleAddress 744 Hrs $3.72
  • I have 2 m5.large running in us-east-1 for a demo I finished last month
  • AccessDeniedException: You don't have access to the model with the specified model ID.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article