Introduction
By no means would have the inventor of electronic mail –Ray Tomlinson– considered how far this piece of tech would attain sooner or later. In the present day, electronic mail is the prime pillar of company {and professional} communications and is utilized in innumerable aspects of the working world. And this has propelled the creation of a complete set of instruments and plugins to optimise your electronic mail inbox! With the appearance of generative AI, the most recent speak on the town is concerning the widespread use of AI Brokers to optimise emails. On this weblog, I’ll clarify the craft of automating electronic mail sorting and labelling by constructing brokers utilizing crewAI.
Overview
- Learn to give your purposes entry to your Gmail utilizing Google Cloud Console’s OAuth 2.0
- Perceive the code and construct an agent that makes use of an LLM to learn and categorise mails into pre-defined classes.
- Learn to automate the method of electronic mail sorting and labelling utilizing crewAI by merely operating a Python script.
Understanding the Context
If you’re not dwelling underneath a rock and have an electronic mail handle, you know the way flooded your inbox tends to get after an evening’s sleep. Advertising and marketing emails, private messages, skilled communications, and so forth, particularly in case you are a busy working skilled. The frustration of a cluttered inbox will be felt within the picture beneath:

The worst half is that even after creating related labels within the electronic mail (Gmail within the case of the creator), one has to take the time to assign these emails to the right label. With the developments in generative AI, shouldn’t it’s a lot simpler to kind and label emails in Gmail? Why don’t we scale back the steps of sorting related emails to a single click on?
Let me illustrate how we will use crewAI to construct an LLM agent and automate this course of. The tip purpose is mechanically sorting our unread emails utilizing crewAI into three classes: ‘Reply Instantly’, ‘No Reply’, and ‘Irrelevant’. We then add these categorised emails to Gmail and the respective labels.
Observe: We manually created these labels – ‘Reply Instantly’, ‘No Reply’, and ‘Irrelevant’ – in Gmail.

Additionally Learn: Prime 10 AI E-mail Automation Instruments to Use in 2024
Steps for Google Authentication
Earlier than we leap to the code to kind emails in Gmail, it’s good to allow the Gmail API and generate the OAuth 2.0 credentials. This may assist your electronic mail sorting agentic system entry your emails. Listed below are the steps to do that.
Step 1: Create a New Venture in Google Cloud
Step one in a Google authentication course of is to create a brand new undertaking in Google Cloud.
- 1. Go to the Google Cloud console and log in together with your electronic mail handle. First-time customers should create an account.
- Then choose “New Venture” within the dropdown, give it a reputation, and click on Create. This undertaking can have the required API-related configurations. Whereas including the brand new undertaking, select your organisation title as the situation, as now we have chosen analyticsvidhya.com



Step 2: Allow Gmail API
The subsequent step is to allow Gmail API.
- 1. Click on the Navigation Menu from the console’s Dashboard to Discover and Allow APIs underneath “Getting Began.“


- On the left aspect of the display screen, choose Library and seek for “Gmail API.” Then, please allow it for the undertaking you created.



Step 3: Set Up OAuth 2.0 Credentials
The final step in Google Authentication is to arrange OAuth 2.0 credentials.
- First, arrange the OAuth consent display screen underneath APIs & Providers >. Click on Configure Consent Display.


- Select the sort (e.g., Exterior for apps utilized by anybody). We selected Inner since we’re utilizing it for our electronic mail ID. Then Click on Create.

- Identify your app and add the Person assist electronic mail and Developer contact info. Ideally, it’s best to add your work electronic mail ID. Click on SAVE AND CONTINUE on the backside of the display screen.

- Now, Outline the scopes within the consent display screen setup. Scopes within the context of Google Console dictate what the API can entry. For email-related duties, you’ll want the next: ‘https://www.googleapis.com/auth/gmail.modify‘. This scope will permit our electronic mail sorting and labelling system to ship and modify emails in your Gmail account.
Click on on ADD OR REMOVE SCOPES after which choose the scope talked about above.


- Click on on Replace. You’ll be able to see the scope has been added. Press SAVE AND CONTINUE.

- Undergo the abstract and click on BACK TO DASHBOARD.

Step 4: Creating Credentials
- Now, select Credentials underneath APIs & Providers and click on CREATE CREDENTIALS.


- For native growth, we’ll select the Desktop App choice. After which press CREATE.

Step 5: Obtain the Credential.json
- Now obtain the JSON file and put it aside domestically at your most popular location.

Python Code for Sorting and Labelling Emails Utilizing crewAI
We’ll now start coding the e-mail sorting and labelling system utilizing crewAI. Guarantee you may have put in crewAI and utils.
Set up crewAI
#pip set up crewai==0.28.8 crewai_tools==0.1.6
#pip set up utils
#pip set up google-auth-oauthlib
#pip set up google-api-python-client
Import Libraries
Now, we’ll import the related libraries.
# Import commonplace libraries
import json # For working with JSON information
import os # For interacting with the working system
import os.path # For manipulating filesystem pathnames
import pickle # For serializing and deserializing Python objects
# Import Google API shopper libraries for authentication and API requests
from google.auth.transport.requests import Request # For making authenticated HTTP requests
from google.oauth2.credentials import Credentials # For dealing with OAuth 2.0 credentials
from google_auth_oauthlib.circulation import InstalledAppFlow # For managing OAuth 2.0 authorization flows
from googleapiclient.discovery import construct # For setting up a Useful resource object for interacting with an API
from googleapiclient.errors import HttpError # For dealing with HTTP errors from API requests
# Import customized libraries (assuming these are your individual modules or third-party packages)
from crewai import Agent, Process, Crew # For managing brokers, duties, and crews
from crewai_tools import Instrument # For extra instruments and utilities
# Import pandas library
import pandas as pd # For information manipulation and evaluation
Entry to LLM
After this, we’ll give our electronic mail sorter and labeller entry to an LLM. I’m utilizing the GPT 4o mannequin for this activity, however you possibly can select the LLM of your alternative.
# Set OpenAI API key
os.environ['OPENAI_API_KEY'] = "Your API Key"
os.environ["OPENAI_MODEL_NAME"] = 'Mannequin Identify’'
Now, we’ll create the EmailCollector activity, which makes use of Google’s API to work together with Gmail and fetch unread emails.
class EmailCollector:
def __init__(self):
self.creds = None
self._authenticate()
def _authenticate(self):
SCOPES = ['https://www.googleapis.com/auth/gmail.modify'] # Use modify to replace emails
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
self.creds = pickle.load(token)
if not self.creds or not self.creds.legitimate:
if self.creds and self.creds.expired and self.creds.refresh_token:
self.creds.refresh(Request())
else:
circulation = InstalledAppFlow.from_client_secrets_file(
'/Customers/admin/Desktop/Blogs/credentials.json', SCOPES)
self.creds = circulation.run_local_server(port=0)
with open('token.pickle', 'wb') as token:
pickle.dump(self.creds, token)
def get_unread_emails(self):
service = construct('gmail', 'v1', credentials=self.creds)
outcomes = service.customers().messages().listing(userId='me', q='is:unread').execute()
messages = outcomes.get('messages', [])
email_list = []
if not messages:
print('No unread emails discovered.')
else:
for message in messages:
msg = service.customers().messages().get(userId='me', id=message['id'], format="full").execute()
email_list.append(msg)
return email_list
Code Clarification
Here’s what the above code does:
- First, the EmailCollector initialises with self.creds = None and calls the _authenticate methodology to deal with authentication.
- Then, the _authenticate methodology checks if a token.pickle file exists. If it exists, it hundreds the saved credentials from the file utilizing pickle.
- If credentials are expired or lacking, it checks if a refresh token is offered to refresh them. If not, it initiates an OAuth circulation utilizing InstalledAppFlow, prompting the person to log in.
- After acquiring the credentials (new or refreshed), they’re saved to the token pickle for future use.
- The get_unread_emails methodology retrieves an inventory of unread emails after connecting to the Gmail API utilizing the authenticated credentials.
- It loops by every unread electronic mail, retrieves full message particulars, and shops them within the email_list.
- Lastly, the listing of unread emails is returned for additional use.
Create Mail Knowledge Gatherer
Now, we’ll create the mailDataGatherer() perform to assemble the unread emails and save them as a .csv file.
def mailDataGatherer():
# Create the E-mail Collector occasion
email_collector_instance = EmailCollector()
# Get unread emails
email_list = email_collector_instance.get_unread_emails()
# Put together information for DataFrame
emails_data = []
for electronic mail in email_list:
topic = subsequent(header['value'] for header in electronic mail['payload']['headers'] if header['name'] == 'Topic')
physique = ''
if 'components' in electronic mail['payload']:
for half in electronic mail['payload']['parts']:
if half['mimeType'] == 'textual content/plain':
physique = half['body']['data']
break
else:
physique = electronic mail['payload']['body']['data']
import base64
physique = base64.urlsafe_b64decode(physique).decode('utf-8')
emails_data.append({
'Topic': topic,
'Physique': physique
})
# Create a DataFrame
df = pd.DataFrame(emails_data)
# Save DataFrame to CSV
df.to_csv('unread_emails.csv', index=False)
df.fillna("",inplace=True)
# Print the DataFrame
return df
Code Clarification
Right here is an evidence of the above code:
- First, the perform handles authentication and retrieves unread emails utilizing an occasion of the EmailCollector class.
- Then, we fetch the unread emails utilizing the get_unread_emails() methodology from the EmailCollector occasion.
- After that, we course of the e-mail information contained in the loop, which is
- The perform extracts the topic from the e-mail headers for every electronic mail within the listing.
- It checks the e-mail’s physique, decoding it from base64 format to get the precise textual content.
- It collects each the topic and physique of the emails.
- We’ll retailer the processed electronic mail information (topic and physique) in a Pandas DataFrame.
- The DataFrame is saved as a CSV file known as unread_emails.csv, and any lacking values are crammed with empty strings.
- Lastly, the perform returns the DataFrame for additional use or viewing.
Now, we’ll create the extract_mail_tool for our agent utilizing the Instrument performance inside crewAI. This device will use the emaiDataGatherer perform to assemble the topic and physique of the unread electronic mail.
# Create the Extract Topics device
extract_mail_tool = Instrument(
title="mailDataGatherer",
description="Get all the themes and physique content material of unread emails.",
func=mailDataGatherer
)
Now, we’ll create a perform that takes within the JSON illustration of the unread emails. It then decodes the emails and labels the corresponding emails in our Gmail inbox as per the pre-defined classes – ‘Reply Instantly’, ‘No Reply’, and ‘Irrelevan.t’
def push_mail_label(dfjson):
emails = pd.DataFrame(json.hundreds(dfjson.substitute("```","").substitute("json","")))
SCOPES = ['https://www.googleapis.com/auth/gmail.modify'] # Use modify to replace emails
#Change the title and path of your file beneath accordingly
circulation = InstalledAppFlow.from_client_secrets_file(
'/Customers/admin/Desktop/Blogs/credentials.json', SCOPES)
creds = circulation.run_local_server(port=0)
service = construct('gmail', 'v1', credentials=creds)
labels = service.customers().labels().listing(userId='me').execute().get('labels', [])
label_map = {label['name']: label['id'] for label in labels}
def get_or_create_label(label_name):
if label_name in label_map:
return label_map[label_name]
else:
# Create new label if it would not exist
new_label = {
'labelListVisibility': 'labelShow',
'messageListVisibility': 'present',
'title': label_name
}
created_label = service.customers().labels().create(userId='me', physique=new_label).execute()
return created_label['id']
# Map the classes to Gmail labels, creating them if they do not exist
category_label_map = {
"Reply Instantly": get_or_create_label("Reply Instantly"),
"No Reply": get_or_create_label("No Reply"),
"Irrelevant": get_or_create_label("Irrelevant")
}
for i in vary(emails.form[0]):
topic = emails.iloc[i]['Subject']
physique = emails.iloc[i]['Body']
class = emails.iloc[i]['Category']
search_query = f'topic:("{topic}")'
outcomes = service.customers().messages().listing(userId='me', q=search_query).execute()
message_id = outcomes['messages'][0]['id'] # Get the primary matching message ID
label_id = category_label_map.get(class, None)
# Apply label primarily based on class
if label_id:
service.customers().messages().modify(
userId='me',
id=message_id,
physique={
'addLabelIds': [label_id],
'removeLabelIds': [] # Optionally add label removing logic right here
}
).execute()
print(f'Up to date electronic mail with topic: {topic} to label: {class}')
else:
print(f'Class {class} doesn't match any Gmail labels.')
return
How does this perform work?
The perform works as follows:
- The dfjson string is first cleaned of additional characters. It’s then parsed right into a Pandas DataFrame that incorporates columns like Topic, Physique, and Class for every electronic mail.
- Then, with Google OAuth 2.0, the perform authenticates with Gmail by InstalledAppFlow utilizing the gmail.modify scope. This permits it to change emails (including labels in our case).
- Subsequent, the perform retrieves all current Gmail labels from the person’s account and shops them in a label_map dictionary (label title to label ID).
- After that, the get_or_create_label() perform checks if a label already exists. If not, it creates a brand new one utilizing the Gmail API.
- Subsequent, it maps the classes within the electronic mail information to their respective Gmail labels (Reply Instantly, No Reply, Irrelevant), creating them if essential.
- For every electronic mail, the perform searches Gmail for an identical message by the topic, retrieves the message ID and applies the corresponding label primarily based on the class.
- On the finish, the perform prints a message indicating success or failure for every electronic mail it processes.
Defining the E-mail Sorting Agent
This agent will classify the unread emails into three classes now we have outlined. The agent makes use of the extract_mail_tool to entry the emails, which makes use of the mailDataGatherer() perform to get the emails. Since this agent makes use of LLM, you need to give correct directions on what is predicted to be executed. For instance, one express instruction I’ve added is concerning the sort of mail that have to be included in each bit of content material. You’ll be able to learn the directions additional within the agent’s backstory parameter.
sorter = Agent(
function="E-mail Sorter",
purpose="Clasify the emails into one of many 3 classes offered",
instruments=[extract_mail_tool], # Add instruments if wanted
verbose=True,
backstory=(
"You might be an professional private assistant working for a busy company skilled."
"You might be dealing with the private electronic mail account of the CEO."
"You have got been assigned a activity to categorise the unread emails into one of many three classes."
"Checklist of the three classes is : ['Reply Immediately', 'No Reply' and 'Irrelevant']"
"'Reply Instantly' ought to embody unread emails from inside the group and outdoors. This generally is a normal inquiry, question and calender invitations."
"'No Reply' contains unread emails the place somebody is letting me know of some growth inside the firm. It additionally contains Newsletters that I've subscribed to."
"'Irrelevant' incorporates unread emails which might be from exterior companies advertising and marketing there merchandise."
"You'll be able to apply your individual intelligence whereas sorting the unread emails."
"You get the information of unread mails in a pandas dataframe utilizing the device mailDataGatherer."
"You're going to get 'Topic' and 'Physique' columns within the dataframe returned by device."
"You must classify the mails on foundation of topic and physique and name it 'Class'."
"There isn't a device which you need to use for classification. Use your individual intelligence to do it."
"Lastly you come back a json with 3 keys for every mail: 'Topic', 'Physique', 'Class'"
)
)
Observe that now we have set verbose = True, which helps us view how the mannequin thinks.
Outline the Process
Now, we’ll outline the Process that the sorter agent will carry out. We now have added the precise listing of duties, which you’ll learn within the code beneath.
# Process for Sorter: Kind Emails
sort_task = Process(
purpose="Kind the categorised emails into: ['Reply Immediately', 'No Reply' and 'Irrelevant'] ",
description= "1. At first, get the dataframe of unread emails utilizing the 'mailDataGatherer'."
"2. Don't use the device once more upon getting obtained the topic and physique"
"3. Classify the emails into one of many above classes: ['Reply Immediately', 'No Reply' and 'Irrelevant']."
"4. There isn't a device which you need to use for classification. Use the directions and your individual intelligence to do it."
"5. Lastly, return a json with three keys for every row: ['Subject', 'Body', 'Category']"
"6. All of the emails should strictly be categorised into one in all above three classes solely.",
expected_output = "A json file with all of the unread emails. There needs to be 3 keys for every mail- Topic, Physique and Class ",
agent=sorter,
async_execution=False
)
Allow Collaboration in CrewAI
Subsequent, we’ll use crewAI’s performance to allow collaboration and let the sorter agent carry out the duties outlined within the sort_task perform above.
# Create the Crew
email_sorting_crew = Crew(
brokers=[sorter],
duties=[sort_task],
verbose=True
)
Lastly, we'll kickoff our crew to let it kind the unread emails mechanically and save the output within the consequence variable.
# Operating the crew
consequence = email_sorting_crew.kickoff()
Since verbose = True for all parts in our agent, we get to see how our agent performs.


Now, we push this consequence into our Gmail utilizing the push_mail_label() perform.
#push the outcomes
push_mail_label(consequence)
Observe that all through the execution, you can be twice redirected to a special window to offer the required permissions. As soon as the code can reaccess the emails, the unread emails will likely be pushed underneath the related labels.
And Voila! We now have the emails with labels connected. For privateness, I cannot show my whole inbox.


Conclusion
Bear in mind the frustration we mentioned earlier within the weblog? Nicely, crewAI’s electronic mail sorting and labelling agentic system permits us to avoid wasting a major period of time.
With LLM brokers, the chances of activity automation are limitless. It is determined by how nicely you suppose and construction your agentic system. As a subsequent step, you possibly can strive constructing an agent that checks whether or not the primary agent’s categorisation is right. Or, you too can strive creating an agent that prepares an electronic mail for the ‘Reply Instantly’ class and pushes it to the drafts in Gmail. Sounds bold? So, go on and get your palms soiled. Pleased studying!!
Ceaselessly Requested Questions
A. crewAI is an open-source Python framework that helps creating and managing multi-agent AI programs. Utilizing crewAI, you possibly can construct LLM-backed AI brokers that may autonomously make selections inside an surroundings primarily based on the variables current.
A. Sure! You need to use crewAI to construct LLM-backed brokers to automate electronic mail sorting and labelling duties.
A. Relying in your agentic system construction, you need to use as many brokers as you prefer to kind emails in Gmail. Nonetheless, it is strongly recommended that you just construct one agent per activity.
A. CrewAI can carry out numerous duties, together with sorting and writing emails, planning tasks, producing articles, scheduling and posting social media content material, and extra.
A. Since GenAI brokers utilizing crewAI make selections utilizing LLMs, it reduces the requirement to allocate human sources to undergo emails and make selections.
A. To automate electronic mail sorting utilizing crewAI, you need to outline the brokers with a descriptive backstory inside the Agent perform, outline duties for every agent utilizing the Process performance, after which create a Crew to allow totally different brokers to collaborate.