{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "aRDQQophCLQs"
   },
   "source": [
    "# AI email agent using Composio"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "bZVu2lrqCLQu"
   },
   "source": [
    "This notebook demonstrates how to create an AI Email agent using Composio’s Gmail tool with autogen to create an agent that will automatically respond to emails based on provided instructions.\n",
    "\n",
    "[Composio](https://composio.dev/) allows an AI agent or LLM to easily connect to apps like Gmail, Slack, Trello etc. The key features of Composio are:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "UI78uqxyCLQu"
   },
   "source": [
    "- Repository of Tools: Composio allows LLMs and agents to integrate with 100+ apps (Github, Salesforce, File Manager, Code Execution & More) to perform actions & subscribe to triggers(events).\n",
    "\n",
    "- Frameworks & LLM Agnostic: Composio provides out of box support for 10+ popular agentic frameworks and works with all the LLM providers using function calling.\n",
    "\n",
    "- Managed Auth: Composio helps manage authentication for all users/agents from a single dashboard."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Visit [Composio Docs](https://docs.composio.dev/introduction/intro/overview) to learn more."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "16kFQX0kCLQv"
   },
   "source": [
    "The notebook demonstrates how to create a Gmail integration with Composio, set up a trigger for new emails, initialize agents with tools and finally we'll see the agent in action."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ixe3kpQrCLQv"
   },
   "source": [
    "````{=mdx}\n",
    ":::info Requirements\n",
    "Some extra dependencies are needed for this notebook, which can be installed via pip:\n",
    "\n",
    "```bash\n",
    "pip install autogen-agentchat~=0.2 composio-autogen\n",
    "```\n",
    "\n",
    "For more information, please refer to the [installation guide](/docs/installation/).\n",
    ":::\n",
    "````"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "XK6_H749CLQv"
   },
   "source": [
    "## Composio Setup\n",
    "\n",
    "To get started with using Composio's Gmail tool, we need to create an integration between Composio and Gmail. This can be done using a simple command -"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "-1XLfYJRCLQv"
   },
   "outputs": [],
   "source": [
    "!composio add gmail"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "T-YxALkYCLQw"
   },
   "source": [
    "To set up a trigger(basically a listener) for new emails -"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "YUzcCGaCCLQw"
   },
   "outputs": [],
   "source": [
    "!composio triggers enable gmail_new_gmail_message"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "yTM8eqE2CLQw"
   },
   "source": [
    "This enables the `gmail_new_gmail_message` trigger, which is fired when a new email is received in the connected account."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "GqlJ06y8CLQw"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from composio_autogen import Action, ComposioToolSet\n",
    "\n",
    "from autogen.agentchat import AssistantAgent, UserProxyAgent\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"YOUR_API_KEY\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BHuqMynBCLQw"
   },
   "source": [
    "## Initialize agents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "VzEYr6uuCLQw"
   },
   "outputs": [],
   "source": [
    "llm_config = {\"config_list\": [{\"model\": \"gpt-4o\", \"api_key\": os.environ.get(\"OPENAI_API_KEY\")}]}\n",
    "\n",
    "# Prompt for email assistant\n",
    "email_assistant_prompt = \"\"\"\n",
    "    You are an AI email assistant specialized in drafting replies to emails.\n",
    "    You create appropriate and professional replies to emails based on the content of the email.\n",
    "    After executing the GMAIL_REPLY_TO_THREAD action and sending the email to the user, respond with TERMINATE.\n",
    "\"\"\"\n",
    "\n",
    "# Initialize AssistantAgent\n",
    "chatbot = AssistantAgent(\n",
    "    \"chatbot\",\n",
    "    system_message=email_assistant_prompt,\n",
    "    llm_config=llm_config,\n",
    ")\n",
    "\n",
    "# Initialize UserProxyAgent\n",
    "user_proxy = UserProxyAgent(\n",
    "    \"user_proxy\",\n",
    "    is_termination_msg=lambda x: x.get(\"content\", \"\") and \"TERMINATE\" in x.get(\"content\", \"\"),\n",
    "    human_input_mode=\"NEVER\",\n",
    "    code_execution_config=False,\n",
    "    llm_config=llm_config,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6SB0HFZ7CLQw"
   },
   "source": [
    "## Initialize Composio's Toolset\n",
    "\n",
    "Now, we initialize Composio's toolset and get the tools and actions we need for the agent. Then, we register the tools with the `UserProxyAgent`.\n",
    "\n",
    "The agent can then call the tools using function calling."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "_nosEvgxCLQx"
   },
   "outputs": [],
   "source": [
    "# Initialize Composio Toolset\n",
    "composio_toolset = ComposioToolSet()\n",
    "\n",
    "# Get the required tools and register them with the agents\n",
    "email_tools = composio_toolset.register_tools(\n",
    "    caller=user_proxy,\n",
    "    executor=chatbot,\n",
    "    actions=[\n",
    "        Action.GMAIL_REPLY_TO_THREAD,\n",
    "    ],\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "kFkkMIIeCLQx"
   },
   "source": [
    "Here, we get the `GMAIL_REPLY_TO_THREAD` action, which is just a function that can be used to reply to an email. We'll be using this action to reply to emails automatically when they arrive."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ZsgE3qm9CLQx"
   },
   "source": [
    "## Create trigger listener"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "fU6TmawGCLQx"
   },
   "source": [
    "Now, we create a listener for the trigger that we created above. This listener will listen for new emails and when a new email arrives, it'll provide data associated with the email like the sender email, email content etc. This data will be used by the attached callback function to invoke the agent and to send a reply to the email."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `@listener.callback` decorator registers the function it decorates as a callback for a specific event trigger, in this case, when a new Gmail message is received (`GMAIL_NEW_GMAIL_MESSAGE`). It listens for the specified trigger and invokes the decorated function (`callback_new_message`) when the event occurs.\n",
    "\n",
    "After extracting the relevant data from the trigger payload, we start a conversation between `user_proxy` and `chatbot` to send a reply to the received email."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "aDTm1tQECLQx",
    "outputId": "8aa5ab9a-9526-4287-e8f1-7b8ac9cfb0b3"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:composio.utils.shared:Creating trigger subscription\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Subscribed to triggers!\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:composio.utils.shared:Received trigger event with trigger ID: ea36d63f-5cc9-4581-9a19-b647e7468697 and trigger name: GMAIL_NEW_GMAIL_MESSAGE\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "user_proxy (to chatbot):\n",
      "\n",
      "\n",
      "        Analyze the email content and create an appropriate reply. \n",
      "                a. The email was received from John Doe <example_email@gmail.com> \n",
      "                b. The content of the email is: hey, how are you?\n",
      " \n",
      "                c. The thread id is: 1922811a78db4....\n",
      "        \n",
      "\n",
      "--------------------------------------------------------------------------------\n",
      "chatbot (to user_proxy):\n",
      "\n",
      "GMAIL_REPLY_TO_THREAD thread_id: 1922811a78db4... message: \n",
      "Hi John,\n",
      "\n",
      "I'm doing well, thank you! How about you?\n",
      "\n",
      "Best,\n",
      "[Your Name]\n",
      "\n",
      "--------------------------------------------------------------------------------\n",
      "user_proxy (to chatbot):\n",
      "\n",
      "***** Suggested tool call (call_qGQzJ6XgyO8LKSSFnwkQhSCz): GMAIL_REPLY_TO_THREAD_8c4b19f45c *****\n",
      "Arguments: \n",
      "{\"thread_id\":\"1922811a78db4...\",\"message_body\":\"Hi John,\\n\\nI'm doing well, thank you! How about you?\\n\\nBest,\\n[Your Name]\",\"recipient_email\":\"example_email@gmail.com\"}\n",
      "*************************************************************************************************\n",
      "\n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      ">>>>>>>> EXECUTING FUNCTION GMAIL_REPLY_TO_THREAD_8c4b19f45c...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:composio.utils.shared:Executing `GMAIL_REPLY_TO_THREAD` with params={'thread_id': '1922811a78db4...', 'message_body': \"Hi John,\\n\\nI'm doing well, thank you! How about you?\\n\\nBest,\\n[Your Name]\", 'recipient_email': 'example_email@gmail.com'} and metadata={} connected_account_i...\n",
      "INFO:composio.utils.shared:Got response={'successfull': True, 'data': {'response_data': {'id': '1922811c1b3ed...', 'threadId': '1922811a78db4...', 'labelIds': ['SENT']}}, 'error': None} from action=<composio.client.enums._action.Action object at 0x7d50554c4310> with params={'thread_...\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "chatbot (to user_proxy):\n",
      "\n",
      "chatbot (to user_proxy):\n",
      "\n",
      "***** Response from calling tool (call_qGQzJ6XgyO8LKSSFnwkQhSCz) *****\n",
      "{\"successfull\": true, \"data\": {\"response_data\": {\"id\": \"1922811c1b3ed...\", \"threadId\": \"1922811a78db4...\", \"labelIds\": [\"SENT\"]}}, \"error\": null}\n",
      "**********************************************************************\n",
      "\n",
      "--------------------------------------------------------------------------------\n",
      "user_proxy (to chatbot):\n",
      "\n",
      "I've replied to the email with the following message:\n",
      "\n",
      "Hi John,\n",
      "\n",
      "I'm doing well, thank you! How about you?\n",
      "\n",
      "Best,\n",
      "[Your Name]\n",
      "\n",
      "Is there anything else you need?\n",
      "\n",
      "--------------------------------------------------------------------------------\n",
      "chatbot (to user_proxy):\n",
      "\n",
      "TERMINATE\n",
      "\n",
      "--------------------------------------------------------------------------------\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Create a trigger listener\n",
    "listener = composio_toolset.create_trigger_listener()\n",
    "\n",
    "\n",
    "@listener.callback(filters={\"trigger_name\": \"GMAIL_NEW_GMAIL_MESSAGE\"})\n",
    "def callback_new_message(event) -> None:\n",
    "    # Get the payload and extract relevant information\n",
    "    payload = event.payload  # Email payload\n",
    "    thread_id = payload.get(\"threadId\")\n",
    "    message = payload.get(\"messageText\")\n",
    "    sender_mail = payload.get(\"sender\")\n",
    "    if sender_mail is None:\n",
    "        print(\"No sender email found\")\n",
    "        return\n",
    "\n",
    "    analyze_email_task = f\"\"\"\n",
    "        Analyze the email content and create an appropriate reply.\n",
    "                a. The email was received from {sender_mail}\n",
    "                b. The content of the email is: {message}\n",
    "                c. The thread id is: {thread_id}.\n",
    "        \"\"\"\n",
    "    # Initiate the conversation\n",
    "    res = user_proxy.initiate_chat(chatbot, message=analyze_email_task)\n",
    "    print(res.summary)\n",
    "\n",
    "\n",
    "print(\"Subscribed to triggers!\")\n",
    "# Start listening\n",
    "listener.listen()"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "front_matter": {
   "description": "Use Composio to create AI agents that seamlessly connect with external tools, Apps, and APIs to perform actions and receive triggers. With built-in support for AutoGen, Composio enables the creation of highly capable and adaptable AI agents that can autonomously execute complex tasks and deliver personalized experiences.",
   "tags": [
    "agents",
    "tool use"
   ]
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
