* * *
* _____________ * .'
|\ /|
| \ @ / |
| \ ___ / |
| \/ \/ |
| \___/ |
| | | |
|_____| |_____|
__ ____________ __ ______________
/ / / / ____/ __ \/ |/ / ____/ ___/
/ /_/ / __/ / /_/ / /|_/ / __/ \__ \
/ __ / /___/ _, _/ / / / /___ ___/ /
/_/ /_/_____/_/ |_/_/ /_/_____//____/
┌─────────────────────────────────────┐
│ Outlook · Calendar · Email · Tasks │
└─────────────────────────────────────┘
Outlook Calendar, Email, Contacts, and To-Do integration via Microsoft Graph API. Works with Hotmail, Outlook.com, and Microsoft 365 accounts.
- List emails with filters (unread, important, by folder)
- Search emails by keyword
- Read full email content
- Send emails with file attachments (up to 3MB)
- Reply and reply-all to emails
- Forward emails
- List and navigate mail folders
- Move emails between folders
- Safe email sender with preview mode (prevents shell variable issues)
- List, create, update, delete calendar events
- Send calendar invites with branded HTML templates and Teams video links
- Check free/busy status for one or more people
- Find open time slots where all attendees are free
- List contacts
- Get user profile info
- Python 3.8+
msalpackage (pip install msal)- A Microsoft account (Hotmail, Outlook.com, or Microsoft 365)
- Azure App Registration (free, takes 5 minutes)
- Go to https://portal.azure.com
- Sign in with your Microsoft account
- Navigate to Azure Active Directory > App registrations > New registration
- Fill in:
- Name:
Hermes Agent(or any name you like) - Supported account types: Select "Accounts in any organizational directory and personal Microsoft accounts (for Hotmail/Outlook.com)"
- Redirect URI: Select "Public client/native (mobile & desktop)" and enter
http://localhost
- Name:
- Click Register
- Copy these values from the overview page:
- Application (client) ID -- you will need this
- Directory (tenant) ID -- you will need this
- Go to Certificates & secrets > New client secret > Add > Copy the Value (not the ID)
- Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions
- Add these permissions:
Calendars.ReadWriteMail.ReadWriteMail.SendUser.ReadContacts.Read
- Click Grant admin consent (if available)
Use the auth script to save your credentials:
./scripts/auth.sh --client-id "YOUR_CLIENT_ID" --client-secret "YOUR_CLIENT_SECRET" --tenant-id "YOUR_TENANT_ID"Or if using a personal Microsoft account (Hotmail/Outlook.com), you can omit the tenant ID:
./scripts/auth.sh --client-id "YOUR_CLIENT_ID" --client-secret "YOUR_CLIENT_SECRET"Credentials are saved to ~/.hermes/microsoft_client_secret.json.
# Get the auth URL
python3 scripts/setup.py --auth-url
# Open the URL in your browser, sign in, and copy the redirect URL
# Paste the redirect URL
python3 scripts/setup.py --auth-code 'PASTE_THE_REDIRECT_URL_HERE'The token is saved to ~/.hermes/microsoft_token.json and auto-refreshes.
If you want personalized calendar invite templates:
./scripts/auth.sh --config --name "Jane Doe" --agent "Hermes"This saves to ~/.hermes/microsoft_config.json. Without this, calendar invites use a clean template with no sign-off.
./scripts/auth.sh --checkAPI="python3 scripts/microsoft_api.py"
# List recent emails
$API mail list --max 10
# List unread emails only
$API mail list --unread
# List high-importance emails
$API mail list --important
# List emails from a specific folder
$API mail list --folder archive --max 5
# Search emails by keyword
$API mail search --query "invoice" --max 5
$API mail search --query "project report" --folder sent
# Read an email
$API mail get MESSAGE_ID
# Send an email
$API mail send --to "user@example.com" --subject "Hello" --body "How are you?"
# Send with attachment (max 3MB)
$API mail send --to "user@example.com" --subject "See attached" --body "Here's the file" --attachment /path/to/file.png
# Reply to an email
$API mail reply MESSAGE_ID --body "Thanks for the update!"
# Reply-all to an email
$API mail replyall MESSAGE_ID --body "Sounds good, team."
# Forward an email
$API mail forward MESSAGE_ID --to "forward@example.com" --body "FYI"
# List all mail folders
$API mail folders
# Move an email to a different folder
$API mail move MESSAGE_ID --folder FOLDER_IDThe safe sender previews emails before sending. This prevents issues with shell $ variable interpretation:
SAFE="scripts/safe_mail_send.sh"
# Preview only (does not send)
$SAFE --to "user@example.com" --subject "Invoice for $20" --body-file /tmp/email.txt
# Preview and send
$SAFE --to "user@example.com" --subject "Invoice for $20" --body-file /tmp/email.txt --confirm
# With attachment
$SAFE --to "user@example.com" --subject "Report" --body-file /tmp/email.txt --attachment /path/to/file.png --confirm# List upcoming events (default)
$API calendar list
# List all events including past
$API calendar list --all
# List events in a date range
$API calendar list --start "2026-04-10T00:00:00" --end "2026-04-10T23:59:59"
# Create an event with Teams link
$API calendar create --summary "Meeting" --start "2026-04-10T15:00:00-04:00" --end "2026-04-10T15:30:00-04:00" --description "Sync up"
# Create an invite with attendees
$API calendar invite --summary "Project Sync" --start "2026-04-11T14:00:00-04:00" --end "2026-04-11T14:30:00-04:00" --description "Let's discuss" --attendees "john@example.com,jane@example.com" --meet
# Update an event (partial -- only update what you pass)
$API calendar update EVENT_ID --summary "New Title"
$API calendar update EVENT_ID --start "2026-04-11T16:00:00-04:00" --end "2026-04-11T16:30:00-04:00"
# Delete an event
$API calendar delete EVENT_ID
# Check free/busy for people (30-min blocks)
$API calendar freebusy --emails "user@example.com,other@example.com" --start "2026-04-14T09:00:00-04:00" --end "2026-04-14T17:00:00-04:00" --interval 30
# Find open 30-min slots where all attendees are free (15-min blocks)
$API calendar findopen --emails "user@example.com" --start "2026-04-14T09:00:00-04:00" --end "2026-04-14T17:00:00-04:00" --duration 30 --interval 15# List contacts
$API contacts list --max 20
# Get your profile info
$API user profile| File | Location | Purpose |
|---|---|---|
| Credentials | ~/.hermes/microsoft_client_secret.json |
Azure app credentials |
| Token | ~/.hermes/microsoft_token.json |
OAuth2 token (auto-refreshed) |
| Config | ~/.hermes/microsoft_config.json |
Display name, agent name (optional) |
| Problem | Fix |
|---|---|
Not authenticated |
Run scripts/setup.py --auth-url then --auth-code |
Token refresh failed |
Re-authorize: run scripts/setup.py --auth-url |
AADSTS700016 |
Wrong client_id or tenant_id in credentials |
AADSTS65001 |
Missing API permissions -- check Azure portal |
$20 becomes 0 in subject |
Use safe_mail_send.sh or write body to a temp file with cat << 'EOF' |
| Attachment too large | Max 3MB for inline attachments. Compress or split the file |
Insufficient privileges |
Need Calendars.ReadWrite permission in Azure |
To install this skill in Hermes Agent:
# Copy to skills directory
cp -r . ~/.hermes/skills/productivity/microsoft-workspace
# Or install from a published repo
hermes skills install your-username/microsoft-workspace-skillOnce installed, the agent can use it to send emails, manage calendar events, and look up contacts on your behalf.
MIT