daimon.email
ExamplesAdvanced

Magic Upgrade Example

Complete implementation of the magic upgrade flow

Overview

The magic upgrade flow enables agents to request tier upgrades when they hit capability limits. The agent generates a magic link, sends it to the operator (via Slack, Discord, email), and waits for the upgrade to complete.

Info

Agent-friendly design: The agent never blocks or crashes. It discovers limits gracefully, requests help, and resumes work when upgraded.

For conceptual background, see the Magic Upgrade Flow Guide.

Flow Diagram

Agent attempts to send email

Receives SEND_REQUIRES_PAID error

Calls POST /v1/upgrade-link

Sends magic link to operator (Slack/Discord)

Operator clicks link → Stripe checkout

Webhook: account.upgraded

Agent retries send → Success!

Complete Implementation

import { DaimonClient } from 'daimon-email';
import { WebClient } from '@slack/web-api';

class MagicUpgradeAgent {
  private client: DaimonClient;
  private slackClient: WebClient;
  private inboxId: string;

  constructor(apiKey: string, slackToken: string, inboxId: string) {
    this.client = new DaimonClient({ apiKey });
    this.slackClient = new WebClient(slackToken);
    this.inboxId = inboxId;
  }

  async sendEmail(to: string, subject: string, body: string) {
    try {
      const result = await this.client.inboxes.send(this.inboxId, {
        to,
        subject,
        body
      });

      console.log('✅ Email sent:', result.messageId);
      return result;

    } catch (error: any) {
      if (error.code === 'SEND_REQUIRES_PAID') {
        console.log('⚠️  Sending requires paid tier');
        console.log('💡 Agent suggestion:', error.upgradeContext.agentScript);

        // Request upgrade from operator
        await this.requestUpgrade('Need sending capabilities to continue email automation');

        // Return gracefully - agent knows to wait
        throw new Error('PENDING_UPGRADE: Waiting for operator to upgrade account');
      }

      throw error;
    }
  }

  async requestUpgrade(reason: string) {
    console.log('🔗 Generating magic upgrade link...');

    const upgradeLink = await this.client.account.createUpgradeLink({
      reason,
      returnUrl: `https://my-dashboard.com/agent/${this.inboxId}`,
      metadata: {
        agentId: this.inboxId,
        requestedAt: new Date().toISOString()
      }
    });

    console.log('✅ Magic link created:', upgradeLink.url);

    // Send to operator via Slack
    await this.notifyOperatorSlack(upgradeLink.url, reason);

    return upgradeLink;
  }

  async notifyOperatorSlack(upgradeUrl: string, reason: string) {
    await this.slackClient.chat.postMessage({
      channel: '#agent-notifications',
      blocks: [
        {
          type: 'section',
          text: {
            type: 'mrkdwn',
            text: '⚠️ *Agent Upgrade Required*'
          }
        },
        {
          type: 'section',
          fields: [
            {
              type: 'mrkdwn',
              text: `*Agent:*\n${this.inboxId}`
            },
            {
              type: 'mrkdwn',
              text: `*Reason:*\n${reason}`
            }
          ]
        },
        {
          type: 'actions',
          elements: [
            {
              type: 'button',
              text: {
                type: 'plain_text',
                text: 'Upgrade Account'
              },
              url: upgradeUrl,
              style: 'primary'
            }
          ]
        }
      ]
    });

    console.log('📲 Notification sent to operator via Slack');
  }

  async handleUpgradeWebhook(event: any) {
    if (event.event === 'account.upgraded') {
      console.log('🎉 Account upgraded!');
      console.log('New tier:', event.account.tier);
      console.log('New capabilities:', event.account.capabilities);

      // Notify operator
      await this.slackClient.chat.postMessage({
        channel: '#agent-notifications',
        text: `✅ Agent ${this.inboxId} successfully upgraded to ${event.account.tier} tier!`
      });

      // Resume work
      await this.resumeWork();
    }
  }

  async resumeWork() {
    console.log('🔄 Resuming work after upgrade...');

    // Retry any failed operations
    // This would typically pull from a queue or retry buffer
  }
}

// Usage
const agent = new MagicUpgradeAgent(
  'dm_free_xxx',
  'xoxb-slack-token',
  'inb_abc123'
);

// This will trigger upgrade flow on free tier
await agent.sendEmail(
  'customer@example.com',
  'Welcome!',
  'Thanks for signing up!'
);

// Webhook handler
app.post('/webhook', async (req, res) => {
  await agent.handleUpgradeWebhook(req.body);
  res.status(200).send('OK');
});
from daimon_email import DaimonClient
from slack_sdk import WebClient

class MagicUpgradeAgent:
    def __init__(self, api_key: str, slack_token: str, inbox_id: str):
        self.client = DaimonClient(api_key=api_key)
        self.slack_client = WebClient(token=slack_token)
        self.inbox_id = inbox_id

    def send_email(self, to: str, subject: str, body: str):
        try:
            result = self.client.inboxes.send(self.inbox_id, {
                'to': to,
                'subject': subject,
                'body': body
            })

            print(f'✅ Email sent: {result.message_id}')
            return result

        except Exception as error:
            if hasattr(error, 'code') and error.code == 'SEND_REQUIRES_PAID':
                print('⚠️  Sending requires paid tier')
                print(f'💡 Agent suggestion: {error.upgrade_context["agent_script"]}')

                # Request upgrade from operator
                self.request_upgrade('Need sending capabilities to continue email automation')

                # Return gracefully - agent knows to wait
                raise Exception('PENDING_UPGRADE: Waiting for operator to upgrade account')

            raise error

    def request_upgrade(self, reason: str):
        print('🔗 Generating magic upgrade link...')

        upgrade_link = self.client.account.create_upgrade_link({
            'reason': reason,
            'return_url': f'https://my-dashboard.com/agent/{self.inbox_id}',
            'metadata': {
                'agent_id': self.inbox_id,
                'requested_at': datetime.now().isoformat()
            }
        })

        print(f'✅ Magic link created: {upgrade_link.url}')

        # Send to operator via Slack
        self.notify_operator_slack(upgrade_link.url, reason)

        return upgrade_link

    def notify_operator_slack(self, upgrade_url: str, reason: str):
        self.slack_client.chat_postMessage(
            channel='#agent-notifications',
            blocks=[
                {
                    'type': 'section',
                    'text': {
                        'type': 'mrkdwn',
                        'text': '⚠️ *Agent Upgrade Required*'
                    }
                },
                {
                    'type': 'section',
                    'fields': [
                        {
                            'type': 'mrkdwn',
                            'text': f'*Agent:*\n{self.inbox_id}'
                        },
                        {
                            'type': 'mrkdwn',
                            'text': f'*Reason:*\n{reason}'
                        }
                    ]
                },
                {
                    'type': 'actions',
                    'elements': [
                        {
                            'type': 'button',
                            'text': {
                                'type': 'plain_text',
                                'text': 'Upgrade Account'
                            },
                            'url': upgrade_url,
                            'style': 'primary'
                        }
                    ]
                }
            ]
        )

        print('📲 Notification sent to operator via Slack')

    def handle_upgrade_webhook(self, event: dict):
        if event['event'] == 'account.upgraded':
            print('🎉 Account upgraded!')
            print(f'New tier: {event["account"]["tier"]}')
            print(f'New capabilities: {event["account"]["capabilities"]}')

            # Notify operator
            self.slack_client.chat_postMessage(
                channel='#agent-notifications',
                text=f'✅ Agent {self.inbox_id} successfully upgraded to {event["account"]["tier"]} tier!'
            )

            # Resume work
            self.resume_work()

    def resume_work(self):
        print('🔄 Resuming work after upgrade...')
        # Retry any failed operations

# Usage
agent = MagicUpgradeAgent(
    'dm_free_xxx',
    'xoxb-slack-token',
    'inb_abc123'
)

# This will trigger upgrade flow on free tier
agent.send_email(
    'customer@example.com',
    'Welcome!',
    'Thanks for signing up!'
)

Notification Methods

Via Slack

await slackClient.chat.postMessage({
  channel: '#agent-ops',
  text: `🔗 Upgrade required: ${upgradeLink.url}`
});

Via Discord

await discordClient.channels.get(channelId).send({
  embeds: [{
    title: 'Agent Upgrade Required',
    description: reason,
    color: 0xff6b35,
    fields: [
      { name: 'Agent', value: inboxId },
      { name: 'Action Required', value: `[Click here to upgrade](${upgradeUrl})` }
    ]
  }]
});

Via Email

await sendgrid.send({
  to: 'operator@company.com',
  from: 'agents@company.com',
  subject: 'Agent Upgrade Required',
  html: `
    <h2>Your agent needs an upgrade</h2>
    <p><strong>Reason:</strong> ${reason}</p>
    <p><a href="${upgradeUrl}">Upgrade Now</a></p>
  `
});

Error Codes and Responses

SEND_REQUIRES_PAID

{
  "error": "SEND_REQUIRES_PAID",
  "message": "Sending emails requires a paid tier",
  "upgradeContext": {
    "operatorActionUrl": "https://daimon.email/upgrade?token=jwt...",
    "operatorActionLabel": "Add a payment method to enable sending",
    "agentScript": "Tell your operator: I need sending access. Here's a direct upgrade link: https://daimon.email/upgrade?token=..."
  }
}

SEND_LIMIT_EXCEEDED

{
  "error": "SEND_LIMIT_EXCEEDED",
  "message": "Monthly send limit reached (100/100)",
  "upgradeContext": {
    "operatorActionUrl": "https://daimon.email/upgrade?token=jwt...",
    "operatorActionLabel": "Upgrade to Growth tier for unlimited sends",
    "suggestedTier": "growth"
  }
}

Retry Logic

async function sendWithRetry(agent: MagicUpgradeAgent, to: string, subject: string, body: string) {
  let attempts = 0;
  const maxAttempts = 3;

  while (attempts < maxAttempts) {
    try {
      return await agent.sendEmail(to, subject, body);
    } catch (error: any) {
      if (error.message.includes('PENDING_UPGRADE')) {
        console.log('⏳ Waiting for upgrade... will retry in 30s');
        await new Promise(resolve => setTimeout(resolve, 30000));
        attempts++;
      } else {
        throw error;
      }
    }
  }

  throw new Error('Max retry attempts reached - upgrade not completed');
}

Webhook Event Schema

{
  "event": "account.upgraded",
  "timestamp": "2024-03-11T14:23:45Z",
  "account": {
    "id": "acc_abc123",
    "tier": "developer",
    "previousTier": "free",
    "capabilities": [
      "send_messages",
      "custom_domains",
      "smtp_access"
    ]
  },
  "billing": {
    "plan": "developer",
    "amount": 9,
    "currency": "usd",
    "interval": "month"
  },
  "upgrade": {
    "requestedAt": "2024-03-11T14:20:00Z",
    "completedAt": "2024-03-11T14:23:45Z",
    "requestedBy": "agent",
    "approvedBy": "operator@company.com"
  }
}

Testing Locally

# 1. Create test inbox
curl -X POST https://api.daimon.email/v1/inboxes \
  -H "Content-Type: application/json" \
  -d '{"username": "test-upgrade"}'

# 2. Try to send (will fail on free tier)
curl -X POST https://api.daimon.email/v1/inboxes/inb_xxx/send \
  -H "Authorization: Bearer dm_free_xxx" \
  -d '{"to": "test@example.com", "subject": "Test", "body": "Test"}'

# 3. Get upgrade link
curl -X POST https://api.daimon.email/v1/upgrade-link \
  -H "Authorization: Bearer dm_free_xxx" \
  -d '{"reason": "Testing upgrade flow"}'

# 4. Click the link (opens Stripe checkout)
# 5. Complete payment
# 6. Webhook fires to your endpoint

Next Steps