*This is a # I Built a Private AI Agent That Reads My Slack & Gmail Every Morning — Runs 100% on My Laptop
No API keys. No cloud. No monthly bill. Just Hermes3 running locally, summarizing my entire day before I drink my first coffee.
The Problem Nobody Talks About
Every morning I opened 47 Slack messages and 23 emails and spent 40 minutes figuring out what actually needed my attention.
The obvious fix? Ask ChatGPT or Claude to summarize them.
But wait — that means sending every private Slack message, every client email, every internal discussion to someone else's server. For a startup, that's a non-starter.
So I built my own. Fully local. Fully private. Free forever.
What I Built
A Python agent that:
- 📥 Reads all Slack channels the bot is a member of
- 📧 Fetches today's Gmail since midnight
- 🧠 Sends everything to Hermes3 (running locally via Ollama)
- 📊 Returns a smart grouped summary with urgency levels
Every morning at 9 AM, this runs automatically and gives me:
🔴 URGENT — ACTION NEEDED
- Production server throwing 503s (#dev) — Ravi needs help
- Client contract must be signed by EOD — priya@client.com
💬 IMPORTANT DISCUSSIONS
- Q3 roadmap debate ongoing in #product
- Partnership proposal from Zoho needs response
📢 FYI — ANNOUNCEMENTS
- Monday is a public holiday (HR, #general)
🗑️ LOW PRIORITY
- 3 newsletters, 2 LinkedIn notifications
In under 60 seconds. On my machine. No data leaving my laptop.
Why Hermes3 — Not ChatGPT or Claude?
This is the question worth answering properly.
| ChatGPT / Claude API | Hermes3 (Local) | |
|---|---|---|
| Your data | Sent to their servers | Never leaves your machine |
| Cost | ~$30–50/month at scale | Free forever |
| Customization | Prompt only | Fine-tune on your own data |
| Internet required | Always | Never |
| Speed | Network latency | Pure local speed |
| Restrictions | Content policies | Full control |
Hermes3 is an open-source model by Nous Research, built on LLaMA 3. It's specifically fine-tuned to be excellent at instruction-following and summarization — exactly what this agent needs.
The Stack
Slack API + Gmail API
↓
Python agent
↓
Ollama (local runner)
↓
Hermes3 (LLM)
↓
Smart grouped summary
- Ollama — runs open-source models locally with one command
- Hermes3 — the local LLM doing all the thinking
- slack-sdk — Python library for Slack
- google-api-python-client — Gmail access
- Flask (optional) — web dashboard UI
Step 1: Install Hermes3 Locally
# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh
# Pull and run Hermes3 (4.7GB download)
ollama run hermes3
Test it works:
curl http://localhost:11434/api/generate \
-d '{"model": "hermes3", "prompt": "Say hello", "stream": false}'
Step 2: Project Structure
daily-summary-agent/
├── slack_reader.py
├── gmail_reader.py
├── summarizer.py
├── main.py
├── credentials.json ← Gmail OAuth file
└── .env
Step 3: Read All Slack Channels
# slack_reader.py
import os
from datetime import datetime
from slack_sdk import WebClient
from dotenv import load_dotenv
load_dotenv()
client = WebClient(token=os.environ["SLACK_BOT_TOKEN"])
def get_today_messages():
all_messages = {}
oldest = datetime.now().replace(hour=0, minute=0, second=0).timestamp()
result = client.conversations_list(types="public_channel,private_channel")
for ch in result["channels"]:
if not ch.get("is_member"):
continue
try:
history = client.conversations_history(
channel=ch["id"], oldest=oldest, limit=100
)
messages = [
m["text"] for m in history["messages"]
if m.get("text") and not m.get("bot_id")
]
if messages:
all_messages[ch["name"]] = messages
except Exception as e:
print(f"Skipping #{ch['name']}: {e}")
return all_messages
Step 4: Fetch Gmail
# gmail_reader.py
import os
from datetime import datetime
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
def get_gmail_service():
creds = None
if os.path.exists("token.json"):
creds = Credentials.from_authorized_user_file("token.json", SCOPES)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
creds = flow.run_local_server(port=0)
with open("token.json", "w") as f:
f.write(creds.to_json())
return build("gmail", "v1", credentials=creds)
def get_today_emails():
service = get_gmail_service()
today = datetime.now().strftime("%Y/%m/%d")
results = service.users().messages().list(
userId="me", q=f"after:{today}", maxResults=50
).execute()
emails = []
for msg in results.get("messages", []):
data = service.users().messages().get(
userId="me", id=msg["id"], format="full"
).execute()
headers = data["payload"]["headers"]
emails.append({
"subject": next((h["value"] for h in headers if h["name"] == "Subject"), ""),
"from": next((h["value"] for h in headers if h["name"] == "From"), ""),
"snippet": data.get("snippet", "")
})
return emails
Step 5: The Hermes Summarizer
This is where the magic happens. The prompt design is everything:
# summarizer.py
import requests
def summarize(slack_data, email_data):
prompt = """You are a smart executive assistant.
Analyze these messages and group them into exactly 4 sections:
🔴 URGENT — ACTION NEEDED (deadlines, outages, decisions needed today)
💬 IMPORTANT DISCUSSIONS (ongoing debates, replies needed soon)
📢 FYI — ANNOUNCEMENTS (good to know, no action needed)
🗑️ LOW PRIORITY (newsletters, notifications, can ignore)
For each item write: channel/sender — one line summary.
Be ruthlessly concise. Max 10 words per item.
=== SLACK ===\n"""
for channel, msgs in slack_data.items():
prompt += f"\n#{channel}:\n" + "\n".join(f"- {m}" for m in msgs)
prompt += "\n\n=== EMAILS ===\n"
for e in email_data:
prompt += f"- From: {e['from']} | {e['subject']} | {e['snippet'][:100]}\n"
prompt += "\n\nNow give the grouped summary:"
response = requests.post("http://localhost:11434/api/generate", json={
"model": "hermes3",
"prompt": prompt,
"stream": False
})
return response.json()["response"]
Step 6: Wire It All Together
# main.py
from slack_reader import get_today_messages
from gmail_reader import get_today_emails
from summarizer import summarize
from datetime import datetime
def run_agent():
print(f"\n🤖 Daily Brief — {datetime.now().strftime('%B %d, %Y %I:%M %p')}")
print("=" * 50)
print("📥 Reading Slack...")
slack = get_today_messages()
print("📧 Reading Gmail...")
emails = get_today_emails()
print("🧠 Thinking with Hermes3...\n")
summary = summarize(slack, emails)
print(summary)
with open("daily_summary.txt", "w") as f:
f.write(summary)
return summary
if __name__ == "__main__":
run_agent()
Step 7: Auto-run Every Morning
# Run at 9 AM every weekday
crontab -e
# Add this line:
0 9 * * 1-5 cd /path/to/daily-summary-agent && python3 main.py >> summary.log 2>&1
Bonus: Test Without Real Data
Before connecting Slack/Gmail, test Hermes summarization with fake data:
# test_summarizer.py
from summarizer import summarize
fake_slack = {
"dev": ["Server is down! 503 errors since 8am", "PR #234 needs review"],
"general": ["Team lunch at 1pm", "Please fill the feedback form"]
}
fake_emails = [
{"from": "boss@company.com", "subject": "Q3 Report Due Today", "snippet": "Submit by EOD"},
{"from": "newsletter@medium.com", "subject": "Top AI stories", "snippet": "Weekly digest..."}
]
print(summarize(fake_slack, fake_emails))
Run it:
python3 test_summarizer.py
No Slack token, no Gmail auth needed. Just Hermes running locally. ✅
The Result
🔴 URGENT — ACTION NEEDED
• #dev — Server down, 503s since 8am, fix immediately
• boss@company.com — Q3 report due today EOD
💬 IMPORTANT DISCUSSIONS
• #product — Q3 roadmap priorities debated, needs decision
• partnerships@zoho.com — Integration call request this week
📢 FYI — ANNOUNCEMENTS
• #general — Monday public holiday, no standups
• HR — Feedback form deadline Friday
🗑️ LOW PRIORITY
• medium.com — Weekly AI newsletter
• linkedin.com — 3 connection requests
40 minutes of inbox anxiety → 60 seconds of clarity. Every morning.
What's Next
Things I'm adding next:
- [ ] Slack DM support — summarize direct messages too
- [ ] Priority scoring — ML model trained on what I actually act on
- [ ] Web dashboard — Flask app with grouped cards UI
- [ ] WhatsApp integration — via Twilio API
- [ ] Voice briefing — text-to-speech with
pyttsx3
The Bigger Picture
We're in a moment where running a capable LLM locally is genuinely possible for any developer. Hermes3 on a MacBook M-series is fast, smart, and completely private.
The real unlock isn't just summarization. It's your own AI that knows your context, your team, your language — without sending that context to anyone else.
Every workflow you currently do with a cloud API, ask yourself: does this data need to leave my machine?
Often the answer is no.
Resources
- 🦙 Ollama — run LLMs locally
- 🤖 Hermes3 on HuggingFace
- 💬 Slack API
- 📧 Gmail API
- 📦 Full source code on GitHub ← add your repo link
Built this over a weekend. Still running every morning. Zero cloud costs.
Have questions or improvements? Drop them in the comments — happy to help you set it up.
Tags: #ai #python #productivity #ollama #opensourcesubmission for the Hermes Agent Challenge: Write About Hermes Agent*
























