How a text-back gets composed
By the time this step runs, the system knows it should reply, and to whom. All that’s left is to say it like the business would. This post is about the only place a model is allowed near the system: the single Bedrock call that turns a few known facts into one warm, on-brand SMS with a booking link — and the fences that keep it to one honest message.
Key takeaways
- One Bedrock Haiku 4.5 call per missed call writes a single short SMS in the business’s voice — the only place a model runs.
- The model is handed only the facts it may use: the caller’s first name if known, the business name, and the booking link.
- The booking 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, to whom, and which link to use were all settled in Part 2.
All that’s left is to say it
By the time this step runs, every real decision has already been made. The catch function in Part 2 proved the call was real and new, cleared it against quiet hours and the opt-out list, and matched the caller. The job on the queue already carries the caller’s number, their first name if we know it, and the booking link that suits them. Nothing about whether to text, or whom to text, is open any more. The only thing left is the wording — and wording is the one thing a small business actually cares about, because a text that sounds like a robot is worse than no text at all.
So this is the single place in the whole system where a model runs. One Bedrock call, using Claude Haiku 4.5, takes a few facts and writes one short, warm SMS that sounds like the business wrote it. Haiku is the right tool here 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 missed call.
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 (“friendly, first-person plural, no exclamation-mark soup”), the caller’s first name if the match found one, and a placeholder where the booking link will go. It is told, in plain terms, to write one SMS under 320 characters that apologises for the missed call, invites a reply, and points to the booking link — and to use only those facts. It has no tools, no web access, and no knowledge of the customer beyond the first name it was handed, so there is nothing for it to over-share or invent.
The booking link itself is never written by the model. The model emits a token like {{booking}}, 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 “improving” it, and a broken booking link is the one error that quietly wastes the whole text. By keeping the link out of the model’s hands and injecting it deterministically, the link is always exactly right.
Checked before it goes
A model writing a one-off SMS is low-risk, but “low” is not “none”, so the draft is validated by code before it leaves the building. An SMS is billed and split by length, so the text must come in under a single sensible limit — 320 characters — or it’s trimmed or rejected. 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”), and it must not contain anything that reads as a price, a promise, or a confirmed booking, because the system is opening a conversation, not closing a sale.
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}, sorry we missed your call at {business}. Reply here or book at {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 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 regular who’s been in five times reads differently from a first-time caller; a 9am missed call reads differently from a 6pm one; a dog groomer and a solicitor want very different warmth. A single template can’t flex to all of that without becoming a pile of if statements, and a stiff template is exactly what makes customers feel they’re talking to a machine. One cheap Haiku call gives every text-back 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 text. A single Haiku call writes one SMS — no chains, no retries that could fan out into more messages.
- Only the facts it’s handed. First name, business, voice, 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 booking URL is injected afterwards so it can never be mangled.
- Validate every draft. Length, a single link, an opt-out hint, no prices or promises — checked before it’s sent.
- A template is always ready. If the model fails or drifts, a fixed, correct text goes out instead — the system never goes quiet.
- The model decides nothing. Whether, to whom, and which link were all settled upstream; the model only chooses words.