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