惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
MongoDB | Blog
MongoDB | Blog
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
aimingoo的专栏
aimingoo的专栏
I
InfoQ
B
Blog
WordPress大学
WordPress大学
Jina AI
Jina AI
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
Google Developers Blog
C
Check Point Blog
月光博客
月光博客
L
LangChain Blog
GbyAI
GbyAI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Daily-summary-agent
muthukumar pattan · 2026-05-31 · via DEV Community

*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


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*