How to Build an Email Drafting Assistant with Claude
Building an email drafting assistant with Claude means combining a well-structured prompt, relevant context (sender intent, recipient relationship, past thread), and an API setup that reliably returns clean, editable drafts. The core technical challenge isn't getting Claude to write an email — it's getting it to write the right email, in the right tone, without hallucinating facts or sounding robotic.
This guide walks through the full implementation: prompt structure, context injection, tone control, streaming the draft to a UI, and handling edge cases like missing information or multi-turn revisions.
What an Email Drafting Assistant Actually Needs
Before writing code, define the inputs your assistant needs on every request:
- Intent — what the email is for (follow-up, apology, sales outreach, status update)
- Recipient context — relationship (client, colleague, cold lead), formality level
- Key facts — dates, numbers, names, decisions that must appear verbatim
- Thread history — if replying, the prior message(s) for continuity
- Tone preference — formal, friendly, direct, apologetic
Skipping any of these is the most common reason drafting assistants produce generic, unusable output. Claude is good at writing — it's bad at guessing what you didn't tell it.
Designing the System Prompt
A focused system prompt keeps output consistent across users and sessions. Avoid vague instructions like "write a good email" — be explicit about structure and constraints.
You are an email drafting assistant. Given an intent, key facts, and tone,
produce a complete email draft.
Rules:
- Use only the facts provided. Never invent names, dates, or numbers.
- Match the requested tone exactly.
- Keep subject lines under 60 characters.
- Output format: Subject line, then a blank line, then the body.
- Do not add a signature unless one is provided.
- If critical information is missing, ask one clarifying question instead
of guessing.
That last rule matters more than it looks. Without it, Claude will happily fabricate a meeting time or a project name to fill a gap — which is the fastest way to lose user trust in a drafting tool.
Structuring the Request
Keep the user-facing input structured rather than free text when possible. A simple JSON-like format in the prompt reduces ambiguity:
{
"intent": "follow-up after no response",
"recipient": "client, mid-formality",
"facts": ["proposal sent March 3", "no reply after two weeks"],
"tone": "polite but direct"
}
Feeding this as structured context inside the user message, rather than a vague "write a follow-up email," produces far more consistent drafts across different users and intents.
Implementation with SubToAPI
If you're already using Claude through a Pro or Team subscription, SubToAPI turns that access into a standard HTTPS API with application keys, so you can call Claude from your drafting tool's backend without managing separate billing or infrastructure. Here's a working example:
const response = await fetch('https://api.subtoapi.app/v1/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUBTOAPI_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'claude-sonnet-4',
max_tokens: 500,
system: `You are an email drafting assistant. Use only the facts
provided. Never invent names, dates, or numbers. Match the requested
tone. Output: Subject line, blank line, then body.`,
messages: [
{
role: 'user',
content: `Intent: follow-up after no response
Recipient: client, mid-formality
Facts: proposal sent March 3, no reply after two weeks
Tone: polite but direct`
}
]
})
});
const data = await response.json();
console.log(data.content[0].text);
This returns a ready-to-edit subject and body. For a chat-style drafting UI where the user refines the draft in follow-up turns ("make it shorter," "add a deadline"), keep appending to the messages array so Claude retains the original facts and tone across revisions. Full request and response details are in the messages docs.
Streaming the Draft for a Better UX
Email drafts are long enough that streaming noticeably improves perceived speed. Instead of waiting for the full response, stream tokens as they're generated:
const response = await fetch('https://api.subtoapi.app/v1/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUBTOAPI_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'claude-sonnet-4',
max_tokens: 500,
stream: true,
system: '...',
messages: [{ role: 'user', content: '...' }]
})
});
for await (const chunk of response.body) {
// append chunk text to the UI as it arrives
}
Streaming setup and event formats are covered in detail in the streaming docs.
Handling Variations: Tone, Length, and Revisions
A production-grade assistant needs more than a single-shot draft. Common patterns:
- Tone switching — keep a fixed set of tone labels (formal, friendly, direct, apologetic) rather than free-text tone descriptions, so output stays predictable.
- Length control — explicitly state a target length ("3 short paragraphs" or "under 100 words") rather than relying on
max_tokensalone, since token limits cut off output rather than compress it. - Revision turns — when a user asks for a change, send the full prior draft back as context along with the revision request, not just the new instruction in isolation.
- Multiple drafts — if offering 2–3 variants, run separate requests with slightly different temperature or tone framing rather than asking Claude to generate several options in one response, which tends to produce weaker variants after the first.
Tool Use for Pulling in Real Data
If your assistant needs to pull facts from a CRM or calendar before drafting (e.g., "follow up on the invoice due March 3"), use tool calling so Claude requests the data it needs rather than guessing. This keeps drafts factually accurate and is covered in the tools documentation.
Getting Started
If you're evaluating infrastructure for this, start with the quickstart guide to get an API key and send your first request. SubToAPI plans start at Solo (€9/month) for individual projects, with Team (€19/seat) and Scale (€49/seat) tiers for shared drafting tools across a team — all with a free trial at signup. Full plan details are on the pricing page.
questions
Does Claude need fine-tuning to draft good emails? No. A well-structured system prompt with explicit rules on tone, facts, and format produces consistent results without fine-tuning. Most quality issues come from vague prompts, not model limitations.
How do I stop Claude from inventing details in drafts? Explicitly instruct it to use only provided facts and to ask a clarifying question instead of guessing when information is missing. Also keep temperature moderate (0.3–0.6) for drafting tasks.
Can I use my existing Claude subscription instead of a separate API plan? Yes — tools like SubToAPI convert a Claude subscription into a standard HTTPS API with application keys, so you can integrate drafting features into your product without separate API billing.