-
-
Detailed AWS infrastructure: CloudFront, API Gateway, reader/writer Lambdas, IAM, S3, logging, Bedrock, and unconnected integrations.
-
AWS overview: CloudFront serves React; API Gateway separates reads from Bedrock-backed writes; SES and external feeds remain unconnected.
-
Hestia runs in AWS eu-west-1 with CloudFront, API Gateway, separate reader and writer Lambdas, private S3 storage, and Amazon Bedrock.
-
Hestia uses a read-only review agent and a no-tools reading agent, with guarded claims and household confirmation before saving.
-
Hestia introduces a sample washing machine repair case and the path from recorded facts to a reviewed notice.
-
The Home screen offers three starting points: report a repair, add an appliance, or paste receipt or order text.
-
The decision queue shows a recorded €185 repair, an expiring trial, and a subscription price change.
-
A review form displays coffee machine purchase facts for the person to check before saving.
-
A live Strands agent briefing summarizes checked records, pending decisions, and a suggested next step.
-
The expanded seven-call tool trace shows successful repair-evidence checks and the missing facts flagged for review.
-
A review modal shows the exact Bosch repair notice, recipient details, recorded facts, and an approval action marked recorded, not sent.
-
The case file records Draft, In review, and Authorized events alongside a form for adding a case update.
-
The case file shows the persisted authorization and a form to start response tracking with a manual update.
-
The About page distinguishes active features from unconnected or disabled capabilities and provides a read-only API console.
Inspiration
A washing machine fails 22 months after purchase. The receipt is in a drawer, the repair invoice is in an email, and the seller's address is on a website. The question "can I ask the seller to review this?" never gets asked, because nobody keeps the case together.
Around it sit smaller leaks: a free trial that turns into a paid plan in three days, a backup plan that went from 9.99 to 13.99 a month, a receipt missing for a hardware store purchase.
Hestia is for the person in a household who keeps the family paperwork and may have no accountant or lawyer to ask. It matters because each of these problems is small and easy to put off, and the facts needed to act sit in different places. By the time the facts are together, the moment to decide may have passed.
The track brief asks for agents that run quietly and only ping you when there is a real decision to make. Hestia implements the decision-only surface today, with the person holding the pen; automatic triggers wait on bank and mailbox connections that are not built.
What it does
The surface is the household's own case page in the browser, at the live URL, with no account and no login. Today the household starts a review from the Home page. The intended trigger, a review after each imported statement, waits on bank and mailbox connections that are not built. What Hestia aims to replace is the folder of receipts, the spreadsheet of subscriptions and the letter the household never writes.
For Elena Georgiou, who runs Athens Apartment 4B, Hestia does five things:
- The records are hers to add. Start here on Home offers three choices: Report a repair, Add an appliance you own, or Paste a receipt or order email. An appliance carries its receipt reference, seller, purchase date, guarantee months and any product page, manual or quick start link she saved, so the Records page becomes a catalogue that can stand in for the drawer of paper manuals. Pasting is the one place a model touches intake: a Strands agent with no tools reads the pasted text, and Hestia stores its proposed records as a draft for her to correct. Only the exact changes she confirms enter the household records.
- A Strands agent on Amazon Bedrock reviews the household. It reads her recorded appliances, subscriptions, transactions, utility bills and saved case through four tools, then writes a briefing in three fixed sections: what it checked, the decisions waiting for her, and one suggested next step. It points; it does not decide eligibility.
- The notice is written by plain code, not by the model. The notice to the seller (Acropolis Appliance Store, about the Bosch Series 6 Washing Machine and the recorded EUR 185.00 repair) is prepared on the server from the recorded facts by deterministic Python. Elena reads the exact recipient, subject, amount and text, then approves it with a single-use token bound to that exact draft. A repair she reports on an appliance of her own goes through the same flow.
- The case stays whole. Reviewing the notice opens the case file, and approving it moves the case to Authorized. The approval is recorded as a simulation (
delivery_statusSIMULATED); no email is sent. The timeline then holds replies, silence, extra evidence, planning deadlines and attested outcomes, each with who recorded it, when and from which source. - Subscription and receipt decisions sit next to it. The sample free trial (Fitness Stream Pro) ends three days after each private copy opens, so the agent review names it on any day, and she can record a cancellation request. A price change (Cloud Backup Vault, 9.99 to 13.99) has a Review the subscription button that opens the Records page. A receipt is missing for EUR 85.50 at Piraeus DIY Supplies, and she can link a receipt reference. An electricity bill is above its baseline, and she can record a review request. Two overlapping music plans are flagged by the agent's subscription tool and on the Records page. None of these contacts a provider.
How the agents are limited:
- 3 reviews and 3 text readings per private copy.
- One shared daily limit of 200 reviews and readings per UTC day, kept in a conditional S3 counter. A review can make several model requests in its tool loop.
- 700 output tokens and a 20 second timeout.
- A pattern guard that withholds a briefing if it matches entitlement or deadline phrases such as "entitled to" or "statutory deadline", names a euro amount the tool outputs do not contain, runs over 3200 characters, or never mentions review.
If no model is configured, a limit is reached, the budget cannot be confirmed, or the model call fails or times out, the review runs the four tools deterministically and the page says which of these happened. The tool trace is one click away.
Reading pasted text has no deterministic equivalent, so it fails closed. A missing model, used-up readings, a spent or unconfirmed daily budget or a model failure returns an error, creates no intake draft and points the household at manual entry. An attempted reading may still retain its input hash, audit event and usage accounting; Hestia does not retain the raw pasted text.
How we built it
How Strands Agents are used
Hestia runs two agents built with the Strands Agents SDK, version 1.53.0, pinned in the Lambda bundle. Both call Claude Haiku 4.5 on Amazon Bedrock through the EU inference profile eu.anthropic.claude-haiku-4-5-20251001-v1:0 in eu-west-1, with 700 output tokens and streaming off. Code: https://github.com/upgradedev/hestia-aws/blob/main/src/hestia/agents/household_agent.py. Details: https://github.com/upgradedev/hestia-aws/blob/main/docs/strands-agents.md.
- The review agent is a
strands.Agentover aBedrockModelat temperature 0.2 with four tools. The tools are built for each private copy: plain Python functions over that copy's recorded facts, wrapped with the Strandstooldecorator, so each tool's schema comes from its signature and docstring. They arereview_repair_evidence(appliance_id),audit_subscriptions(),check_receipts_and_utilities()andread_case_timeline(). The system prompt requires all four tools, forbids entitlement claims, invented deadlines and any amount or date that no tool returned, and leaves the call order and arguments to the agent before it writes the three-section briefing. - The trace is visible. Hestia rebuilds the tool calls and their outputs from the agent's messages and reads token usage from
result.metrics.accumulated_usage. The page shows both, with the mode, the model id and the Strands version. - The reading agent is a second
strands.Agentwith no tools, at temperature 0.0. It turns pasted receipt or order text into JSON records. A server-side allow-list of record kinds and keys narrows them, and Hestia stores them as a staged draft that the household edits and confirms. Only the confirmed changes enter the household records. - Around both agents: the per-copy and daily limits, the 20 second timeout, the briefing guard and the deterministic fallback described above.
AWS and the rest of the build
- Amazon Bedrock: the writer role may invoke one Claude Haiku 4.5 inference profile and its foundation model; the reader role denies
bedrock:*. - AWS Lambda behind an Amazon API Gateway HTTP API: a reader function answers the default route, and a writer function answers an explicit list of POST routes in https://github.com/upgradedev/hestia-aws/blob/main/infra/hestia_api_stack.py. Both deny SES and object deletes. Python 3.11, with boto3 1.43.93 bundled.
- Amazon S3: one JSON document per private copy, created with
If-None-Matchand updated withIf-Match, so a lost race never overwrites a case. The daily model budget uses the same conditional writes. - Amazon CloudFront with S3 serves the React 19, TypeScript and Vite web app, with same-origin API routing and no credentials in JavaScript.
- AWS Secrets Manager holds the session signing key, which CloudFormation resolves into the functions at deploy time.
- AWS CloudFormation defines both stacks: the API and the web hosting.
- GitHub Actions: lint, a prose check over
README.md,docs/*.mdand the video narration, pytest with a coverage threshold, Lambda packaging with pinned SDKs and the rendered CloudFormation template, and Playwright journeys against the real Lambda handler behind a local HTTP server. A manually started web app release goes through GitHub OIDC and is gated on the live backend health. Production acceptance runs against the live URL. - Backend release: CI packages the Lambda zip and renders the template as an artifact.
scripts/release_backend.py, run by the owner, downloads that artifact from a successfulmainrun, checksSHA256SUMS, uploads it once, prepares a CloudFormation change set, refuses one that removes or replaces resources, executes it only with--execute, and then checks/healthzfor the released commit. - Deterministic notice:
draft_statutory_claim_letterin https://github.com/upgradedev/hestia-aws/blob/main/src/hestia/agents/tools.py writes the review request from recorded facts. It cites Directive (EU) 2019/771 as a general reference only; eligibility needs its own review. - Reused from the author's earlier projects: the CloudFront and S3 hosting template (
infra/frontend_stack.py) and the video production tooling. Everything else was written for Hestia.
Challenges we ran into
- Keeping the model from deciding money or law. The review agent writes the briefing and can read recorded amounts and warranty boundaries. The reading agent only proposes intake facts, which count only after the household confirms them, and it never proposes a repair amount. The notice, the approval and every case step are deterministic. The guard had to be strict enough to catch a sentence that promises a refund and loose enough to let "requires review" through.
- Bounding cost on a public URL with no login. Per-copy and per-day limits are enforced on the server with S3 conditional writes. An unconfirmed budget means no model call.
- A Lambda that reports its own configuration.
/healthzreports the commit,live_model, the model id and the limits. The web app release gate refuses to publish unless that health names the approved backend commit,live_modeltrue with a model id,live_sendfalse, and configured storage and sessions. - Sample data that ages. The sample trial used to end on a fixed date, so from the next day the agent review would stop naming it while Home still showed it. In this release the sample trial ends three days after each private copy opens.
- Saying what is not built, on the page where it would be expected. The About page marks each feature on or off, and names the ones that are not connected: bank feeds, mailbox and retailer sync, Guardrails and AgentCore.
Accomplishments we are proud of
- A Strands agent on the public path with a visible tool trace, a stated fallback reason and a guard, covered by https://github.com/upgradedev/hestia-aws/blob/main/tests/test_household_agent.py (tools-only mode, guard rejections and acceptances, fallback on error and timeout, the conditional daily counter, limits, health reporting).
- A model that proposes and waits for confirmation: pasted text becomes a stored staged draft that the household edits, confirms and commits. Only confirmed changes enter the household records. https://github.com/upgradedev/hestia-aws/blob/main/tests/test_registry_intake.py covers the route failing closed without a model and past its limit, a timeout keeping the reading counted, an identical paste replaying without a second call, and the appliance and repair intake behind it.
- An approval that cannot be replayed into a second record and cannot be applied to changed evidence: https://github.com/upgradedev/hestia-aws/blob/main/src/hestia/app/claims.py.
- A case lifecycle whose every entry names its actor, time and source, and whose outcomes are capped at the recorded repair amount: https://github.com/upgradedev/hestia-aws/blob/main/src/hestia/domain/cases.py.
- Reader and writer separation with IAM denies for Bedrock (reader), SES and deletes (both): https://github.com/upgradedev/hestia-aws/blob/main/infra/hestia_api_stack.py.
- CI and a backend acceptance run against the live URL ran for the deployed revision (links at the top); the acceptance suite's API cases include a live text reading.
What we learned
We believe the agent earns trust by reading and pointing, not by acting. A three-section briefing with a visible tool trace, and a deterministic notice the person can read in full, turn "the AI wrote a letter" into "I approved this letter".
We have not tested this with independent users. Briefing quality, extraction accuracy, latency and cost are unmeasured, and independent human user acceptance testing is NOT_RUN.
What's next
- Reaching households where they already look: a bank's transaction feed, a retailer's order history and an insurer's claim portal, each with explicit consent and a visible label for where a fact came from. Reading a pasted order email already works; reading the mailbox it came from does not.
- Receipt reading from a photo or a PDF through Bedrock vision, staged behind the same review-and-confirm intake as pasted text. Photo OCR is not connected today.
- A measurement of extraction quality. Today the model's proposals pass a server allow-list and the same field checks as typed records, then the household reviews them; no accuracy figure is claimed.
- Email delivery through Amazon SES only after a separate consent step, with the approval token and digest carried into the sent record. Today IAM denies SES.
Built With
- amazon-api-gateway
- amazon-bedrock
- amazon-cloudfront
- amazon-web-services
- aws-cloudformation
- aws-lambda
- aws-secrets-manager
- claude-haiku-4-5
- github-actions
- python
- react
- strands-agents
- typescript
- vite

Log in or sign up for Devpost to join the conversation.