> ## Documentation Index
> Fetch the complete documentation index at: https://docs.galadriel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Discord Agent

This tutorial will walk you through building a Discord agent using the Galadriel framework. This agent will simulate a specific persona and interact with users on your Discord server.

## Prerequisites

* **Discord Bot:** You'll need a Discord bot account with its token and your server's ID. Follow [Discord's documentation](https://discordpy.readthedocs.io/en/stable/discord.html) to create an application, add a bot to it, and invite it to your server. Ensure the bot has the necessary permissions ("Send Messages", "Read Message History").
* **Galadriel Environment:** Make sure you have the Galadriel framework installed and set up as per the [Quickstart Guide](/galadriel-network/get-started/quickstart). This includes Python 3.10 or higher, and the Galadriel library.
* **OpenAI API Key:** You will need an OpenAI API key to utilize the LLM for generating responses.
* **(Optional) Composio API Key:** If you plan to use Composio tools, you will need an API Key from Composio.

## Step 1: Set up the Discord Bot

1. **Create a Discord Application:** Go to the [Discord Developer Portal](https://discord.com/developers/applications) and create a new application.

2. **Create a Bot User:**  Navigate to the "Bot" tab of your application and click "Add Bot."

3. **Obtain your Bot Token:**  In the "Bot" tab, click "Reset Token" and copy the token. Store this token securely. You'll need it later. **Keep this token secure!**  Enable the "Message Content Intent" under the "Privileged Gateway Intents" section.

4. **Invite the Bot to Your Server:** Go to the "OAuth2" -> "URL Generator" tab, select the "bot" scope and the "Send Messages" and "Read Message History" permissions. Copy the generated URL and open it in your browser to add the bot to your server.

## Step 2: Create a Galadriel Agent Project

1. **Clone the Galadriel repository:**

   ```bash theme={null}
   git clone <repository_url>
   cd galadriel/examples/discord
   ```

   Replace `<repository_url>` with the actual URL of the Galadriel repository.

2. **Create a virtual environment:**

   ```bash theme={null}
   python3 -m venv venv
   source venv/bin/activate
   ```

3. **Install the Galadriel framework:**

   ```bash theme={null}
   pip install galadriel
   ```

## Step 3: Configure Your Agent

1. **Set Environment Variables:** Create a `.env` file in the root of your agent directory. Populate it with the necessary environment variables:

   ```bash theme={null}
   DISCORD_TOKEN=<YOUR_DISCORD_BOT_TOKEN>
   DISCORD_GUILD_ID=<YOUR_DISCORD_SERVER_ID>
   OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
   COMPOSIO_API_KEY=<YOUR_COMPOSIO_API_KEY> # Optional, only if using Composio tools
   ```

   * Replace `<YOUR_DISCORD_BOT_TOKEN>` with the bot token you obtained from the Discord Developer Portal.
   * Replace `<YOUR_DISCORD_SERVER_ID>` with the ID of your Discord server. To get the server ID, enable Developer Mode in Discord (User Settings -> Advanced) and right-click your server icon to select "Copy ID".
   * Replace `<YOUR_OPENAI_API_KEY>` with your OpenAI API key.
   * Replace `<YOUR_COMPOSIO_API_KEY>` with your Composio API key, if you intend to use Composio tools.

2. **Create a Character Agent Configuration:** This step involves creating a `agent.json` file containing the personality settings for your agent. This file dictates the agent's behavior and style of communication.

   Create a `agent.json` file in your agent directory. You can customize this file to define the agent's persona. Here's an example configuration for an Elon Musk persona:

   ```json theme={null}
   {
     "name": "Elon Musk",
     "settings": {
       "model": "gpt-4",
       "debug": true
     },
     "system": "You are roleplaying as Elon Musk, CEO of Tesla, SpaceX, and X (formerly Twitter). You are known for your ambitious goals in sustainable energy, space exploration, and technological innovation. You have a unique communication style mixing technical depth with memes and humor.",
     "bio": [
       "Entrepreneur focused on accelerating humanity's transition to sustainable energy and making life multi-planetary",
       "Believes in taking bold risks to advance technology and human civilization",
       "Known for controversial statements and unorthodox leadership style"
     ],
     "lore": [
       "Sold PayPal to focus on rockets and electric cars when everyone said it was impossible",
       "Lives in a $50k house despite being one of the world's wealthiest people",
       "Named his child X Æ A-12",
       "Hosted SNL and revealed he has Asperger's syndrome",
       "Bought Twitter for $44B and renamed it to X"
     ],
     "topics": [
       "sustainable energy",
       "space exploration",
       "artificial intelligence",
       "electric vehicles",
       "neural technology",
       "social media",
       "cryptocurrency"
     ],
     "knowledge": [
       "Rocket engineering and orbital mechanics",
       "Electric vehicle technology and manufacturing",
       "Renewable energy systems and battery technology",
       "Artificial intelligence and its potential risks",
       "Software engineering and internet technology",
       "Physics and engineering principles",
       "Business strategy and scaling operations"
     ],
   }
   ```

3. **Modify the `agent/character_agent.py` file:**

   Replace the content of `agent/character_agent.py` with the following code:

   ```python theme={null}
   import json
   from pathlib import Path

   from rich.text import Text

   from galadriel import ToolCallingAgent
   from galadriel.core_agent import LogLevel
   from galadriel.domain.prompts.format_prompt import load_agent_template
   from galadriel.entities import AgentMessage
   from galadriel.entities import Message

   DISCORD_SYSTEM_PROMPT = """
   {{system}}

   # Areas of Expertise
   {{knowledge}}

   # About {{agent_name}}:
   {{bio}}
   {{lore}}
   {{topics}}

   # Task: You received a new message on discord from {{user_name}}. You must reply in the voice and style of {{agent_name}}, here's the message:
   {{message}}

   Be very brief, and concise, add a statement in your voice.
   Maintain a natural conversation on discord, don't add signatures at the end of your messages.
   Don't overuse emojis.
   Please remember the chat history and use it to answer the question.
   """


   class CharacterAgent(ToolCallingAgent):
       def __init__(self, character_json_path: str, **kwargs):
           super().__init__(**kwargs)
           try:
               self.character_json_path = character_json_path
               # validate content of character_json_path
               _ = load_agent_template(DISCORD_SYSTEM_PROMPT, Path(self.character_json_path))
           except Exception as e:
               self.logger.log(Text(f"Error validating character file: {e}"), level=LogLevel.ERROR)
               raise e

       async def execute(self, message: Message) -> Message:
           try:
               character_prompt = load_agent_template(DISCORD_SYSTEM_PROMPT, Path(self.character_json_path))
               task_message = character_prompt.replace("{{message}}", message.content).replace(
                   "{{user_name}}", message.additional_kwargs["author"]
               )
               # Use parent's run method to process the message content
               response = super().run(
                   task=task_message,
                   stream=False,
                   reset=False,  # retain memory
               )

               # Extract message text if response is in JSON format
               response_text = str(response)
               try:
                   response_json = json.loads(response_text)
                   if isinstance(response_json, dict) and "answer" in response_json:
                       response_text = response_json["answer"]
               except json.JSONDecodeError:
                   pass  # Not JSON format, use original response

               return AgentMessage(
                   content=response_text,
                   conversation_id=message.conversation_id,
               )
           except Exception as e:
               self.logger.log(Text(f"Error processing message: {e}"), level=LogLevel.ERROR)
               return None
   ```

4. **Modify the `agent/agent.py` file:** Replace the content with following code. Ensure `character_json_path="agent.json"` points to the correct location of the `agent.json` file.

   ```python theme={null}
   from galadriel.core_agent import LiteLLMModel
   from dotenv import load_dotenv
   from pathlib import Path

   from galadriel.tools.composio_converter import convert_action
   from character_agent import CharacterAgent
   from tools import get_time
   from galadriel import AgentRuntime
   from galadriel.clients import DiscordClient
   import os
   import asyncio
   from galadriel.logging_utils import get_agent_logger

   load_dotenv(dotenv_path=Path(".") / ".env", override=True)
   model = LiteLLMModel(model_id="gpt-4o", api_key=os.getenv("OPENAI_API_KEY"))

   logger = get_agent_logger()

   # Setup Discord client which
   # - pushes users' messages to the agent
   # - sends agent's responses back to the users
   discord_client = DiscordClient(guild_id=os.getenv("DISCORD_GUILD_ID"))

   # Setup Composio weather tool
   composio_weather_tool = convert_action(os.getenv("COMPOSIO_API_KEY"), "WEATHERMAP_WEATHER")

   # Add agent with GPT-4o model and tools helpful to answer Discord users' questions
   elon_musk_agent = CharacterAgent(
       character_json_path="agent.json",
       tools=[get_time],
       model=model,
   )

   # Set up the runtime
   runtime = AgentRuntime(
       inputs=[discord_client],
       outputs=[discord_client],
       agent=elon_musk_agent,
   )

   # Run the agent
   asyncio.run(runtime.run())
   ```

## Step 4: Run the Agent

1. **Start the agent:**  In your terminal, navigate to the project directory and execute:

   ```bash theme={null}
   python agent.py
   ```

## Step 5: Interact with the Agent on Discord

1. Go to your Discord server.
2. Send a message in a channel where the bot has access.
3. The bot should respond in the style of the specified persona (Elon Musk in this example).

## Code Explanation:

1. The `CharacterAgent` is a `ToolCallingAgent` that's designed to embody a specific persona. It loads its personality from the `agent.json` file.

   ```python theme={null}
   class CharacterAgent(ToolCallingAgent):
   ```

2. The `agent.json` file provides the agent with specific information such as lore, bio, and style to better generate the persona.

   ```python theme={null}
   character_json_path="agent.json"
   ```

3. Tools are functions that the Agent can leverage. The time tool is listed here,

   ```python theme={null}
   tools=[get_time],
   ```

4. The model defines the LLM that the Agent will use to compute and perform tasks.

   ```python theme={null}
   model=model,
   ```

## Conclusion

You have now successfully created a Discord agent using the Galadriel framework that embodies a specific persona and interacts with users on a Discord server. Experiment with different personas, tools, and prompts to create diverse and engaging AI agents.
