You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
oabrivard d9c7497acb Added openai classifier 1 week ago
app Added openai classifier 1 week ago
.env.example Added openai classifier 1 week ago
.gitignore Initial commit 1 week ago
README.md Added openai classifier 1 week ago
requirements.txt Added openai classifier 1 week ago

README.md

Personal Gmail + Calendar Agent

This project runs a small local API service that:

  • scans new Gmail inbox messages
  • classifies emails with an LLM as LINKEDIN, ADVERTISING, or OTHER
  • moves LinkedIn emails to a LinkedIn label/folder
  • moves advertising emails to an Advertising label/folder
  • exposes a secure availability endpoint powered by Google Calendar free/busy

1) Prerequisites

  • Python 3.11+
  • A Google account
  • An OpenAI-compatible API key for the LLM classifier
  • A Google Cloud project with:
    • Gmail API enabled
    • Google Calendar API enabled
    • OAuth consent configured
    • OAuth Client ID of type Desktop app

2) Google OAuth setup

  1. In Google Cloud Console, create a desktop OAuth client.
  2. Download the client JSON file.
  3. Save it in this project as credentials.json.

The first run opens a browser window for consent and creates token.json.

3) Install and configure

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

Edit .env and set:

  • AGENT_API_KEY to a strong secret for agent-to-agent calls
  • LLM_API_KEY and optional LLM_MODEL / LLM_BASE_URL
  • optional scan frequency and Gmail query

4) Run

uvicorn app.main:app --reload

At startup, the scheduler runs every GMAIL_SCAN_INTERVAL_MINUTES.

5) API usage

Health check

curl http://127.0.0.1:8000/health

Manual Gmail scan

curl -X POST "http://127.0.0.1:8000/scan?max_results=100" \
  -H "X-API-Key: your-secret"

Availability for other AI agents

curl -X POST "http://127.0.0.1:8000/availability" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-secret" \
  -d '{
    "start": "2026-03-09T09:00:00+01:00",
    "end": "2026-03-09T10:00:00+01:00",
    "calendar_ids": ["primary"]
  }'

If available is true, there are no busy slots in that range.

Classification behavior

  • LLM classification is used for each email (LINKEDIN, ADVERTISING, OTHER).
  • LinkedIn has priority over advertising inside the classifier prompt.
  • Set LLM_FALLBACK_TO_RULES=true only if you want rules-based backup when LLM calls fail.
  • Every scanned message gets an AgentProcessed label to avoid reprocessing loops.

Notes

  • Gmail "folders" are labels. This agent creates:
    • LinkedIn
    • Advertising
    • AgentProcessed
  • Messages classified as LinkedIn/Advertising are removed from INBOX (moved out of inbox).