What it does
A small equipment-rental shop chases every overdue item by hand: a text or email asking "when will you bring it back?", then a ledger update. This project runs that conversation end to end on AWS Communication Developer Services (Amazon SES and End User Messaging SMS): open the overdue item, send through an outbound gate (PASS, HOLD, BLOCK or APPROVAL, shown before every send, human or agent), read the reply into quantity and date, check it against the ledger, then post it and close, or hand it to a person with a reason. Delivery, bounce and opt-out events change the next decision.
What is different: an AI agent's proposal cannot get around the gate either (one dispatch point, test test_g11_no_path_to_sender_except_gate), and the customer's answer is checked against the ledger before anything is posted. The customer scene is a market where two-way SMS is supported (United States, Canada, United Kingdom, Australia in the End User Messaging country table); in South Korea two-way SMS is not supported, so there the conversation runs on email only.
What is real and what is simulated
- SES sends through the gate: 4 first sends and 2 retried sends that passed, with DELIVERY, BOUNCE and OPT_OUT events read back. Real, us-east-1 sandbox, mailbox simulator and owner inbox only.
- End User Messaging SMS: 3 sends PASS from a simulator origination number (traffic stays inside AWS, no phone receives it); delivery read back from CloudWatch AWS/SMSVoice, the failure number not delivered (BOUNCE, retry BLOCK with 0 SMS calls), the account opt-out list read back (OPT_OUT, retry BLOCK with 0 SMS calls).
- Amazon Bedrock reply assist (Converse, Nova Micro), called only when the regex reader's confidence is below 0.8: 6 Converse calls succeeded on 2026-10-27 in two runs of 3 (about $0.00007 in all). After the weekday check, two dates that did not match their weekday were refused and went to a person; the third stayed unread and nothing was guessed.
- Lambda events_handler deployed without CloudFormation and invoked 3 times with documented event shapes; CloudFormation CreateStack and SNS CreateTopic were refused by IAM (logged).
- The customer reply travelled by the owner's Gmail, not SES receiving (no owned domain). The AI agent is scripted and goes through the same gate. Screens use synthetic data.
- Closure rate 8 of 14 synthetic reply variants measures the gate and hand-off rules, not language understanding (regex reader).
Value
N x c x m / 60 x w - N x s x p with its lower bound shown; base case 23,578 KRW (about $17) per month for 40 overdue items at the Korean minimum wage, or $16.56 at the US federal minimum wage; the low case is below zero by the send cost only ($0.008 for 40 threads). A partner sells it per shop: install with sam deploy into the shop's own AWS account, the shop pays $0.25 per closed thread and nothing for a thread handed to a person. Details in docs/ROI.md and docs/OFFERING.md.
How it differs from what exists
Compared on public pages read 2026-10-26: AWS sample campaign orchestrator, SES Mail Manager attachment pipeline, RCS agent setup, Booqable, EZRentOut, Chaser, and the built-in SES suppression list and SMS opt-out list. Only here: every send, including one an AI agent proposes or a model drafts, shows its gate verdict before it leaves, and SES/SMS events and the customer's reply change the next decision instead of a fixed reminder schedule.
How it is built
Python 3.9+, standard library for the domain, boto3 adapters. Four layers (domain, application, adapters, infrastructure) with a no-reverse-import test. 143 tests pass. IaC in template.yaml (cfn-lint pass), agent-readable deployment guide in AGENTS.md, reproduction IAM table in the README.
Not done yet
Two-way SMS replies from End User Messaging into SNS (not built), SES receiving on a verified domain, events pushed by SNS into the Lambda (SNS denied), a CloudFormation deploy (CreateStack denied), SMS to a real phone, a stored ledger, an AgentCore agent.
Code and license (MIT): https://github.com/Ryugi62/cds-rental-recovery
Built With
- amazon-bedrock
- amazon-cloudwatch
- amazon-ses
- aws-end-user-messaging
- aws-lambda
- aws-sam
- boto3
- pytest
- python