Voice Profile As Prompt Input: Why Auto-Drafting Quote Follow-ups Doesn't Sound Like a Bot
From "the cadence engine fires beat 1 / 7 / 14 days after a quote sends and emits a follow-up notification at the assigned UW so they can write the email — except they're booked, the queue piles up, and the broker hears from us four days late in a tone that's three notches more formal than the one we set during the quote conversation" to "auto-drafted personalized follow-up emails on the UW's behalf using their stored voice profile (tone, length, sign-off, style hints), a pre-send review window UWs can configure per cadence, an auto-send sweeper that ships drafts after the review window with the UW's blessing, and a regenerate-with-instruction-delta loop when the first draft misses" — through one orchestrator service, one User Persona table that already existed, four Follow Up columns, and a draft-pane embedded into the existing follow-up panel.
The Problem
The quote follow-up cadence engine (blog #95) works. When a quote sends, a beat-1 / beat-7 / beat-14 follow-up is materialized in Follow Up per the (lob, product) cadence config. The worker sweeps due rows and writes a quote followup due notification at the assigned UW.
The problem isn't the cadence. The problem is what happens after the notification.
A booked UW, four hours late on the beat-1 because she was in a renewal review, opens the inbox at 4:30 PM. The notification says "Follow-up due on Acme renewal quote." She opens the submission, reads the quote summary, opens the email composer, writes a follow-up, sends. Twelve minutes per email. Six pending follow-ups in the inbox. She does two and saves the rest for tomorrow. The broker waits two more days.
Or — and this is the real failure mode — she dashes off something quick, a generic "checking in on the Acme quote, let me know if you need anything else," sends in 90 seconds, and the broker hears from the workstation in a voice that doesn't match the thoughtful, concrete tone the UW used during the quote conversation. The broker registers the mismatch, even subconsciously. The relationship erodes a notch.
Two naïve framings:
- Auto-send a templated follow-up at beat-1 / beat-7 / beat-14. Now every UW's voice is the same template-rendered voice. Brokers get the same email shape from every UW. The personalization is gone, the trust signal is gone, and the carrier's biggest competitive moat — the UW relationship — is flattened.
- Generate emails using a generic LLM at send time. Now the UW has no read on what got sent. The voice is ChatGPT-generic. Some emails are great; some land sideways. The UW finds out when the broker replies.
The right framing: the cadence already exists; the auto-draft is what happens between the cadence firing and the email going out. Generate a draft when the cadence fires; let the UW review it (configurable hours); auto-send only with explicit per-cadence opt-in; let the LLM see the UW's voice profile so the draft sounds like her, not like the model.
User Persona already exists. It carries tone preference (formal / collegial / direct / warm), preferred length (terse / standard / verbose), sign-off (-Sarah, Best regards, Sarah, etc.), and style hints (free-text). Email AIDraft Service already does the prompt assembly and PII strip. AIDraft already stores the generated subject + body. None of this is new.
What's new is the orchestrator that ties the cadence to the draft.
The InsightUW Approach
The orchestrator is the new piece. Everything else already shipped or already existed.
User Persona — the voice profile (already existed)
This table predates the cadence work; it was originally added for declination drafts. Reusing it costs nothing.
The voice-profile editor at /uw/settings/voice-profile is straight-forward — four selects, one textarea, a list of phrase chips for blocked topics, save button. Most UWs do it once and forget about it. The orchestrator reads it on every draft.
Follow Up — four new columns
That's it. The cadence row has a pointer to the draft, a state, a flag, and a timestamp.
Quote Follow Up Config — three new columns
Three knobs per cadence row. Conservative defaults: auto_draft_enabled=True, require_uw_review_before_send=True, auto_send_after_review_hours=NULL (i.e., never auto-send; explicit UW accept required). A team that trusts the drafts can set require_uw_review_before_send=False and auto_send_after_review_hours=4 — drafts get 4 hours of review window, then go.
AIDraft — two new columns
Both nullable; legacy decline drafts ignore them.
The orchestrator — five entry points
Five entry points total: auto draft for followup, regenerate draft, discard draft, mark draft sent, auto send sweep. Each is a small state-machine move on the Follow Up.ai_draft_status field.
The cadence worker (process due follow ups) calls auto draft for followup instead of the old "emit notification" code path. Beat fires → draft generated → notification fires → UW reviews.
regenerate draft — the instruction-delta loop
The instruction_delta lands in the existing AI draft service's regenerate path (which already handles the prior-draft + instruction format from the declination flow). UW types "shorter and mention the broker's name in the open" → new draft → embedded preview updates.
auto send sweep — the timed-out path
Default sweep interval 900s; disable via QUOTE_FOLLOWUP_AUTO_SEND_DISABLED=1. The sweep only acts on rows where the UW deliberately turned require uw review before send off + set a non-null auto send after review hours — opt-in, not default.
Blocked-topic guard
User Persona.blocked_topics_json flows into the prompt assembly. If the generated draft mentions a phrase the UW has blocked ("we'll match," "best price guarantee," etc.), the AI draft service raises BlockedTopicError; the orchestrator catches it, sets ai_draft_status='failed', fires quote followup draft failed with the reason. The UW gets the notification, opens the inbox, regenerates with an instruction_delta or writes the email manually.
The blocked-topic check is per-UW. A UW who never wants "best price" rendered, ever, won't see it on a draft on her behalf.
Worked Example: Sarah's Wednesday Inbox
Sarah's voice profile is set:
- tone: collegial
- preferred_length: standard
- sign_off: -Sarah
- style_hints: "Open with the broker's first name. Reference the specific account name once. Avoid 'reaching out' as an opener."
- blocked_topics: ["best price", "match the market"]
Wednesday 10:14 AM. Two quote follow-ups land in the cadence worker — beat-7 on Acme Construction (broker: Mary Acme), beat-1 on Beta Industries (broker: Tom Beta). Both have auto_draft_enabled=True, require_uw_review_before_send=True (default).
The orchestrator generates two drafts. Two quote followup draft ready notifications land in Sarah's inbox under the "Follow-ups" tab.
Sarah opens the Acme one. The submission workspace's quote-followup-panel has a draft pane embedded:
Subject: Checking in on the Acme Construction excess casualty quote
Hi Mary,
Following up on the $50M excess casualty quote we sent for Acme Construction on April 18 — wanted to check whether you've had a chance to review with the client. Happy to walk through the deductible structure or sub-limit detail if it would be useful for your conversation; let me know what timing looks like for a decision.
-Sarah
She reads it. The opener is collegial, the broker's name is in the open, the account is named once, "reaching out" isn't there, the sign-off is hers. Length is standard. Tone matches. She clicks "Accept and send." The draft pane calls mark draft sent, the email composer drawer hands off to the existing uw_email_send_service.send_from_draft path, and the email goes out from Sarah's send-as-UW connector. ai_draft_status='sent'. followup_status='sent'. The follow-up row drops out of her queue.
The Beta one she clicks open. The draft is generic — the LLM didn't have great context for Tom's prior tone, the open is "Reaching out about the Beta Industries quote." She sees the violated style hint and clicks "Regenerate." Modal: "Tell me what to change." She types: "Open with Tom's name; don't use 'reaching out'; mention the workers' comp coverage we discussed last week." Submits. New draft renders in 4 seconds:
Subject: Beta Industries quote — checking on next steps
Hi Tom,
Wanted to circle back on the Beta Industries quote we sent yesterday. We've got the workers' comp coverage you flagged on our call last week reflected in the layered structure — let me know if there's anything you want me to clarify or restructure before you take it to the client.
-Sarah
Better. She accepts. Sent.
Two follow-ups handled in 90 seconds total — including one regenerate. The voice is hers; the brokers don't know an LLM was involved. The audit trail captures the prompt (PII-stripped), the persona at draft time, the regenerate delta, the final body, and the send timestamp.
When auto-send fires
A different cadence config — for renewal-bound accounts on Sarah's team — has require_uw_review_before_send=False and auto_send_after_review_hours=6. Friday afternoon, beat-3 fires for an account; the orchestrator drafts; Sarah's inbox gets a quote followup draft ready notification.
She doesn't get to it before leaving for the weekend. Saturday morning, 6 hours after generation, the auto_send_sweep runs. The draft is sent. ai_draft_status='sent'. Sarah comes in Monday, sees the audit row in her sent folder, reads the email, confirms it's fine. The system shipped on her behalf with the voice profile she set, the topics she didn't block, and a trail back to the source cadence row.
When the LLM hits a wall
Tuesday, Sarah is reviewing a sensitive declination follow-up where the broker hasn't accepted that the carrier won't write the risk. The orchestrator generates a draft; the prompt assembly notices the prompt context contains "best price" (in a prior email thread chunk supplied to the model). The model output includes "I want to make sure we're offering the best price possible" — which Sarah has blocked.
BlockedTopicError. ai_draft_status='failed'. quote followup draft failed notification fires with reason='blocked_topic: best price'. Sarah sees the notification, clicks through, reads the failure reason, and writes the email manually — exactly the path she'd have taken without the auto-draft. The system didn't add work; it just got out of the way when it couldn't help.
What's Deferred (Phase 2)
- Persona learning from sent emails. Today, the persona is set explicitly by the UW. Phase 2: a periodic ingestion of the UW's sent folder that auto-suggests style hints based on observed patterns. Stub designed; intentionally manual today because UWs distrust auto-tuning of their voice.
- Per-broker tone overrides. A UW might want a different tone for one specific broker (more formal for an institutional broker, more direct for a high-volume MGA). The persona is per-UW today; per-(UW, broker) overrides are a Phase 2 join.
- Beat-specific drafting templates. Today, beat-1 / beat-7 / beat-14 use the same prompt template with sequence_index as a context variable. Phase 2: distinct templates per beat ("first nudge" vs. "polite escalation" vs. "last call before withdrawal") with their own LLM prompts.
- Draft scoring. A confidence/quality score on the draft (e.g., persona-match, length-target, blocked-topic-clear) shown to the UW pre-send. Mechanically simple; deferred until UWs ask for it.
- Multilingual drafts. Today, drafts are English-only. Bermuda + Canadian deployments occasionally want CA/FR or BMD-specific phrasing; the prompt assembly supports it but no UI control yet.
- Reply-thread context expansion. Today, the orchestrator passes quote + submission + insured + broker context. Including the broker's most recent reply text (PII-stripped) for tone-mirroring is a Phase 2 enrichment.
- Auto-send escalation paths. When auto-send sends and the broker replies with a question the UW hasn't seen, no notification fires. Phase 2: detect "first reply on a UW-absent thread" → high-priority notification.
What This Means for Underwriters
- The cadence engine is unchanged. Beat-1 / beat-7 / beat-14 still fires from the existing worker. The orchestrator is what runs after the beat fires.
- Voice profile is a one-time setup. Tone, length, sign-off, style hints, blocked topics. Most UWs do it once and never touch it again. The orchestrator reads it on every draft.
- Three knobs per cadence row. auto draft enabled, require uw review before send, auto send after review hours. Conservative defaults — explicit accept required. Teams that trust drafts opt into auto-send.
- Regenerate-with-instruction-delta is one click + one sentence. "Shorter and less formal." "Open with the broker's name." "Mention the workers' comp coverage we discussed." The LLM revises against the same persona.
- Blocked topics never ship. If a draft mentions a phrase the UW has blocked, the orchestrator fails the draft and surfaces the failure as a notification. UW writes manually that round.
- Auto-send is opt-in, time-bound, and audit-tagged. Auto-sent drafts carry an audit row pointing to the persona at draft time, the prompt, the body, and the source cadence row. Compliance can reconstruct exactly what shipped on whose behalf.
- Failures don't pile up silently. quote followup draft failed notifications fire with a reason —
blocked_topic: ..., generation error, auto send send failed. UW sees what happened and acts. - Audit captures persona at draft time. If a UW's persona changes after a draft was generated but before send, the draft's audit row carries the persona snapshot from when it was generated. Drift doesn't pollute the audit.
- Existing send-as-UW infrastructure is reused.
uw_email_send_service.send_from_draftis the same path the manual composer uses. The sent folder, outbox, retries, bounce handling — all unchanged. - Brokers don't experience a "carrier voice." Each UW's auto-drafts sound like that UW. The relationship signal stays intact; the carrier scales without flattening tone.
- Voice profile editor lives at
/uw/settings/voice-profile. Two-minute setup, four selects + one textarea + chip input for blocked topics. Most UWs do it during onboarding. - The follow-up panel and inbox don't change shape. Existing follow-up workflow surfaces —
quote-followup-panel, "Follow-ups" inbox tab — gain a draft pane and one new notification type. Zero shift in mental model for UWs who know the workflow.
What's Next
The data integration hub (blog #108) catalogs every cross-system flow — including the AI draft generation path that the orchestrator triggers. When auto-send sends an email, the hub captures the trace from cadence-fire → draft-generated → email-sent → broker-reply, end-to-end. Next blog: how that trace works without moving any data.
Want to see how InsightUW auto-drafts follow-ups in your underwriters' voices instead of a generic carrier voice? Request a demo.