Example: Event-Driven Agent
Build a proactive, event-driven GitHub agent that uses Webhooks to handle replies in real time.
This tutorial walks you through building a sophisticated, dual-mode agent. It will:
- Proactively monitor a GitHub repository and send an outreach email when it detects a new “star”.
- Reactively process and reply to incoming emails in real-time using AgentMail Webhooks.
We will use Flask to create a simple web server and ngrok
to expose it to the internet so AgentMail can send it events.
Prerequisites
Before you start, make sure you have the following:
- Python 3.8+
- An AgentMail API Key.
- An OpenAI account and API key.
- An ngrok account and authtoken.
Step 1: Project Setup
First, let’s set up your project directory and install the necessary dependencies.
-
Create a project folder and navigate into it.
-
Create a
requirements.txt
file with the following content: -
Install the packages:
-
Create a
.env
file to store your secret keys and configuration.- Replace the placeholder values with your actual keys.
WEBHOOK_DOMAIN
is your custom domain from your ngrok dashboard.INBOX_USERNAME
will be the email address for your agent (e.g.,github-star-agent@agentmail.to
).
Step 2: The Agent Code (main.py
)
Create a file named main.py
and add the full code example you provided. This script contains all the logic for our agent, including the new logic to idempotently create the inbox it needs.
Understanding the Code
Idempotency with client_id
Idempotency with client_id
Notice that the script now handles its own setup. Before the agent starts, the code calls client.inboxes.create
with a client_id
parameter. This makes the operation idempotent.
The first time you run the script, it creates the inbox. Every subsequent time, the AgentMail API will recognize the client_id
, see that the inbox already exists, and simply return the existing inbox’s data instead of creating a duplicate. This makes your script robust and safe to run multiple times. The same principle is used when creating the webhook.
Agent Persona and Instructions
The instructions
variable defines the agent’s entire personality, goals, and operational logic. It’s a comprehensive prompt that tells the agent how to behave in two distinct scenarios: proactive outreach for new GitHub stars and reactive replies to incoming emails. It includes strict rules on HTML formatting and how to handle different types of user queries.
Proactive Polling (poll_github_stargazers
)
Proactive Polling (poll_github_stargazers
)
This function runs in a separate background thread. For this demo, it simulates finding a new star on your target repository every 13 seconds. When it “finds” one, it constructs a detailed prompt and calls the agent to begin the outreach workflow (search for info, then send an email).
This is a Simulation
To keep the example focused, this code does not actually connect to the GitHub API. It simulates finding a new star to trigger the agent. In a real-world application, you would replace the simulation logic inside this function with actual API calls to GitHub to get real data.
Webhook Server (Flask
and ngrok
)
Webhook Server (Flask
and ngrok
)
app = Flask(__name__)
creates our web server.@app.route("/webhooks", methods=["POST"])
defines the specific URL that will listen forPOST
requests from AgentMail.listener = ngrok.forward(...)
tellsngrok
to create a public URL (using yourWEBHOOK_DOMAIN
) and securely forward all traffic to our local Flask server on port8080
.
Webhook Processing (process_webhook
)
Webhook Processing (process_webhook
)
When a request hits our /webhooks
endpoint, the receive_webhook
function immediately starts the process_webhook
function in a new thread. This is a crucial best practice: it allows us to return a 200 OK
status to AgentMail instantly while the heavy lifting happens in the background.
Inside process_webhook
, the function parses the JSON payload, constructs a prompt from the email’s content, runs the agent, and then uses client.messages.reply()
to send the agent’s HTML output as a reply.
Step 3: Run the Agent
Now, let’s bring your agent to life. The script is now fully self-contained. When you run it, it will automatically:
- Create the agent’s inbox.
- Start an
ngrok
tunnel to get a public URL. - Use that URL to create the AgentMail webhook.
- Start the web server to listen for events.
- Start the background process to monitor GitHub.
Open your terminal in the project directory and run the command:
You should see a series of logs confirming that all setup steps have been completed. Keep this terminal window running.
Step 4: Test Your Agent
Test Scenario 1: Proactive Outreach
You don’t have to do anything for this one! The poll_github_stargazers
function is already running. Within about 15 seconds, you should see logs in your terminal indicating that a new star was detected and the agent is being triggered. A few moments later, an email should arrive in the inbox you specified for DEMO_TARGET_EMAIL
.
Test Scenario 2: Reactive Reply
- Find the email your agent just sent you.
- Reply to it with a question, like “This is cool! How do I install it?”
- Check your running
main.py
terminal. You should see new logs indicating a webhook was received and is being processed. - Shortly after, you should receive an HTML-formatted email reply from your agent in your inbox.
You now have a fully event-driven agent that can both initiate conversations and respond to them in real time!