daimon.email
ExamplesInbound

Smart Labeling Agent

Automatically categorize and label incoming emails

Overview

A smart labeling agent uses LLMs to automatically classify and tag incoming emails, making it easy to filter and process messages by category. This example demonstrates polling, classification, and label management.

Info

Perfect for email triage, spam filtering, priority detection, or routing messages to specialized handlers.

How It Works

  1. Poll for new messages regularly
  2. Use an LLM to classify each message (support, billing, spam, urgent, etc.)
  3. Apply labels via the API
  4. Filter messages by label for downstream processing

Complete Implementation

import { DaimonClient } from 'daimon-email';
import OpenAI from 'openai';

const client = new DaimonClient({ apiKey: process.env.DAIMON_API_KEY });
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

interface EmailLabel {
  category: string;
  priority: 'low' | 'medium' | 'high' | 'urgent';
  tags: string[];
}

// Step 1: Poll for new messages
async function pollForMessages(inboxId: string) {
  const messages = await client.inboxes.messages.list(inboxId, {
    limit: 50,
    unread: true // Only process unread messages
  });

  console.log(`Found ${messages.length} unread messages`);

  for (const message of messages) {
    await processMessage(inboxId, message);
  }
}

// Step 2: Classify message with LLM
async function classifyEmail(message: any): Promise<EmailLabel> {
  const prompt = `Classify this email into categories and assign priority:

From: ${message.from}
Subject: ${message.subject}
Body: ${message.replyBody || message.body}

Return a JSON object with:
{
  "category": "support" | "billing" | "sales" | "spam" | "notification",
  "priority": "low" | "medium" | "high" | "urgent",
  "tags": ["tag1", "tag2"]
}`;

  const completion = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: [{ role: 'user', content: prompt }],
    response_format: { type: 'json_object' }
  });

  return JSON.parse(completion.choices[0].message.content);
}

// Step 3: Apply labels
async function processMessage(inboxId: string, message: any) {
  try {
    const classification = await classifyEmail(message);

    console.log(`Classified "${message.subject}" as ${classification.category} (${classification.priority})`);

    // Apply labels to the message
    const labels = [
      classification.category,
      `priority:${classification.priority}`,
      ...classification.tags
    ];

    // Update message with labels (using custom metadata)
    await client.inboxes.messages.update(inboxId, message.id, {
      labels: labels,
      metadata: {
        classified_at: new Date().toISOString(),
        category: classification.category,
        priority: classification.priority
      }
    });

    // Handle high priority messages immediately
    if (classification.priority === 'urgent' || classification.priority === 'high') {
      await handleUrgentMessage(message, classification);
    }

  } catch (error) {
    console.error(`Failed to process message ${message.id}:`, error);
  }
}

// Step 4: Handle urgent messages
async function handleUrgentMessage(message: any, classification: EmailLabel) {
  console.log(`URGENT: ${message.subject}`);

  // Could trigger alerts, escalations, or immediate responses
  // For example, notify via Slack or create a high-priority ticket
}

// Step 5: Filter messages by label
async function getMessagesByCategory(inboxId: string, category: string) {
  const messages = await client.inboxes.messages.list(inboxId, {
    labels: [category]
  });

  return messages;
}

// Run the labeling agent
async function runLabelingAgent() {
  const inboxId = 'inb_abc123';

  console.log('Starting smart labeling agent...');

  // Poll every 30 seconds
  setInterval(async () => {
    await pollForMessages(inboxId);
  }, 30000);

  // Initial poll
  await pollForMessages(inboxId);
}

runLabelingAgent();
from daimon_email import DaimonClient
from openai import OpenAI
import os
import time
import json
from typing import Dict, List

client = DaimonClient(api_key=os.environ.get('DAIMON_API_KEY'))
openai_client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))

# Step 1: Poll for new messages
def poll_for_messages(inbox_id: str):
    messages = client.inboxes.messages.list(
        inbox_id,
        limit=50,
        unread=True  # Only process unread messages
    )

    print(f"Found {len(messages)} unread messages")

    for message in messages:
        process_message(inbox_id, message)

# Step 2: Classify message with LLM
def classify_email(message: Dict) -> Dict:
    prompt = f"""Classify this email into categories and assign priority:

From: {message['from']}
Subject: {message['subject']}
Body: {message.get('reply_body') or message.get('body')}

Return a JSON object with:
{{
  "category": "support" | "billing" | "sales" | "spam" | "notification",
  "priority": "low" | "medium" | "high" | "urgent",
  "tags": ["tag1", "tag2"]
}}"""

    completion = openai_client.chat.completions.create(
        model='gpt-4',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )

    return json.loads(completion.choices[0].message.content)

# Step 3: Apply labels
def process_message(inbox_id: str, message: Dict):
    try:
        classification = classify_email(message)

        print(f"Classified \"{message['subject']}\" as {classification['category']} ({classification['priority']})")

        # Apply labels to the message
        labels = [
            classification['category'],
            f"priority:{classification['priority']}",
            *classification['tags']
        ]

        # Update message with labels
        client.inboxes.messages.update(inbox_id, message['id'], {
            'labels': labels,
            'metadata': {
                'classified_at': time.time(),
                'category': classification['category'],
                'priority': classification['priority']
            }
        })

        # Handle high priority messages immediately
        if classification['priority'] in ['urgent', 'high']:
            handle_urgent_message(message, classification)

    except Exception as e:
        print(f"Failed to process message {message['id']}: {e}")

# Step 4: Handle urgent messages
def handle_urgent_message(message: Dict, classification: Dict):
    print(f"URGENT: {message['subject']}")

    # Could trigger alerts, escalations, or immediate responses
    # For example, notify via Slack or create a high-priority ticket

# Step 5: Filter messages by label
def get_messages_by_category(inbox_id: str, category: str):
    messages = client.inboxes.messages.list(
        inbox_id,
        labels=[category]
    )

    return messages

# Run the labeling agent
def run_labeling_agent():
    inbox_id = 'inb_abc123'

    print('Starting smart labeling agent...')

    while True:
        poll_for_messages(inbox_id)
        time.sleep(30)  # Poll every 30 seconds

if __name__ == '__main__':
    run_labeling_agent()

Advanced: Multi-Label Classification

For more nuanced classification, apply multiple labels simultaneously.

interface AdvancedClassification {
  primaryCategory: string;
  subcategories: string[];
  sentiment: 'positive' | 'neutral' | 'negative';
  intent: string[];
  requiresAction: boolean;
}

async function advancedClassification(message: any): Promise<AdvancedClassification> {
  const prompt = `Perform advanced classification on this email:

From: ${message.from}
Subject: ${message.subject}
Body: ${message.replyBody}

Return JSON with:
{
  "primaryCategory": "support" | "billing" | "sales" | "feedback",
  "subcategories": ["refund_request", "technical_issue"],
  "sentiment": "positive" | "neutral" | "negative",
  "intent": ["request_refund", "report_bug"],
  "requiresAction": true | false
}`;

  const completion = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: [{ role: 'user', content: prompt }],
    response_format: { type: 'json_object' }
  });

  return JSON.parse(completion.choices[0].message.content);
}
def advanced_classification(message: Dict) -> Dict:
    prompt = f"""Perform advanced classification on this email:

From: {message['from']}
Subject: {message['subject']}
Body: {message.get('reply_body')}

Return JSON with:
{{
  "primaryCategory": "support" | "billing" | "sales" | "feedback",
  "subcategories": ["refund_request", "technical_issue"],
  "sentiment": "positive" | "neutral" | "negative",
  "intent": ["request_refund", "report_bug"],
  "requiresAction": true | false
}}"""

    completion = openai_client.chat.completions.create(
        model='gpt-4',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )

    return json.loads(completion.choices[0].message.content)

Use Cases

  • Support triage: Route urgent issues to humans, auto-handle common questions
  • Spam filtering: Classify and auto-archive spam
  • Sales lead scoring: Identify high-value prospects from inquiries
  • Priority routing: Escalate VIP or time-sensitive messages
  • Compliance: Flag messages requiring legal or security review

Next Steps