CrewAI makes it easy to orchestrate multiple AI agents that collaborate on complex tasks. Each agent in a crew can have its own role, goal, and set of tools. With AgentSend, you can add email as a first-class capability to any CrewAI agent, enabling your crews to communicate with the outside world via email.
This guide shows how to build a CrewAI tool that wraps AgentSend's REST API, giving your agents the ability to send emails, check inboxes, and manage threaded conversations. Whether you are building a customer support crew, a sales outreach team, or a research squad, email is the missing link between your agents and the humans they serve.
Why CrewAI Agents Need Email
CrewAI excels at internal agent collaboration: a researcher gathers data, an analyst processes it, and a writer produces output. But most real-world workflows require communicating results to humans. Consider these scenarios:
- Support crews where a triage agent reads incoming support emails, a resolver agent investigates the issue, and a communicator agent drafts and sends the reply.
- Sales crews where a prospector agent identifies leads, a content agent drafts personalized outreach, and an outreach agent sends the email and handles replies.
- Report crews where an analyst agent compiles weekly metrics and an email agent distributes the report to stakeholders.
- Scheduling crews where a coordinator agent manages meeting requests via email, handling back-and-forth scheduling with multiple participants.
Setting Up the Integration
You need an AgentSend account and API key. Sign up at agentsend.io, create an inbox from the dashboard, and copy your API key. Then install the dependencies:
pip install crewai requests
Building the CrewAI Email Tool
CrewAI tools are defined by subclassing BaseTool. Here is a complete email tool that supports both sending messages and checking an inbox:
import os import requests from typing import Optional, Type from pydantic import BaseModel, Field from crewai.tools import BaseTool AGENTSEND_API_KEY = os.environ["AGENTSEND_API_KEY"] AGENTSEND_BASE = "https://agentsend.io" class SendEmailSchema(BaseModel): to: str = Field(description="Recipient email address") subject: str = Field(description="Email subject line") body: str = Field(description="Plain text email body") inbox_id: str = Field(description="AgentSend inbox ID to send from") thread_id: Optional[str] = Field( default=None, description="Thread ID for replies" ) class SendEmailTool(BaseTool): name: str = "send_email" description: str = ( "Send an email via AgentSend. Use this to communicate " "with humans via email. Provide recipient, subject, and body." ) args_schema: Type[BaseModel] = SendEmailSchema def _run( self, to: str, subject: str, body: str, inbox_id: str, thread_id: Optional[str] = None, ) -> str: payload = { "inboxId": inbox_id, "to": to, "subject": subject, "text": body, } if thread_id: payload["threadId"] = thread_id resp = requests.post( f"{AGENTSEND_BASE}/messages", json=payload, headers={ "Authorization": f"Bearer {AGENTSEND_API_KEY}" }, ) resp.raise_for_status() data = resp.json() return ( f"Email sent successfully. " f"Message ID: {data['id']}, Thread: {data['threadId']}" ) class CheckInboxSchema(BaseModel): inbox_id: str = Field(description="AgentSend inbox ID") class CheckInboxTool(BaseTool): name: str = "check_inbox" description: str = ( "Check for new emails in an AgentSend inbox. " "Returns a summary of recent messages." ) args_schema: Type[BaseModel] = CheckInboxSchema def _run(self, inbox_id: str) -> str: resp = requests.get( f"{AGENTSEND_BASE}/inboxes/{inbox_id}/messages", headers={ "Authorization": f"Bearer {AGENTSEND_API_KEY}" }, ) resp.raise_for_status() messages = resp.json().get("messages", []) if not messages: return "No new messages in inbox." lines = [] for msg in messages[:5]: lines.append( f"From: {msg['from']}, " f"Subject: {msg['subject']}, " f"Thread: {msg['threadId']}" ) return "\n".join(lines)
Building a Crew with Email
With the tools defined, you can assign them to agents in a crew. Here is a complete example of a customer support crew where one agent handles incoming emails and another researches solutions:
from crewai import Agent, Task, Crew from crewai_email_tool import SendEmailTool, CheckInboxTool # Create tool instances send_email = SendEmailTool() check_inbox = CheckInboxTool() # Define agents support_agent = Agent( role="Customer Support Agent", goal="Read customer emails and send helpful replies", backstory="You are a senior support engineer who handles " "customer inquiries via email with expertise and empathy.", tools=[send_email, check_inbox], verbose=True, ) researcher = Agent( role="Knowledge Base Researcher", goal="Find solutions to customer problems", backstory="You search internal documentation and knowledge bases " "to find answers to customer questions.", verbose=True, ) # Define tasks check_email_task = Task( description="Check inbox inbox_abc123 for new support emails. " "Summarize each request.", expected_output="A list of customer requests with details", agent=support_agent, ) reply_task = Task( description="For each customer request, draft and send a helpful reply " "using inbox inbox_abc123. Include the thread_id to keep " "the conversation threaded.", expected_output="Confirmation that all replies have been sent", agent=support_agent, ) # Run the crew crew = Crew( agents=[support_agent, researcher], tasks=[check_email_task, reply_task], verbose=2, ) result = crew.kickoff() print(result)
When the crew runs, the support agent checks the inbox for new messages, processes each one, and sends replies through AgentSend. The thread ID ensures replies appear as part of the original email conversation in the customer's inbox.
Tip: Assign the email tools only to the agent that needs them. In a multi-agent crew, keeping email capabilities on a single "communicator" agent prevents multiple agents from sending conflicting replies to the same thread.
Handling Incoming Email with Webhooks
For real-time email processing, configure an AgentSend webhook to POST incoming messages to your server. When a new email arrives, your webhook handler can trigger a crew kickoff:
from fastapi import FastAPI, Request app = FastAPI() @app.post("/webhook/email") async def handle_incoming(request: Request): payload = await request.json() message = payload["message"] # Dynamically create a task for this specific email task = Task( description=( f"Reply to email from {message['from']}. " f"Subject: {message['subject']}. " f"Body: {message['text']}. " f"Use thread_id {message['threadId']} " f"and inbox inbox_abc123." ), expected_output="Reply sent confirmation", agent=support_agent, ) crew = Crew(agents=[support_agent], tasks=[task]) crew.kickoff() return {"status": "processed"}
Multi-Agent Email Workflows
CrewAI's strength is multi-agent collaboration, and email workflows benefit enormously from this pattern. You can design crews where different agents handle different stages of an email interaction:
- Triage agent: Reads incoming emails and classifies them by urgency and topic.
- Research agent: Looks up relevant information based on the email content.
- Drafting agent: Composes a reply using the research results.
- Quality agent: Reviews the draft for tone, accuracy, and completeness before sending.
- Send agent: Delivers the approved reply via AgentSend.
This pipeline ensures every outgoing email is well-researched, well-written, and reviewed before it reaches the recipient. Each agent focuses on what it does best, and the email tool is only exposed to the agent that actually needs to send.
Next Steps
- Create role-specific inboxes so each crew member has its own email identity.
- Add memory by storing thread IDs in CrewAI's built-in memory, enabling long-running email conversations across crew runs.
- Use custom domains to send from professional addresses like support@yourdomain.com.
- Build escalation flows where the crew automatically escalates unresolvable issues to human agents via a separate email thread.
Frequently Asked Questions
Can CrewAI agents send and receive email?
Yes. By creating a custom CrewAI tool that wraps AgentSend's REST API, any agent in a CrewAI crew can send emails, check for incoming messages, and manage threaded conversations. The tool works with any CrewAI agent role and integrates into existing crew workflows.
How do I add email to a CrewAI agent?
Subclass CrewAI's BaseTool class and implement the _run method to call AgentSend's API. Then pass the tool to your Agent definition. The agent can invoke the tool during task execution to send or check email without any additional configuration.
Can different agents in a crew share an inbox?
Yes. Multiple CrewAI agents can use the same AgentSend inbox, or you can create separate inboxes for each agent role. For example, a support agent and an escalation agent could share an inbox, with routing logic determining which agent handles each message.
Give Your CrewAI Agents Email
Free tier available. No credit card required. Add email to your CrewAI crew in under 5 minutes.
Start for Free →