Skip to content

Draft

What the model is asked at 2.1 draft_reply. One call, and only for items that reach it.

Rules for every prompt, including the ten-section anatomy and the cache boundary, are in architecture: prompts. This page is what fills those sections for Draft.

Engine Capture
Runs Only when the chosen action needs generated content
Model Better than Classify
Output Prose, as plain text or light markdown
Improves via Retrieval of approved examples, and the diff on edited drafts

At a glance

# Section Block Cached Filled with
1 Role System ✅ Writes a reply for a human to approve. Does not send, does not decide
2 Vocabulary System ✅ The tenant's voice: formality, sign-off, standing instructions
3 Tie-breaks System ✅ Accuracy beats voice. The rule when they conflict
4 Escape hatch System ✅ Say what is not known rather than inventing it
5 Output contract System ✅ Body text only. No subject, no recipients, no HTML
6 Examples System ✅ Approved drafts retrieved for this situation
7 Facts User ❌ KNOWN and NOT KNOWN
8 State User ❌ Last two messages in full, plus what we already said
9 Permitted actions User ❌ n/a. The action is already decided
10 The content User ❌ The message being replied to, masked

The snippets below show shape, not the live text. The prompt itself is a versioned template in the brain's source.


Accuracy over voice

Three things Draft could optimise, and they conflict:

Accurate Says only true things
In their voice Sounds like the person who normally writes
Complete Answers everything they asked

A safely accurate reply hedges everything and sounds nothing like a tradesman. A voice-perfect reply may confidently state something we do not know.

Accuracy wins, and the prompt says so explicitly.

A draft that sounds slightly generic gets approved with a small edit. A draft that promises a Tuesday callback nobody agreed to gets sent, and then someone rings the customer back to unpick it.


The system block

1. Role

You write email replies on behalf of {business_name}, a {business_type}.

A human reviews every draft before it is sent.

You do not send. You do not decide what happens next. You do not
choose the subject or the recipients.

Stating the negative matters here more than anywhere. Given an email, a model's instinct is to be maximally helpful: offering times, confirming things, adding next steps. Every one of those is a commitment we may not be able to keep.

2. Voice

Injected from tenant config (reply_voice).

Formality:        first names, no "Dear"
Sign-off:         "Cheers, {name}"
Length:           short. Three or four sentences is normal
Standing rules:   never quote a price. never confirm a technician by name

Standing rules are the useful part. "Never quote a price in an email" is a business rule the model can follow, and it is not something the retrieved examples would reliably teach.

3. Accuracy beats voice

If matching the customary tone would require stating something you
do not know, choose accuracy. A slightly stiff reply that is true
is better than a natural one that is wrong.

4. Say what is not known

If answering properly requires something in NOT KNOWN, say you will
confirm it and come back to them.

Do not estimate. Do not use a typical value. Do not say "usually"
about something specific to this customer.

"I'll confirm the arrival time and come back to you" is an honest draft. Inventing 9am is not, and 9am is what such an email usually says, which is exactly why the model will reach for it.

5. Output contract

Return the body text only, as plain text or light markdown.

No subject line. No greeting block beyond the salutation. No
signature. No HTML.

The subject and recipients come from the mail connector, and the signature and HTML wrapper are applied by the brain from the tenant's template (2.1). The model writes the body and nothing else.

6. Examples

Retrieved by the Remember engine via pgvector: past approved drafts for this tenant, similar to the current situation.

This is the only place in the product that uses Remember, and it is what makes a reply sound like them rather than like a language model.

An empty example set is expected, not a bug

Client-zero has no approved drafts on day one. Retrieval returns nothing and Draft falls back to reply_voice alone.

The result is more generic prose, corrected by the approver, and those corrections seed the store. Worth knowing so nobody spends a day debugging why retrieval is empty.

Only approved drafts are retrieved, and where a human edited before approving, the edited version is stored. The unedited one is what they rejected.


The user block

7. KNOWN and NOT KNOWN

"Be accurate" is an instruction models agree to and then ignore. It needs a structure.

KNOWN:
  customer:            Preston Warehousing
  job:                 J-4471, switchboard upgrade
  job status:          scheduled
  scheduled date:      Thursday 21 August
  job link certainty:  certain

NOT KNOWN:
  who will attend
  arrival time
  whether the part has arrived

The NOT KNOWN block is the load-bearing part. Without it, a model asked about a Thursday job will write "our technician will be there Thursday morning", because that is what such an email contains.

Rule Guards against
Never state anything not in KNOWN Invention
Never commit to a time, date or person unless it is in KNOWN The failure that costs money
Hedge when job_link_certain is false "Regarding your Preston job", not "regarding job 4471"

NOT KNOWN is generated, not written. It is derived from what Resolve failed to find and what the job record leaves null, so it stays honest without anyone maintaining a list.

8. State

Draft needs the wording, where Classify needed only summaries.

Age Sent as
The message being replied to Full
The two before it Full
Older One-line summaries
What we already sent Full. So it does not repeat or contradict

This is the expensive half of the split, and it is only paid on items that actually produce a reply. "We said someone would call Tuesday" has to be quoted accurately, not paraphrased.

Two facts change the framing:

Fact Effect
was_chased Open by acknowledging the delay, not with a fresh greeting
Regenerated for staleness Same
human_response_reason The reason a human rejected the last attempt. Goes in verbatim

That last one is why the regenerate reason is mandatory. "Too formal", "do not promise Tuesday", "they already know this" is what makes attempt two different from attempt one.

10. The content

The message being replied to, masked, with quoted history stripped.

Tokens, never plausible fake names. A failed replacement produces Dear [PERSON_1], which the approver catches, rather than Dear Robert, which reads as a normal email and gets sent to Sarah (2.1).


Scheduling

What the draft may say about times depends on scheduling_mode and on what the connector can actually answer (ADR-0035).

Mode The draft says
none "Someone will call to arrange a time"
propose "Thursday or Friday morning look open, subject to availability"
hold "I have pencilled you in for Thursday 9am, held until Monday"

Slots go into KNOWN, so proposing a time is not invention. And the draft may only claim what the answer supports:

The connector answered The draft may say
Slots with a named, skilled resource "Dave is free Thursday morning"
Slots, no resource attribution "Thursday morning looks open", nothing about who
Nothing Times sit in NOT KNOWN. No time is offered

That middle row is the one to get right. A system with a single shared calendar can say a slot is free and cannot say anyone qualified is free, so the draft must not imply one.

Proposed times go stale faster than the rest of a draft

A draft written Monday saying "Thursday morning looks open", approved Thursday, may be offering a slot that filled on Tuesday.

"Subject to availability" covers the wording. Tenants on propose also want a shorter draft_staleness, and re-checking availability at approval time would be better than regenerating the whole draft. Not yet designed.


Open

  • OI-082: attachments. document_request is nearly worthless without them, and the draft needs to reference what it is sending.
  • Re-check availability at approval rather than regenerating. Better, undesigned.
  • When a draft hedges on everything, is it worth sending at all, or should it become an acknowledgement? Undecided.