DEV Community

muthukumar pattan
muthukumar pattan

Posted on

Daily-summary-agent

Hermes Agent Challenge Submission: Write About Hermes Agent

*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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

Test it works:

curl http://localhost:11434/api/generate \
  -d '{"model": "hermes3", "prompt": "Say hello", "stream": false}'
Enter fullscreen mode Exit fullscreen mode

Step 2: Project Structure

daily-summary-agent/
├── slack_reader.py
├── gmail_reader.py
├── summarizer.py
├── main.py
├── credentials.json     ← Gmail OAuth file
└── .env
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

Run it:

python3 test_summarizer.py
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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


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*

Top comments (0)