MolKit logo
Tools

Step 4 of 10

Classify intent with AI

Use OpenAI to assign each email an intent category, a confidence score, and a risk flag, the three signals that determine which route the email takes.

Why this matters

Classification is the intelligence layer of this system. It replaces the human judgment call of 'is this a billing issue or a general inquiry?' with a structured, auditable decision. Without classification, you cannot route emails differently, every email either gets the same treatment or requires a human to decide.

Build instructions

Write the classification prompt

The prompt must force the model to return structured JSON. Natural language output cannot be reliably parsed.

  1. Step 1

    In the OpenAI action step, set the 'User Message' to this classification prompt, replacing the categories with your actual policy table categories:

  2. Step 2

    TASK: Classify the email below into exactly one intent category. Return ONLY valid JSON with no explanation or preamble.

  3. Step 3

    CATEGORIES: inquiry, follow-up, support, billing, legal, unknown

  4. Step 4

    OUTPUT FORMAT: { "intent": "<category>", "confidence": <0.0 to 1.0>, "risk_flag": <true if billing/legal/unknown>, "missing_context": "<one sentence about what context would improve this classification, or null>" }

  5. Step 5

    EMAIL CONTENT: [Normalized text from previous step]

  6. Step 6

    In the 'System' message field, type: 'You are an email classification system. Always respond with valid JSON only. Never include explanation or markdown formatting.'

Parse the JSON output

  1. Step 1

    Add a Code by Zapier step after the OpenAI step. Map the OpenAI response text to a variable called 'rawJson'.

  2. Step 2

    In the code field: try { const parsed = JSON.parse(inputData.rawJson); return { intent: parsed.intent || 'unknown', confidence: parsed.confidence || 0, risk_flag: parsed.risk_flag ? 'true' : 'false', missing_context: parsed.missing_context || '' }; } catch(e) { return { intent: 'unknown', confidence: 0, risk_flag: 'true', missing_context: 'JSON parse failed' }; }

  3. Step 3

    The try/catch ensures that even if the model returns malformed JSON, the workflow continues safely by defaulting to 'unknown' intent, which escalates to human review.

Log classification results

  1. Step 1

    Add a Google Sheets step to create a new row in your Autoresponder Config sheet's second tab named 'Classification Log'.

  2. Step 2

    Write these fields: Timestamp, From Email, Subject, Detected Intent, Confidence, Risk Flag, Missing Context.

  3. Step 3

    This log becomes your primary tool for monitoring system accuracy and identifying categories where the classifier is consistently wrong.

Common mistakes

  • Asking the model to explain its classification in natural language instead of returning only JSON. Natural language cannot be reliably parsed. Enforce JSON-only output in both the system message and the user message.
  • Not handling JSON parse errors. If the model occasionally returns malformed JSON (it happens), an unhandled parse error will crash the Zap step. Always wrap JSON parsing in a try/catch that defaults to 'unknown'.
  • Using the same model for classification and drafting without separate prompts. The classification prompt and the drafting prompt have very different requirements. Always keep them in separate steps with separate prompts.

Pro tips

  • Add 'confidence must be a decimal between 0.0 and 1.0' to your prompt. Without this, models sometimes return confidence as a percentage (like 85) instead of a decimal (0.85), which breaks your threshold comparisons.

Before you continue

Send three test emails through the trigger: one obvious inquiry, one billing question, one ambiguous message. Confirm the classification log shows appropriate intent assignments with reasonable confidence scores. The billing email should have risk_flag = true regardless of confidence.

Step result

Every email passing through the trigger is assigned an intent category, confidence score, and risk flag that the routing logic can act on.