togitoon commited on
Commit
186f97f
·
1 Parent(s): 14a8781

Improve the promt for sending email always

Browse files
README.md CHANGED
@@ -12,6 +12,12 @@ short_description: Agent for Topcoder Challenge
12
 
13
  An intelligent agent that helps developers discover and get notified about relevant Topcoder challenges based on their preferences.
14
 
 
 
 
 
 
 
15
  ## Configuration
16
 
17
  ### Environment Variables
@@ -45,15 +51,53 @@ The daily notification schedule can be customized using the `DAILY_NOTIFICATION_
45
  - `"*/30 9-17 * * 1-5"` - Every 30 minutes during business hours (9 AM to 5 PM) on weekdays
46
  - `"*/5 * * * *"` - Every 5 minutes (for testing)
47
 
48
- To override the default schedule, set the environment variable:
49
  ```bash
50
- export DAILY_NOTIFICATION_CRON="0 9 * * 1-5" # Weekdays at 9:00 AM UTC
51
  ```
52
 
53
  ## Usage
54
 
55
  ### 1. Setup Environment
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  ```bash
58
  export MISTRAL_API_KEY="your_mistral_api_key"
59
  export SUPABASE_URL="your_supabase_url"
@@ -61,6 +105,8 @@ export SUPABASE_ANON_KEY="your_supabase_anon_key"
61
  export SENDGRID_API_KEY="your_sendgrid_api_key"
62
  ```
63
 
 
 
64
  ### 2. Install Dependencies
65
 
66
  ```bash
 
12
 
13
  An intelligent agent that helps developers discover and get notified about relevant Topcoder challenges based on their preferences.
14
 
15
+ See `docs/` folder for all modules and refer to `demo.mov` for demo. It's running in https://huggingface.co/spaces/togitoon/tc-agent
16
+
17
+ **IMPORTANT: Hugging face environment uses my personal email for sending emails, so it will end up in spam folder**
18
+
19
+ **IMPORTANT: The images in the modules are hosted on git lfs, so use hugging face to be able to view those documents**
20
+
21
  ## Configuration
22
 
23
  ### Environment Variables
 
51
  - `"*/30 9-17 * * 1-5"` - Every 30 minutes during business hours (9 AM to 5 PM) on weekdays
52
  - `"*/5 * * * *"` - Every 5 minutes (for testing)
53
 
54
+ To override the default schedule, set the environment variable for local development to see it in action:
55
  ```bash
56
+ export DAILY_NOTIFICATION_CRON="*/5 * * * *" # Every 5 mins
57
  ```
58
 
59
  ## Usage
60
 
61
  ### 1. Setup Environment
62
 
63
+ Before running the application, you'll need to set up accounts with the following SaaS providers. All of them offer generous free tiers that are perfect for getting started:
64
+
65
+ #### **Mistral AI** - AI Model Provider
66
+ - **Free Tier**: Personal AI assistant with access to high-performing models, unlimited projects, voice mode, web searches, and more
67
+ - **Sign up**: [https://chat.mistral.ai/](https://chat.mistral.ai/)
68
+ - **API Access**: [https://console.mistral.ai/](https://console.mistral.ai/)
69
+ - Get your API key from the console to use the `mistral-large-latest` model for intelligent challenge matching
70
+
71
+ #### **Supabase** - Database & Backend
72
+ - **Free Tier**: 500MB database, 50,000 monthly active users, 5GB bandwidth, 1GB file storage
73
+ - **Sign up**: [https://supabase.com/dashboard/new?plan=free](https://supabase.com/dashboard/new?plan=free)
74
+ - **Pricing**: [https://supabase.com/pricing](https://supabase.com/pricing)
75
+ - **Setup Steps**:
76
+ 1. Create a new project and verify your email address when prompted
77
+ 2. Navigate to Settings → API to get your `SUPABASE_URL` and `SUPABASE_ANON_KEY`
78
+ 3. Go to SQL Editor in your Supabase dashboard
79
+ 4. Copy the contents of `database/supabase_schema.sql` and paste it into the editor
80
+ 5. Click "Run" to create the required database tables and indexes
81
+
82
+ #### **SendGrid** - Email Service
83
+ - **Free Trial**: 60 days free, send up to 100 emails/day (no credit card required)
84
+ - **Sign up**: [https://signup.sendgrid.com/](https://signup.sendgrid.com/)
85
+ - **Pricing**: [https://sendgrid.com/pricing](https://sendgrid.com/pricing)
86
+ - **Setup Steps**:
87
+ 1. Create your account and verify your email address
88
+ 2. **Important**: Set up Single Sender Verification in Settings → Sender Authentication
89
+ - Add your personal email address as a verified sender
90
+ - Click the verification link sent to your email
91
+ - This is required before you can send any emails through SendGrid
92
+ 3. Navigate to Settings → API Keys to create your `SENDGRID_API_KEY`
93
+ 4. For production use, consider Domain Authentication for better deliverability
94
+
95
+ **Note**: SendGrid requires sender identity verification to prevent spam and maintain reputation. Single Sender Verification is perfect for testing, while Domain Authentication is recommended for production environments.
96
+
97
+ #### Environment Variables Setup
98
+
99
+ Once you have your accounts set up, configure the following environment variables:
100
+
101
  ```bash
102
  export MISTRAL_API_KEY="your_mistral_api_key"
103
  export SUPABASE_URL="your_supabase_url"
 
105
  export SENDGRID_API_KEY="your_sendgrid_api_key"
106
  ```
107
 
108
+ **Why these services?** All three platforms are industry leaders that offer robust free tiers, making them perfect for development and small-scale production deployments. They scale seamlessly as your application grows, ensuring you only pay for what you actually use.
109
+
110
  ### 2. Install Dependencies
111
 
112
  ```bash
docs/module-8/Readme.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Hugging Face Deployment
2
+
3
+ ## Step 1
4
+
5
+ Configure required variables as secret
6
+
7
+ ## Step 2
8
+
9
+ Let the build happen and application starts
10
+
11
+ See: https://huggingface.co/spaces/togitoon/tc-agent
docs/module-9/Readme.md ADDED
@@ -0,0 +1 @@
 
 
1
+ # See Readme in the root
prompts/challenge_prompts.py CHANGED
@@ -64,7 +64,8 @@ User Preferences: {preferences}
64
  Your task:
65
  1. Query Topcoder for active challenges with good prizes (preferably $500+)
66
  2. Filter challenges that match the user's preferences
67
- 3. If you find relevant challenges, send a professional email notification
 
68
 
69
  Email Guidelines:
70
  - Subject should be compelling: "🏆 Relevant Topcoder Challenges Available"
 
64
  Your task:
65
  1. Query Topcoder for active challenges with good prizes (preferably $500+)
66
  2. Filter challenges that match the user's preferences
67
+ 3. If you find relevant challenges, send a professional email notification.
68
+ !!!IMPORTANT!!! If you find relevant challanges, always send an email using email tool
69
 
70
  Email Guidelines:
71
  - Subject should be compelling: "🏆 Relevant Topcoder Challenges Available"
tools/email_tool.py CHANGED
@@ -2,34 +2,141 @@ from sendgrid import SendGridAPIClient
2
  from sendgrid.helpers.mail import Mail
3
  from strands import tool
4
  from config.settings import settings
 
5
  import logging
6
 
7
  logger = logging.getLogger(__name__)
8
 
9
- @tool
10
- def send_email(to: str, html_content: str, subject: str) -> str:
11
- """Send an email notification about relevant Topcoder challenges"""
 
 
 
12
 
13
- logger.info(f"Sending email to {to} with subject: {subject}")
 
 
14
 
15
- # Use centralized configuration
 
 
 
 
 
 
 
 
 
 
 
16
  if not settings.SENDGRID_API_KEY:
17
- error_msg = "SENDGRID_API_KEY environment variable is not set"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  logger.error(error_msg)
19
- raise ValueError(error_msg)
 
 
 
 
 
20
 
21
- message = Mail(
22
- from_email=settings.SENDGRID_FROM_EMAIL,
23
- to_emails=to,
24
- subject=subject,
25
- html_content=html_content
26
- )
 
 
 
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  try:
29
  sg = SendGridAPIClient(settings.SENDGRID_API_KEY)
30
  response = sg.send(message)
31
- logger.info(f"Email sent successfully to {to}. Status: {response.status_code}")
32
- return f"Mail sent successfully to {to}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  except Exception as e:
34
- logger.error(f"Error sending email to {to}: {str(e)}")
35
- return f"Failed to send email to {to}: {str(e)}"
 
 
 
 
 
 
 
2
  from sendgrid.helpers.mail import Mail
3
  from strands import tool
4
  from config.settings import settings
5
+ from typing import Dict, Union
6
  import logging
7
 
8
  logger = logging.getLogger(__name__)
9
 
10
+ @tool(
11
+ name="send_notification_email",
12
+ description="Sends HTML email notifications about Topcoder challenges to registered users"
13
+ )
14
+ def send_email(to: str, html_content: str, subject: str) -> Dict[str, Union[str, list]]:
15
+ """Send an email notification about relevant Topcoder challenges using SendGrid.
16
 
17
+ This tool handles the complete email delivery process including validation,
18
+ formatting, and error handling. It uses the configured SendGrid API to send
19
+ HTML-formatted challenge notifications to registered users.
20
 
21
+ Args:
22
+ to: The recipient's email address (must be a valid email format)
23
+ html_content: The HTML-formatted content of the email notification
24
+ subject: The subject line for the email notification
25
+
26
+ Returns:
27
+ Dictionary with status and content indicating success or failure details
28
+ """
29
+
30
+ logger.info(f"Attempting to send email to {to} with subject: '{subject}'")
31
+
32
+ # Validate required configuration
33
  if not settings.SENDGRID_API_KEY:
34
+ error_msg = "SENDGRID_API_KEY environment variable is not set. Please configure SendGrid API key."
35
+ logger.error(error_msg)
36
+ return {
37
+ "status": "error",
38
+ "content": [
39
+ {"text": error_msg}
40
+ ]
41
+ }
42
+
43
+ if not settings.SENDGRID_FROM_EMAIL:
44
+ error_msg = "SENDGRID_FROM_EMAIL is not configured. Please set the sender email address."
45
+ logger.error(error_msg)
46
+ return {
47
+ "status": "error",
48
+ "content": [
49
+ {"text": error_msg}
50
+ ]
51
+ }
52
+
53
+ # Validate input parameters
54
+ if not to or "@" not in to:
55
+ error_msg = f"Invalid recipient email address: {to}"
56
+ logger.error(error_msg)
57
+ return {
58
+ "status": "error",
59
+ "content": [
60
+ {"text": error_msg}
61
+ ]
62
+ }
63
+
64
+ if not html_content.strip():
65
+ error_msg = "Email content cannot be empty"
66
  logger.error(error_msg)
67
+ return {
68
+ "status": "error",
69
+ "content": [
70
+ {"text": error_msg}
71
+ ]
72
+ }
73
 
74
+ if not subject.strip():
75
+ error_msg = "Email subject cannot be empty"
76
+ logger.error(error_msg)
77
+ return {
78
+ "status": "error",
79
+ "content": [
80
+ {"text": error_msg}
81
+ ]
82
+ }
83
 
84
+ # Construct the email message
85
+ try:
86
+ message = Mail(
87
+ from_email=settings.SENDGRID_FROM_EMAIL,
88
+ to_emails=to,
89
+ subject=subject,
90
+ html_content=html_content
91
+ )
92
+ except Exception as e:
93
+ error_msg = f"Failed to construct email message: {str(e)}"
94
+ logger.error(error_msg)
95
+ return {
96
+ "status": "error",
97
+ "content": [
98
+ {"text": error_msg}
99
+ ]
100
+ }
101
+
102
+ # Send the email via SendGrid API
103
  try:
104
  sg = SendGridAPIClient(settings.SENDGRID_API_KEY)
105
  response = sg.send(message)
106
+
107
+ # Check response status
108
+ if response.status_code in [200, 201, 202]:
109
+ success_msg = f"Email sent successfully to {to}"
110
+ logger.info(f"{success_msg}. SendGrid status: {response.status_code}")
111
+ return {
112
+ "status": "success",
113
+ "content": [
114
+ {"text": success_msg},
115
+ {"json": {
116
+ "recipient": to,
117
+ "subject": subject,
118
+ "status_code": response.status_code,
119
+ "message_id": response.headers.get("X-Message-Id", "N/A")
120
+ }}
121
+ ]
122
+ }
123
+ else:
124
+ error_msg = f"SendGrid returned unexpected status code: {response.status_code}"
125
+ logger.warning(error_msg)
126
+ return {
127
+ "status": "error",
128
+ "content": [
129
+ {"text": error_msg},
130
+ {"json": {"status_code": response.status_code, "response_body": str(response.body)}}
131
+ ]
132
+ }
133
+
134
  except Exception as e:
135
+ error_msg = f"Error sending email to {to}: {str(e)}"
136
+ logger.error(error_msg)
137
+ return {
138
+ "status": "error",
139
+ "content": [
140
+ {"text": error_msg}
141
+ ]
142
+ }