Skip to content

Arslanex/custom-gmail-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Custom Gmail Agent

AI ile güçlendirilmiş, hafızası olan bir Gmail yönetim asistanı. Gelen mailleri senin kurallarına göre sınıflandırır, görev çıkarır, taslak üretir — Gmail'i asla kendi başına göndermez.

Genel vizyon ve yol haritası: docs/PLAN.md

Hızlı başlangıç

python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env          # ANTHROPIC_API_KEY ekle
# credentials.json → proje kökü (Google Cloud OAuth Desktop app)

python -m app.main auth
python -m app.main sync --dry-run
python -m app.main serve      # http://127.0.0.1:8765

Gmail'e yazma varsayılan kapalı (GMAIL_WRITE=off): sınıflandırma yalnızca yerel DB'de tutulur, Gmail etiketleri değişmez. Etiketlemeyi açmak için .envGMAIL_WRITE=on.

Faz 1 — Gelen mailleri güvenli biçimde çekip senin tanımladığın kurallara göre (rules.yaml) sınıflandırır, etiketler ve istersen gelen kutusundan arşivler. Sınıflandırma koda gömülü değil — tamamen senin elinde.

Faz 2Beklentiler ("şu gelince haber ver" + son tarih hatırlatması) ve süregelen işler (durum takibi, otomatik mail bağlama, zaman çizelgesi).

Faz 3Üslup öğrenme (Sent klasöründen kime nasıl yazdığını öğrenir) ve taslak üretimi (senin tarzında yanıt taslağı; asla göndermez, Gmail Taslaklar'a koyar — sen düzeltip gönderirsin).

Faz 4Knowledge Base (agent'a kişi/proje/kurum bilgisi öğretirsin) ve süreç tartışma (ask) — ilgili bilgileri + işleri toplayıp durumu konuşur. KB, taslak üretimine de beslenir.

Faz 5Günlük briefing (brief) ve davranış öğrenme (suggest-rules): agent kendi geçmişine bakıp tekrarlayan LLM sınıflandırmaları için deterministik kural önerir (token tasarrufu + tutarlılık).

Kurulum

1. Bağımlılıklar

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

2. Ortam değişkenleri (.env)

cp .env.example .env
Değişken Varsayılan Açıklama
ANTHROPIC_API_KEY Zorunlu. Claude API anahtarı
GMAIL_WRITE off on → sınıflandırmayı Gmail'e de yansıt (etiket/arşiv/yıldız)
CLASSIFIER_MODEL claude-haiku-4-5-20251001 Sınıflandırma modeli
DRAFTER_MODEL claude-sonnet-4-6 Taslak üretimi modeli
LABEL_PREFIX AI Öncelik/durum etiketleri için önek (AI/Öncelik/...)
FIRST_SYNC_QUERY newer_than:7d İlk sync'te hangi mailler taranır
FIRST_SYNC_MAX 50 İlk sync'te en fazla kaç mail

3. Gmail OAuth istemcisi

  1. Google Cloud Console → yeni proje.
  2. Gmail API'yi etkinleştirin.
  3. APIs & Services → OAuth consent screen → External, kendinizi "Test user" ekleyin.
  4. Credentials → Create Credentials → OAuth client ID → Desktop app.
  5. İndirdiğiniz JSON'u proje köküne credentials.json adıyla koyun.

Kullanım

python -m app.main auth            # İlk bağlantı (tarayıcıda izin verirsiniz)
python -m app.main sync --dry-run  # ÖNİZLEME: ne yapılacağını gösterir, dokunmaz
python -m app.main sync            # Yeni mailleri sınıflandır + etiketle/arşivle
python -m app.main status          # Son sınıflandırmaları listele

İlk kez çalıştırmadan önce sync --dry-run ile kurallarının ne yapacağını gör; emin olduğunda --dry-run olmadan çalıştır.

Beklentiler ve süregelen işler (Faz 2)

# Beklentiler — "şu gelince haber ver"
python -m app.main watch "Ali'den sunum dosyasını bekliyorum" --due 2026-07-05
python -m app.main watchers              # listele
python -m app.main watch-cancel 3        # iptal

# Süregelen işler — durum takibi + otomatik bağlama
python -m app.main matter "X firması bütçe onayı" --from x-firma.com --keyword bütçe
python -m app.main matters               # listele
python -m app.main matter-show 1         # zaman çizelgesi
python -m app.main matter-status 1 done  # open | waiting | done

sync sırasında: gelen mailler eşleşen işlere otomatik bağlanır (thread devamlılığı + kriter), beklentiler önce deterministik ön-filtreden geçer, yalnızca aday çıkanlar için tek LLM çağrısıyla doğrulanır. Tetiklenen mail yıldızlanır ve gelen kutusunda tutulur. Son tarihi geçen beklentiler sync sonunda hatırlatılır.

Üslup öğrenme ve taslak (Faz 3)

python -m app.main learn-style              # Sent klasörünü analiz et, üslubu öğren
python -m app.main styles                   # öğrenilen profilleri listele
python -m app.main draft <message_id> --instruction "kabul et, salıyı öner"
python -m app.main draft <message_id> --dry-run   # taslağı sadece göster, oluşturma

learn-style gönderdiğin maillerden global ve kişiye özel üslup profilleri çıkarır (dil, resmiyet, selamlama/kapanış, imza, uzunluk, emoji). draft bir maile yanıt taslağını senin üslubunda üretir ve Gmail Taslaklar'a koyar — draft asla göndermez; gözden geçirip kendin gönderirsin (human-in-the-loop).

Knowledge Base ve süreç tartışma (Faz 4)

# Agent'a bilgi öğret (doğal dille ya da yapılandırılmış)
python -m app.main remember "Ayşe Yılmaz mentor programının sorumlusu, ayse@vakif.org"
python -m app.main kb-add project "Bütçe 2026" "Yıllık onay süreci" --keyword bütçe
python -m app.main kb                       # listele  ·  kb-show / kb-remove

# Bir süreci/durumu ajanla tartış
python -m app.main ask "Bütçe onay sürecinde ne durumda olmalıyım?"

remember doğal dil notu yapılandırılmış bir kayda çevirir (kişi/proje/kurum/tercih). ask soruyla ilgili KB kayıtlarını + süregelen işleri (zaman çizelgesiyle) toplar, durumu özetler ve sonraki adımları önerir. KB ayrıca draft üretimine de beslenir — alıcıya/projeye dair bildiklerin taslağa yansır.

Günlük briefing ve davranış öğrenme (Faz 5)

python -m app.main brief --days 1     # bugün neye bakmalısın (deterministik, LLM'siz)
python -m app.main suggest-rules      # geçmişe bakıp deterministik kural öner

brief yanıt bekleyenleri, aktif/süresi geçmiş beklentileri ve açık işleri tek ekranda toplar. suggest-rules agent'ın kendi geçmişini analiz eder: bir domain sürekli aynı kategoriye (çoğunlukla LLM ile) atanıyorsa, yapıştırmaya hazır bir rules.yaml kuralı önerir — gelecekte o domain LLM harcamadan sınıflanır. Kuralı otomatik eklemez; onaylayıp eklemek sende.

İlk açılış: onboarding (geçmişten kişi/iş haritası)

python -m app.main onboard            # son 3 ayı tara → kişi/iş önerileri (dosyaya)
#   → onboarding/people.yaml + matters.yaml'ı düzenle (ilişki doldur, gereksizi sil)
python -m app.main onboard --apply    # KB + işlere işle, başlangıç çizgisini çek

İş zekâsı: görevler + toplantı notları (Faz 6)

python -m app.main tasks              # gelen kutusundan çıkarılan görevler (to-do)
python -m app.main tasks --check      # thread'lere bakıp yanıtlanmışları kapat
python -m app.main task-done 4        # görevi elle kapat
python -m app.main notes              # çıkarılan toplantı notları (karar + aksiyon)
python -m app.main sync --lite        # ucuz mod: görev/not çıkarımını atla

sync sırasında yanıt-bekleyen maillerden görev (tür/ne/kim/son tarih), karar içeren maillerden toplantı notu (kararlar + aksiyonlar) çıkarılır. tasks --check bir görevin thread'inde senden sonraki yanıtın varsa onu "halledildi" sayıp kapatır ("zaten yapıldı mı"). Hepsi brief'te toplanır.

Proaktif çalışma: zamanlama + bildirim (Faz 7)

python -m app.main notify-test                       # bildirim çalışıyor mu?
python -m app.main sync --notify                     # önemli bir şey varsa masaüstü bildirimi
python -m app.main brief --notify                    # günlük özeti bildirim olarak da gönder
python -m app.main schedule --times 08:00,13:00,18:00  # otomatik çalıştırma (macOS launchd)
#   → etkinleştir:  launchctl load ~/Library/LaunchAgents/com.gmailagent.sync.plist
python -m app.main schedule --remove                 # zamanlamayı kaldır

schedule macOS launchd ile sync --notify --quiet'i seçtiğin saatlerde otomatik çalıştırır. Akıllı bildirim: sadece acil mail, tetiklenen beklenti, yeni görev ya da süresi geçen beklenti varsa rahatsız eder — gerisi sessiz. Bildirimler ayrıca data/notifications.log'a, sync logları data/agent.log'a yazılır.

Calendar + toplantı-öncesi brief (Faz 8)

python -m app.main auth            # ⚠️ Calendar scope eklendi → bir kez yeniden auth
python -m app.main agenda --days 7         # yaklaşan toplantılar
python -m app.main meeting-brief --days 2  # yaklaşan toplantı(lar) için hazırlık brief'i

meeting-brief her yaklaşan toplantıyı geçmiş kararlar + aksiyon maddeleri + açık görevler ile eşleştirir ve "geçen sefer şunu kararlaştırdın, bu toplantıya kadar şunlar bekliyor" özeti üretir. Calendar erişimi calendar.readonly (salt-okunur).

Türkçe-duyarlı arama + yakın-tekrar birleştirme (Faz 9)

Arama (KB, ask) artık Türkçe eklere toleranslı: "bütçeyi" sorgusu "Bütçe" kaydını bulur (ASCII-fold + kök-önek eşleşmesi, yeni bağımlılık/anahtar yok).

python -m app.main matters --dups          # yakın-tekrar işleri bul
python -m app.main matter-merge 5 11       # #11'i #5'e birleştir (bağ/görev/not taşınır)

Not: Gerçek vektör arama (Voyage + pgvector) bilinçli olarak ertelendi — bu ölçekte kök-eşleşmesi aynı değeri sıfır altyapıyla veriyor. Veri büyürse yükseltilebilir.

İlk sync son 7 günün maillerini işler (.envFIRST_SYNC_QUERY / FIRST_SYNC_MAX). Sonraki çalıştırmalar yalnızca yeni gelenleri işler (incremental, history.list).

Sınıflandırmayı sen tanımlıyorsun — rules.yaml

Kategoriler, kurallar ve gelen-kutusu görünürlüğü koda gömülü değil; hepsi proje kökündeki rules.yaml dosyasında (panel Kurallar sayfasından da düzenlenebilir — kaydet deyince dosyaya yazılır). Kurallar yukarıdan aşağıya değerlendirilir, ilk eşleşen kazanır.

Kategoriler vs kurallar: Kategori = mail türü ve gelen kutusunda mı kalacağı (inbox: keep|archive). Kural = hangi mail hangi kategoriye gider (when koşulu

  • set aksiyonu). Önce kategori tanımla, sonra ona yönlendiren kurallar yaz.

Koşullar (when) üç tipte olabilir, karıştırabilirsin:

  • Deterministik (ücretsiz): from, from_domain, from_contains, to, subject_contains, body_contains, has_attachment, is_calendar_invite, list_unsubscribe, precedence_bulk, has_header
  • Anlamsal (LLM): prompt: "doğal dille evet/hayır sorusu"
  • Birleştirici: all: [..] (VE) · any: [..] (VEYA) · not: {..}

Aksiyon (set): category, priority (Acil|Normal|Düşük), inbox (keep|archive), requires_reply, notify (yıldızla + bildir). stop: true → eşleşince dur.

Kılavuzlu dinamik kategoriler

Kategorileri elle eklemek zorunda değilsin. Hiçbir kategoriye tam oturmayan bir mail gelince agent otomatik yeni kategori açar (varsayılan inbox: keep) ve sana bildirir. İki kaynak vardır:

  • rules.yaml → senin sabit/öncelikli kategorilerin ve kuralların.
  • Öğrenilen kategoriler (DB) → agent'ın gözlemleyip açtıkları.

Guardrail (drift önleme): yeni ad önerilince mevcut kategorilerle harf-duyarsız karşılaştırılır; "Fatura" varken "fatura"/"Faturalar" açılmaz, var olan kullanılır. LLM fallback'i her zaman tüm bilinen kategorilerin listesini görür, böylece parçalanma olmaz.

python -m app.main categories                  # tüm kategoriler (dosya + öğrenilen)
python -m app.main category-inbox "Bağış" archive   # öğrenilen birinin görünürlüğü

İstediğinde öğrenilen bir kategoriyi rules.yaml'a taşıyıp kurala bağlayabilirsin.

Maliyet optimizasyonu: iki geçişli motor

  1. Deterministik geçiş (0 token): tamamen kural tabanlı bir eşleşme bulunursa LLM hiç çalışmaz.
  2. Anlamsal geçiş (gerekirse tek çağrı): kalan tüm prompt soruları + (gerekiyorsa) fallback sınıflandırması tek Claude Haiku çağrısında çözülür. N anlamsal kural = N çağrı değil.

Nihai seçim her zaman senin yazdığın öncelik sırasına göre yapılır. sync sonunda kaç mailin kural-tabanlı, kaçının LLM ile sınıflandığını raporlar.

Oluşan Gmail etiketleri / aksiyonlar

<KategoriAdı>          # rules.yaml kategorisi — doğrudan etiket adı (Toplantı, Fatura…)
AI/Öncelik/{Acil, Normal, Düşük}
AI/Durum/Yanıt Bekliyor   # requires_reply olanlar
⭐ yıldız               # notify:true olan kurallar
📥 arşivle              # inbox:archive → INBOX etiketi kaldırılır (geri alınabilir)

Mac uygulaması (menü çubuğu + servis)

python -m app.main serve        # FastAPI servisi (http://127.0.0.1:8765 · /docs)
python -m app.main menubar      # macOS menü çubuğu (servisi de başlatır)

menubar menü çubuğunda 📬 açık-görev sayısı + 🔴 acil rozetini gösterir; tıkla → Bugün / Hatırlatmalar / Şimdi sync / Önerileri gözden geçir / Paneli aç. Servis ayakta değilse menü çubuğu onu arka planda başlatır (tek komutla her şey).

Panel (http://127.0.0.1:8765/) — Notion tarzı, beyaz/minimal web arayüzü:

Sayfa Ne yapar
Bugün Günün özeti — sayılar, hatırlatmalar (açık görev listesi burada tekrarlanmaz)
Gelen öneriler E-postalardan çıkarılan görev önerileri (Onayla / Yoksay)
Görevler Açık işler — Tamamla / Tamamla ve taslak
Projeler Süregelen işler (matters)
Kurallar Görsel kural editörü — kategori + kural ekle/düzenle, arka planda rules.yaml'a yazar

Sidebar:

  • Şimdi eşitle — anlık sync
  • 15 dk otomatik eşitle — checkbox (tercih localStorage'da saklanır, sessiz sync)

Ham API: /docs · Kurallar API: GET /rules{document}, PUT /rules/document

Çift-tıkla açılan uygulama (.app)

python -m app.main build-app    # dist/GmailAgent.app üretir
open dist/GmailAgent.app        # menü çubuğunda başlar (Dock'ta görünmez)

Üretilen .app mevcut .venv'i sarar (hafif, anında çalışır). Uygulamalar'a taşıyıp Sistem Ayarları → Giriş Öğeleri'ne ekleyerek girişte otomatik başlatabilirsin. Tamamen bağımsız bir bundle istersen py2app/Briefcase kullanılabilir (daha ağır).

Testler

pip install -r requirements-dev.txt
python -m pytest          # tests/ — izole geçici DB, Gmail/LLM gerektirmez

Suite çekirdeği uçtan uca kapsar: sınıflandırma motoru, görev döngüsü, watcher/matter, DB-only sınıflandırma, FastAPI servis (TestClient), onboarding, hatırlatmalar.

Güvenlik notları

  • credentials.json, token.json, .env asla commit edilmez.gitignore'da.
  • data/ (SQLite DB, loglar) ve onboarding/ (kişisel öneriler) yerel kalır.
  • Mail içeriği güvenilmez girdi sayılır; prompt-injection'a karşı sınırlayıcıyla sarılır.
  • Agent asla mail göndermez/silmez — en fazla etiketler, arşivler, Gmail Taslaklar'a yazar.

Proje yapısı

rules.yaml                      # kategoriler + kurallar (panelden de düzenlenir)
.env.example                    # ortam değişkeni şablonu
app/
├── main.py                     # CLI giriş noktası
├── config.py                   # ayarlar (.env)
├── labels.py                   # karar → Gmail etiketi / arşiv / yıldız
├── gmail/                      # OAuth, API, incremental sync
├── classification/
│   ├── config_rules.py         # rules.yaml yükleme + doğrulama
│   ├── rules_document.py       # görsel editör ↔ YAML dönüşümü
│   ├── engine.py               # iki geçişli karar motoru
│   └── classifier.py           # Claude (Haiku) batched anlamsal değerlendirme
├── tracking/                   # beklentiler (watchers) + süregelen işler (matters)
├── drafting/                   # üslup öğrenme + taslak üretimi
├── knowledge/                  # Knowledge Base + ask
├── learning/                   # briefing + kural önerisi
├── work/                       # görev çıkarımı, yanıt takibi
├── service/
│   ├── api.py                  # FastAPI (panel + REST)
│   └── static/panel.html       # web arayüzü
├── menubar/                    # macOS menü çubuğu uygulaması
└── storage/db.py               # SQLite
data/                           # agent.db, loglar (gitignore)
tests/                          # pytest — Gmail/LLM gerektirmez
docs/                           # PLAN, mimari notlar

Lisans

Kişisel / dahili kullanım. Dağıtım veya lisans belirtilmemişse repo sahibine aittir.

About

Personal AI Gmail agent: rule-based + LLM classification, task extraction, draft replies, and a local FastAPI dashboard. Never sends email.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors