How the review ask gets written
By the time this step runs, the system has decided to ask, when to ask, and that this customer looks happy. All that’s left is to say it like the business would. This post is about the place a model is allowed to write: the single Bedrock call that turns a few known facts into one warm, on-brand ask with a direct review link — and the fences that keep it to one honest message.
Key takeaways
- Once the gate has read a customer as happy, one Bedrock Haiku 4.5 call writes a single warm ask in the business’s voice.
- The model is handed only the facts it may use: the customer’s first name, the business name, the job, and a review-link token.
- The review link is injected by code after the model writes, never typed by the model, so it can never be mangled or invented.
- The draft is checked for length, a single link, and an opt-out hint before it’s sent — a bad draft falls back to a fixed template.
- The model decides wording only. Whether to send, when, and that this customer is happy were all settled upstream.
All that’s left is to say it
By the time this step runs, every real decision has already been made. Part 2 proved the job was real and eligible, Part 3 waited for the right moment and re-checked opt-out and quiet hours, and the sentiment gate in Part 5 has read this customer as happy. The request already carries the customer’s first name, the job they had done, the channel to reach them on, and the review link that suits them. Nothing about whether, when, or who is open any more. The only thing left is the wording — and wording is what decides whether a review ask gets a tap or a shrug, because a message that reads like a mail-merge is one a happy customer still ignores.
So this is one of only two places a model runs in the whole system, and the only one that writes customer-facing words. One Bedrock call, using Claude Haiku 4.5, takes a few facts and writes one short, warm ask that sounds like the business wrote it. Haiku is the right tool precisely because the task is small: a sentence or two, in a set tone, with no reasoning to do. It’s fast and it costs a fraction of a penny, which matters when it runs on every happy customer.
Handed only the facts it may use
The prompt is deliberately narrow. The model is given the business name and voice notes from the settings doc (“warm, first-person, grateful without grovelling”), the customer’s first name, the job in a few plain words (“full valet”, “course of physio”, “annual boiler service”), and a placeholder where the review link will go. It is told, in plain terms, to write one message under a sensible length that thanks the customer, references the job lightly, and invites a review — and to use only those facts. It has no tools, no web access, and no knowledge of the customer beyond what it was handed, so there is nothing for it to over-share or invent about someone’s appointment.
The review link itself is never written by the model. The model emits a token like {{review}}, and the code substitutes the real URL afterwards. This is a small thing that matters a lot: language models are perfectly capable of subtly mistyping a URL or “tidying” it into something that 404s, and a broken review link is the one error that quietly wastes the whole ask — the customer’s goodwill was there, and it hit a dead page. By keeping the link out of the model’s hands and injecting it deterministically, the link is always exactly right, and the same mechanism means the unhappy branch in Part 5 can inject the private feedback link into the same slot without the model ever knowing which road it’s on.
Checked before it goes
A model writing a one-off ask is low-risk, but “low” is not “none”, so the draft is validated by code before it leaves the building. If the ask goes by SMS it must come in under a sensible length or it’s trimmed or rejected; by email it still needs to stay short and skimmable. It must contain exactly one link, the one we injected, and no others. It must carry the small opt-out hint that keeps the business on the right side of messaging rules (“reply STOP to opt out”, or an unsubscribe footer on email). And it must not contain anything that reads as a discount, a bribe for a good review, or a promise — because paying or pressuring for reviews breaks every platform’s rules and the whole point is an honest ask.
If the draft fails any of those checks — or if Bedrock is slow or errors — the composer doesn’t retry forever or send something half-formed. It falls back to a fixed, hand-written template: “Hi {name}, thanks for choosing {business} for your {job}. If you’ve a moment, a quick review really helps us: {link}. Reply STOP to opt out.” The fallback is plain, but it’s always correct, always on time, and always within the rules. The model makes the common case sound human; the template guarantees the system never goes silent, or worse says something odd, just because a model had a bad moment.
Why let a model near it at all
It’s fair to ask why this needs a model when a template already exists as the fallback. The honest answer is tone and fit. A loyal regular who’s had ten valets reads differently from a first-timer; “annual boiler service” wants different warmth from “emergency call-out at 11pm”; a physio clinic and a car valeter want very different voices. A single template can’t flex to all of that without becoming a pile of if statements, and a stiff, obviously-templated ask is exactly what makes a happy customer decide it’s not worth two minutes. One cheap Haiku call gives every ask a little of the business’s actual character, while the deterministic link injection, the validation, and the template fallback make sure that character never comes at the cost of correctness. The model gets the warmth; the code keeps the guarantees.
Design rules that shaped the composer
- One call, one ask. A single Haiku call writes one message — no chains, no retries that could fan out into more sends.
- Only the facts it’s handed. First name, business, voice, job, and a link token — no tools, no lookups, nothing to over-share.
- The link is the code’s job. The model emits a token; the real URL is injected afterwards, so review and feedback links can never be mangled or swapped.
- Validate every draft. Length, a single link, an opt-out hint, no bribes or promises — checked before it’s sent.
- A template is always ready. If the model fails or drifts, a fixed, correct ask goes out instead — the system never goes quiet.
- The model decides nothing. Whether, when, to whom, and which link were all settled upstream; the model only chooses words.