Build an AI Agent That Monitors Your GitHub Repository
Learn to build a Python AI agent that watches GitHub issues and PRs, summarizes changes, and posts updates to Slack using OpenAI and the GitHub API.
Before you start
You have a GitHub repository and you want to stay on top of new issues, pull requests, and comments without refreshing the page. Manually checking is tedious, and email notifications get lost. This article walks you through building a small AI agent that monitors your repository, summarizes activity, and posts a digest to Slack.
The agent runs on a schedule, fetches recent events from the GitHub API, uses OpenAI to generate a concise summary, and sends it to a Slack webhook. You will end up with a script you can run locally or deploy as a cron job.
This tutorial assumes you have Python 3.10 or newer, a GitHub personal access token, and an OpenAI API key. You also need a Slack incoming webhook URL. If you do not have Slack, you can swap the final step for a simple console print.
- Python 3.10+ installed on your machine
- GitHub personal access token with repo scope
- OpenAI API key
- Slack incoming webhook URL (optional)
- pip and virtualenv available
Step 1: Set up the project
Create a new directory for the project and set up a virtual environment. You will install the requests library for API calls and python-dotenv for managing secrets.
mkdir gh-monitor-agent
cd gh-monitor-agent
python -m venv venv
source venv/bin/activate
pip install requests python-dotenv- Use a virtual environment to keep dependencies isolated.
- The requests library handles HTTP calls to GitHub and Slack.
- python-dotenv loads your .env file at runtime.
Step 2: Store your credentials
Create a .env file in the project root. This file holds your API tokens and repository name. Never commit this file to version control.
GITHUB_TOKEN=ghp_your_token_here
OPENAI_API_KEY=sk-your-key-here
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
REPO_OWNER=your-github-username
REPO_NAME=your-repo-name- Replace the placeholder values with your real credentials.
- Add .env to your .gitignore file.
- The GitHub token needs the repo scope to read issues and pull requests.
Step 3: Write the agent script
The agent script has three main parts: fetching recent activity, generating a summary with OpenAI, and posting to Slack. We will build it in a single file for simplicity, but you can split it into modules later.
The fetch function queries the GitHub events endpoint for your repository and filters for relevant event types. We keep the script focused: it looks at issues, pull requests, and their comments.
import os
import json
import requests
from datetime import datetime, timedelta
from dotenv import load_dotenv
load_dotenv()
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
SLACK_WEBHOOK_URL = os.getenv('SLACK_WEBHOOK_URL')
REPO_OWNER = os.getenv('REPO_OWNER')
REPO_NAME = os.getenv('REPO_NAME')
GITHUB_API = 'https://api.github.com'
def fetch_recent_activity(hours=24):
"""Get issues, PRs, and comments from the last N hours."""
since = (datetime.utcnow() - timedelta(hours=hours)).isoformat() + 'Z'
headers = {'Authorization': f'token {GITHUB_TOKEN}', 'Accept': 'application/vnd.github.v3+json'}
url = f'{GITHUB_API}/repos/{REPO_OWNER}/{REPO_NAME}/issues'
params = {'since': since, 'state': 'all', 'per_page': 100}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
return response.json()- The since parameter filters by update time, so comments count too.
- The per_page parameter caps the result at 100 items.
- The Accept header requests the v3 JSON representation.
Step 4: Generate the summary with OpenAI
Now that we have raw issue data, we send it to OpenAI to create a concise digest. We use the chat completions endpoint with a system prompt that instructs the model to summarize and prioritize.
The response is a short paragraph that highlights new issues, ongoing discussions, and any pull requests that need attention.
def summarize_with_openai(items):
"""Use OpenAI to summarize the activity."""
if not items:
return "No significant activity in the last 24 hours."
# Build a compact representation
lines = []
for item in items:
lines.append(f"#{item['number']} [{item['state']}] {item['title']}")
activity_text = '\n'.join(lines)
prompt = f"""You are a helpful assistant that summarizes GitHub activity.
Here are recent issues and pull requests:
{activity_text}
Write a short digest (max 150 words) that groups related items and highlights anything urgent."""
headers = {
'Authorization': f'Bearer {OPENAI_API_KEY}',
'Content-Type': 'application/json'
}
payload = {
'model': 'gpt-4o-mini',
'messages': [
{'role': 'system', 'content': 'You summarize GitHub activity concisely.'},
{'role': 'user', 'content': prompt}
],
'max_tokens': 200,
'temperature': 0.3
}
response = requests.post('https://api.openai.com/v1/chat/completions', headers=headers, json=payload)
response.raise_for_status()
return response.json()['choices'][0]['message']['content'].strip()- The model gpt-4o-mini is fast and cheap for this task.
- Temperature 0.3 keeps the summary factual.
- The prompt is trimmed to the essentials to save tokens.
Step 5: Post the digest to Slack
The final piece sends the summary to a Slack channel using an incoming webhook. The webhook URL is all you need; no Slack API token required.
def post_to_slack(text):
"""Send a message to Slack via webhook."""
payload = {'text': text}
response = requests.post(SLACK_WEBHOOK_URL, json=payload)
response.raise_for_status()
def main():
items = fetch_recent_activity()
summary = summarize_with_openai(items)
if SLACK_WEBHOOK_URL:
post_to_slack(summary)
else:
print(summary)
if __name__ == '__main__':
main()- If SLACK_WEBHOOK_URL is empty, the script prints the summary instead.
- The webhook expects a JSON payload with a text field.
- Slack webhooks are simple and work without extra permissions.
Step 6: Run the agent manually
Before you schedule it, run the script once to verify everything works. You should see a summary printed to the console or posted to Slack.
python agent.py- If you get a 403 error, check your GitHub token permissions.
- If OpenAI returns an error, verify your API key and billing status.
- Slack webhook errors usually mean the URL is wrong or the webhook was revoked.
Step 7: Schedule it with cron
To run the agent every morning, add a cron job. The example below runs it at 9 AM UTC daily. Adjust the path to your Python interpreter and script location.
crontab -e
# Add this line:
0 9 * * * cd /path/to/gh-monitor-agent && /path/to/venv/bin/python agent.py >> agent.log 2>&1- The cd ensures the script runs from the project directory.
- Logging output helps debug failures.
- Use the full path to the virtualenv python to avoid PATH issues.
Verify it worked
After the first scheduled run, check the log file for errors and confirm you received the Slack message. You can also test by manually running the script again after creating a test issue in your repository.
- Create a test issue and comment on it, then run the script to see if it appears.
- Check agent.log for any stack traces.
- If Slack is not receiving messages, test the webhook URL with a curl command.
Troubleshooting
Common issues include authentication failures, missing environment variables, and rate limiting. Here are quick fixes for the most frequent problems.
- 401 Unauthorized from GitHub: regenerate your token and ensure it has repo scope.
- OpenAI API error 429: you may be out of credits or hitting rate limits. Check your usage dashboard.
- Slack webhook returns 404: the webhook URL may be expired. Create a new one in Slack.
- Script runs but no summary: your repository may have no activity in the window. Adjust the hours parameter.
What I would do
For a production setup, I would add a few enhancements: persist the last seen timestamp so you do not miss events, filter out bot comments, and use a more robust scheduling tool like GitHub Actions.
Here is a recommended starter configuration for a GitHub Action that runs the same script on a schedule.
name: daily-digest
on:
schedule:
- cron: '0 9 * * *'
workflow_dispatch:
jobs:
digest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install -r requirements.txt
- run: python agent.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}- Store secrets in GitHub repository settings.
- The GITHUB_TOKEN is automatically provided, but it may not have enough permissions for all repos; you can add a PAT if needed.
- The workflow_dispatch trigger lets you run it manually from the Actions tab.
FAQ
- Q: Can I use a different LLM provider? A: Yes, the code calls OpenAI, but you can swap the endpoint and payload for Anthropic or a local model.
- Q: How do I monitor multiple repositories? A: Loop over a list of repos and call the fetch function for each, then combine the summaries.
- Q: What if I do not want to use Slack? A: Replace the post_to_slack function with an email or Discord webhook. The structure stays the same.
Next steps
You now have a working AI agent that watches your GitHub repository and delivers a daily digest. Run it once more to confirm, then schedule it with cron or GitHub Actions.
The next improvement is to add a filter for labels or assignees so the digest only shows what matters to you. Modify the fetch function to pass extra query parameters.
python agent.pyTry it on code.live
If you need to quickly format or inspect the JSON payloads your agent sends, use the JSON Formatter and JSON Diff tools on code.live to debug your API responses.
Key takeaways
- Apply one concrete change from this post before collecting more reading.
- Prefer browser-side tools when the work involves secrets, tokens, or PII.
- Document the why next to the how so the next reviewer inherits context.
FAQ
- Who is this guide on ai-agent for?
- Working developers who need a practical take on build an ai agent that monitors your github repository — not a marketing overview. Skim the sections, apply one tip, then come back when you hit an edge case.
- Do I need an account to use the related tools?
- No. code.live tools run in your browser with no signup. Nothing you paste is uploaded to a server for the client-side utilities linked from this post.
- How often is this article updated?
- This post was published November 3, 2026. Fundamentals stay stable; check linked tool pages and official docs when version-specific behavior matters.