# Using Nylas and OpenAI to triage email

[Canonical article](https://www.ashryan.io/writing/nylas-openai-triage-email/)

Published: 2023-04-19

Solving email inbox triage with Nylas APIs and OpenAI GPT APIs.

[In my previous post about using AI in DevRel](https://www.ashryan.io/writing/experimenting-with-ai-in-devrel/), I mentioned a sample code repo I built with Nylas APIs and OpenAI APIs.

In this post, I will walk through that code to demonstrate how simple it can be to get started with both sets of APIs.

You can see [the repo on the Nylas Samples GitHub org](https://github.com/nylas-samples/node-chatgpt-email-spam-detect?ref=ashryan.io).

## The concept

Despite all the advances in email sorting technologies over the years, I still find it difficult to open Gmail and just know what deserves my attention. Even with rules, filters, and Gmail’s priority inbox, I find that I’m visually hunting through emails to get to the signal within the noise.

This seems like a problem AI could solve.

## The flow

The [Node.js script](https://github.com/nylas-samples/node-chatgpt-email-spam-detect?ref=ashryan.io) I put together is a simple demonstration of how to wade into using AI to triage email.

The script flow:

1. \[Nylas Email API] Pull in the latest emails from a user’s inbox
2. \[OpenAI API] Prompt GPT to triage email based on relevant data
3. \[Node.js app] Receive the triage results and pass to the user

And that’s it.

We’ll talk about ways this could get really useful later. For now, let’s have a look at the code.

## The prereqs

To keep focus on the core purpose of the code, I’ll jump past explaining any prereqs and setup for the repo.

But if you do want a hand in getting started, here are some resources to check out:

- [the GitHub repo for this sample](https://github.com/nylas-samples/node-chatgpt-email-spam-detect?ref=ashryan.io)
- [the Nylas Node.js SDK guide](https://developer.nylas.com/docs/sdks/node/?ref=ashryan.io)
- [the OpenAI API docs](https://platform.openai.com/docs/introduction?ref=ashryan.io)

## The code

Let’s go in order from our flow list above:

> \[Nylas Email API] Pull in the latest emails from a user’s inbox

We start by getting a list of messages from an email account (Gmail in my case, but it could be a host of other providers including Microsoft Outlook and Exchange).

Note how the following code is quite simply asking for the 10 latest messages and returning a list (as a JavaScript array). I’m not doing anything with the data at this stage of the script, just returning.

```plaintext
// Get messages from Nylas
const getMessageList = async () => {
  try {
    const messageList = await nylas.messages.list({ limit: 10 });

    console.log(`Found ${messageList.length} messages in your inbox...`);

    return messageList;
  } catch (err) {
    console.error("Error:\n", err);
  }
};
```

Next up from our flow list:

> \[OpenAI API] Pass relevant email data to GPT for triaging

I tackled this step in 2 parts:

1. Loop through the list, and pass each Nylas email message object to a helper function
2. In the helper function, extract data from each email message and pass it to GPT with a prompt that instructs the AI how to triage

I’ll skip going into depth on the loop, but you can see that code in the `classifyMessages()` function in the repo.

Within said loop, each single `message` is passed to the `classifyMessage()` function shown below. Note that the `message` argument is the email message object that came back from the Nylas API—I’m simply deconstructing it in the function parameter as `from`, `subject`, and `snippet`, all properties in the Nylas email message object.

```plaintext
// Pass a message to GPT
// Get a string value for whether the user should read and why
const classifyMessage = async ({ from, subject, snippet }) => {
  const response = await openai.createChatCompletion({
    model: "gpt-3.5-turbo",
    messages: [
      {
        role: "system",
        content: `You're an email assistant and you help me figure out which emails are something I should read and which are not worth my time.
        The following are categories I want to avoid: spam, newsletters, sales messages, junk.
        Answer with "Yes" or "No", then a comma followed by a one-word category to demonstrate your reason.
        Is the following message something I should read?
        From: ${from}
        Subject: ${subject}
        Snippet: ${snippet}`,
      },
    ],
  });

  return response.data.choices[0].message.content;
};
```

The OpenAI API returns a response with a lot of good data, but for this simple example, we only want the response to the prompt.

For this prompt with GPT 3.5 Turbo, that response will be a string formatted as “Yes, {category}” or “No, {category}”. The “Yes” or “No” indicates whether the message is likely to be important to you, the user.

## The prompt

You can see the prompt in the code above, but I’ll format it for easier viewing here:

> You’re an email assistant and you help me figure out which emails are something I should read and which are not worth my time.
>
> The following are categories I want to avoid: spam, newsletters, sales messages, junk.
>
> Answer with “Yes” or “No”, then a comma followed by a one-word category to demonstrate your reason.
>
> Is the following message something I should read?
>
> From: ${from} Subject: ${subject} Snippet: ${snippet}\`

The responses from GPT will be along the lines of “Yes, personal” or “No, newsletter”.

## The output

When the cycle is complete, the script will put the following output in your terminal for each email:

```plaintext
# date, subject, category, and message ID
[4/8/YYYY] Here's an important message - Yes, security. (1yz01ivndb)
[4/7/YYYY] Here's an email subject - No, newsletters. (2wwqyz01ivnmzb)
[4/6/YYYY] Another subject - No, spam. (241ahbvvivnmzb)
```

So in this example, I’d have one email message worth looking at according to GPT.

## Where to take it from here

This is obviously a basic demonstration, but you can imagine where this could go:

- Give the prompt the option to be “unsure”
- Let the user “train” the prompt by storing an allow/block list to add to the prompt
- Expose the results in a graphical email client
- Use the results to categorize emails in Gmail/Outlook/Exchange
- Expand on the list of categories to triage

The list goes on and on. I challenge you to explode this into something fun and useful.
