ExamplesFrameworks
CrewAI Integration
Email-capable CrewAI agents
Overview
Integrate daimon.email into CrewAI multi-agent systems, enabling your crew members to handle email tasks as part of collaborative workflows.
Info
Multi-agent email: Create specialized agents within a crew that handle email operations (inbox creation, monitoring, sending) while other agents focus on their core tasks.
Installation
npm install crewai daimon-email
# or
pip install crewai daimon-emailComplete Implementation
from crewai import Agent, Task, Crew, Process
from crewai_tools import BaseTool
from daimon_email import DaimonClient
from pydantic import BaseModel, Field
import json
# Initialize daimon.email client
daimon_client = DaimonClient(api_key=os.getenv('DAIMON_API_KEY'))
# Store created inboxes in crew context
crew_inboxes = {}
# Tool 1: Create Inbox
class CreateInboxTool(BaseTool):
name: str = "Create Email Inbox"
description: str = "Create a new email inbox for the crew. Returns email address and inbox ID."
def _run(self, username: str) -> str:
inbox = daimon_client.inboxes.create(
username=username,
client_id=f'crewai-{username}-{int(time.time())}'
)
inbox_data = {
'email': inbox['result']['address'],
'inbox_id': inbox['result']['id'],
'api_key': inbox['result']['api_key']
}
# Store for crew use
crew_inboxes[inbox_data['inbox_id']] = inbox_data
return json.dumps(inbox_data)
# Tool 2: Check Messages
class CheckMessagesTool(BaseTool):
name: str = "Check Email Messages"
description: str = "Check for new messages in an inbox. Input: inbox_id"
def _run(self, inbox_id: str) -> str:
messages = daimon_client.inboxes.messages.list(inbox_id)
return json.dumps([
{
'from': m['from'],
'subject': m['subject'],
'body': m.get('reply_body') or m['body'],
'received_at': m['received_at'],
'cta_links': m.get('cta_links', [])
}
for m in messages[:10] # Limit to 10 most recent
])
# Tool 3: Send Email
class SendEmailTool(BaseTool):
name: str = "Send Email"
description: str = "Send an email from an inbox. Input: JSON with inbox_id, to, subject, body"
def _run(self, inbox_id: str, to: str, subject: str, body: str) -> str:
try:
result = daimon_client.inboxes.send(inbox_id, {
'to': to,
'subject': subject,
'body': body
})
return json.dumps({
'success': True,
'message_id': result['message_id']
})
except Exception as error:
return json.dumps({
'success': False,
'error': str(error)
})
# Create specialized agents
email_manager = Agent(
role='Email Manager',
goal='Manage email infrastructure for the crew',
backstory='You are responsible for creating inboxes, monitoring messages, and coordinating email operations.',
tools=[CreateInboxTool(), CheckMessagesTool(), SendEmailTool()],
verbose=True
)
customer_support = Agent(
role='Customer Support Specialist',
goal='Provide excellent customer support via email',
backstory='You handle customer inquiries with empathy and efficiency.',
tools=[CheckMessagesTool(), SendEmailTool()],
verbose=True
)
researcher = Agent(
role='Research Analyst',
goal='Analyze incoming emails for insights',
backstory='You extract key information and action items from email communications.',
tools=[CheckMessagesTool()],
verbose=True
)
# Define tasks
task1 = Task(
description='Create a new inbox with username "crew-support"',
agent=email_manager,
expected_output='Email address and inbox ID'
)
task2 = Task(
description='Monitor the inbox for new customer inquiries',
agent=customer_support,
expected_output='Summary of incoming messages',
context=[task1] # Depends on task1
)
task3 = Task(
description='Analyze customer emails and identify common themes',
agent=researcher,
expected_output='Report on customer email patterns',
context=[task2]
)
task4 = Task(
description='Send personalized responses to all customer inquiries',
agent=customer_support,
expected_output='List of sent responses',
context=[task2, task3]
)
# Create and run the crew
crew = Crew(
agents=[email_manager, customer_support, researcher],
tasks=[task1, task2, task3, task4],
process=Process.sequential,
verbose=True
)
result = crew.kickoff()
print("Crew Result:")
print(result)import { Agent, Task, Crew } from '@crewai/crewai';
import { DaimonClient } from 'daimon-email';
// TypeScript implementation
// Note: CrewAI is primarily Python-based
// This is a conceptual TypeScript equivalent
interface EmailTool {
name: string;
description: string;
run: (args: any) => Promise<string>;
}
const daimonClient = new DaimonClient({ apiKey: process.env.DAIMON_API_KEY });
const crewInboxes = new Map();
// Create tools
const createInboxTool: EmailTool = {
name: 'create_inbox',
description: 'Create a new email inbox',
run: async ({ username }) => {
const inbox = await daimonClient.inboxes.create({
username,
clientId: `crewai-${username}-${Date.now()}`
});
const inboxData = {
email: inbox.result.address,
inboxId: inbox.result.id,
apiKey: inbox.result.apiKey
};
crewInboxes.set(inboxData.inboxId, inboxData);
return JSON.stringify(inboxData);
}
};
const checkMessagesTool: EmailTool = {
name: 'check_messages',
description: 'Check for new messages',
run: async ({ inboxId }) => {
const messages = await daimonClient.inboxes.messages.list(inboxId);
return JSON.stringify(messages.slice(0, 10));
}
};
const sendEmailTool: EmailTool = {
name: 'send_email',
description: 'Send an email',
run: async ({ inboxId, to, subject, body }) => {
try {
const result = await daimonClient.inboxes.send(inboxId, {
to,
subject,
body
});
return JSON.stringify({ success: true, messageId: result.messageId });
} catch (error: any) {
return JSON.stringify({ success: false, error: error.message });
}
}
};
// Create agents (conceptual)
const emailManager = new Agent({
role: 'Email Manager',
goal: 'Manage email infrastructure',
tools: [createInboxTool, checkMessagesTool, sendEmailTool]
});
const customerSupport = new Agent({
role: 'Customer Support',
goal: 'Handle customer emails',
tools: [checkMessagesTool, sendEmailTool]
});
// Create crew and run
const crew = new Crew({
agents: [emailManager, customerSupport],
tasks: [/* tasks */],
process: 'sequential'
});
await crew.kickoff();Use Case: Customer Support Crew
from crewai import Agent, Task, Crew, Process
# Specialized crew for customer support
support_crew = Crew(
agents=[
Agent(
role='Email Monitor',
goal='Monitor support inbox and categorize incoming emails',
tools=[CheckMessagesTool()],
backstory='You watch for new support tickets and prioritize them.'
),
Agent(
role='Support Responder',
goal='Draft appropriate responses to customer inquiries',
tools=[SendEmailTool()],
backstory='You craft helpful, professional responses to customers.'
),
Agent(
role='Quality Assurance',
goal='Review responses before sending',
tools=[],
backstory='You ensure all responses meet quality standards.'
)
],
tasks=[
Task(
description='Check support inbox for new messages',
expected_output='List of new support tickets'
),
Task(
description='Draft responses for each ticket',
expected_output='Drafted email responses'
),
Task(
description='Review and approve responses',
expected_output='Approved responses ready to send'
),
Task(
description='Send approved responses',
expected_output='Confirmation of sent emails'
)
],
process=Process.sequential
)
# Run the crew
result = support_crew.kickoff()Use Case: Lead Generation Crew
# Crew for sales lead generation
sales_crew = Crew(
agents=[
Agent(
role='Lead Qualifier',
goal='Create inbox and monitor for inbound leads',
tools=[CreateInboxTool(), CheckMessagesTool()],
backstory='You identify and qualify incoming sales leads.'
),
Agent(
role='Outreach Specialist',
goal='Send personalized outreach emails',
tools=[SendEmailTool()],
backstory='You craft compelling outreach messages.'
),
Agent(
role='Follow-up Manager',
goal='Track responses and send follow-ups',
tools=[CheckMessagesTool(), SendEmailTool()],
backstory='You ensure no lead falls through the cracks.'
)
],
tasks=[
Task(
description='Create inbox "sales-leads" and monitor for inquiries',
expected_output='New lead emails'
),
Task(
description='Send personalized outreach to 10 prospects',
expected_output='List of sent outreach emails'
),
Task(
description='Check for responses and send follow-ups',
expected_output='Follow-up emails sent'
)
],
process=Process.sequential
)
result = sales_crew.kickoff()Advanced: Hierarchical Process
# Manager agent coordinates email operations
manager = Agent(
role='Email Operations Manager',
goal='Coordinate all email activities across the crew',
tools=[CreateInboxTool(), CheckMessagesTool()],
backstory='You oversee email operations and delegate tasks.',
allow_delegation=True
)
# Hierarchical crew with manager
hierarchical_crew = Crew(
agents=[manager, email_manager, customer_support, researcher],
tasks=[/* tasks */],
process=Process.hierarchical,
manager_llm='gpt-4'
)
result = hierarchical_crew.kickoff()Crew Memory & Context
from crewai import Crew, Process
from crewai.memory import ConversationMemory
# Crew with memory of email operations
crew = Crew(
agents=[email_manager, customer_support],
tasks=[task1, task2, task3],
process=Process.sequential,
memory=ConversationMemory(), # Remembers inbox IDs, past emails, etc.
verbose=True
)
# Agent can reference previous inboxes without re-creating
result = crew.kickoff(
inputs={
'inbox_username': 'support-crew',
'customer_email': 'customer@example.com'
}
)Integration with CrewAI Manager
from crewai import CrewManager
# Manage multiple crews with email capabilities
manager = CrewManager()
# Support crew
support_crew = Crew(
agents=[/* support agents */],
tasks=[/* support tasks */]
)
# Sales crew
sales_crew = Crew(
agents=[/* sales agents */],
tasks=[/* sales tasks */]
)
# Coordinate crews
manager.add_crew('support', support_crew)
manager.add_crew('sales', sales_crew)
# Run crews in parallel
results = manager.kickoff_all()Error Handling
class SafeSendEmailTool(BaseTool):
name: str = "Safe Send Email"
description: str = "Send email with error handling"
def _run(self, inbox_id: str, to: str, subject: str, body: str) -> str:
try:
result = daimon_client.inboxes.send(inbox_id, {
'to': to,
'subject': subject,
'body': body
})
return json.dumps({'success': True, 'message_id': result['message_id']})
except Exception as error:
if hasattr(error, 'code') and error.code == 'SEND_REQUIRES_PAID':
return json.dumps({
'success': False,
'error': 'UPGRADE_REQUIRED',
'message': 'Please upgrade to paid tier to send emails',
'upgrade_url': error.upgrade_context.get('operator_action_url')
})
else:
return json.dumps({
'success': False,
'error': str(error)
})Testing Your Crew
# Test crew with mock inbox
def test_support_crew():
# Create test inbox
inbox = daimon_client.inboxes.create(
username='test-crew',
client_id='test-crew-1'
)
# Run crew
result = support_crew.kickoff(
inputs={'inbox_id': inbox['result']['id']}
)
# Verify results
assert 'email sent' in result.lower()
# Clean up
daimon_client.inboxes.delete(inbox['result']['id'])