← Blog

Build an Email Assistant Using the Claude API

2026-10-19 · 5 min read · SubToAPI Team

Building an email assistant with the Claude API means wiring together three things: a way to read and classify incoming messages, a prompting strategy that drafts replies in your voice, and a set of tools the model can call to take actions like labeling, scheduling, or sending. None of this requires a custom ML pipeline — Claude's existing language understanding handles classification and drafting out of the box, and tool use handles the actions.

This guide walks through the actual architecture: how to structure prompts for triage and drafting, how to give Claude tools for email actions, and how to stream responses so users see drafts appear in real time instead of waiting on a full response.

What the assistant actually needs to do

A useful email assistant typically does four things:

  1. Classify incoming mail — support request, sales lead, newsletter, spam, needs-reply, FYI.
  2. Summarize long threads so a human doesn't have to read 20 replies.
  3. Draft replies that match the sender's tone and the account's writing style.
  4. Take action — apply a label, create a calendar event, flag for follow-up — via tool calls.

Each of these maps cleanly onto a Claude API call. Classification and summarization are plain text completions. Drafting benefits from a system prompt with examples of the user's tone. Actions require tool definitions.

Step 1: Classification and summarization

Keep classification cheap and fast — a short system prompt and a small max_tokens value is enough:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 50,
    "system": "Classify the email into one category: support, sales, newsletter, spam, needs-reply, fyi. Respond with only the category.",
    "messages": [{"role": "user", "content": "Subject: Invoice overdue\n\nHi, just checking on invoice #4821..."}]
  }'

For thread summarization, pass the full thread text and ask for a 3-sentence summary plus an action flag. This is the pattern most teams get wrong by over-engineering — a single well-scoped prompt handles both tasks without a separate model or fine-tune.

Step 2: Drafting replies that sound right

Drafting is where tone matters. Store a small set of past sent emails as examples and include them in the system prompt:

{
  "system": "You draft email replies for Alex, a customer success manager. Match this tone: direct, friendly, no corporate jargon. Example of Alex's writing: 'Thanks for flagging this — I'll get the refund processed today, no need to wait on approval.'",
  "messages": [
    {"role": "user", "content": "Draft a reply to this email: [original email text]"}
  ]
}

Keep the examples short — two or three snippets is enough to shift tone without bloating every request's token count.

Step 3: Giving the assistant tools

This is where the assistant stops being a text generator and starts doing work. Define tools for the actions you actually support — applying a label, creating a draft in the user's mail client, or flagging for follow-up:

{
  "tools": [
    {
      "name": "apply_label",
      "description": "Apply a label to an email thread",
      "input_schema": {
        "type": "object",
        "properties": {
          "thread_id": {"type": "string"},
          "label": {"type": "string", "enum": ["urgent", "waiting-on-reply", "resolved"]}
        },
        "required": ["thread_id", "label"]
      }
    },
    {
      "name": "schedule_followup",
      "description": "Schedule a follow-up reminder for an email thread",
      "input_schema": {
        "type": "object",
        "properties": {
          "thread_id": {"type": "string"},
          "days": {"type": "integer"}
        },
        "required": ["thread_id", "days"]
      }
    }
  ]
}

Claude decides when to call these based on the email content and your instructions — you don't need separate classification logic to trigger them. If you're new to tool use, the pattern (define schema, send request, execute the returned tool call, send the result back) is covered in detail in /docs/tools.

Step 4: Streaming for a live drafting UI

If your assistant has a UI where users watch a draft get written — similar to how Gmail's "Help me write" feels — use streaming instead of waiting for the full completion:

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-3-5-sonnet-20241022',
    max_tokens: 500,
    stream: true,
    messages: [{ role: 'user', content: 'Draft a reply declining this meeting request politely.' }]
  })
});

const reader = response.body.getReader();
// append each chunk to the draft textarea as it arrives

Streaming matters more for email assistants than most apps because drafts are often 100–300 words — long enough that a blocking request feels sluggish. Details on handling stream events are in /docs/streaming.

Production considerations

A few things that matter once this moves past a prototype:

If you're running this as a product rather than a personal script, SubToAPI gives you application-level API keys (sub_live_...), per-key usage metadata, and team seats on top of your existing Claude access — useful if multiple people or multiple customer mailboxes are hitting the same backend. Setup takes a few minutes; see /docs/quickstart for the full flow, or /docs/messages for the request format if you're migrating from a direct Anthropic integration. Plans start at €9/month with a free trial at /signup, and the full breakdown is at /pricing.

questions

Do I need fine-tuning to match a user's writing tone? No. A system prompt with two or three example sent emails is usually enough to shift tone noticeably. Fine-tuning adds cost and maintenance without a proportional quality gain for this use case.

How do I stop the assistant from sending emails automatically? Design the "send" action as a tool that returns a draft for human approval rather than one that executes immediately. Only wire up auto-send for low-risk categories like auto-replies after you've validated classification accuracy.

What's the cheapest way to handle high email volume? Use a smaller, cheaper model pass for classification and triage, and reserve a stronger model call for drafting replies that actually need nuance — most inbound email doesn't need a full-quality draft generated for it.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →