Microsoft Graph Skill
Integrates with Microsoft Graph API for Outlook mail and calendar on personal Microsoft accounts (consumers tenant). Uses PKCE auth — no client secret needed.
Skill root: Skill directory containing scripts/ and references/
Token file: ~/.openclaw/msgraph-tokens.json
First-time setup: Setup Guide — Walk through Azure app registration one time
For API details, scopes, and endpoint reference: see API Reference.
Auth
Always check auth status before making API calls.
python scripts/auth.py status # Check if authenticated
python scripts/auth.py login # Full PKCE login (opens browser — interactive, needs user)
python scripts/auth.py refresh # Force token refresh
python scripts/auth.py token # Print current access token
First-time setup: Run auth.py login. A browser window opens for Microsoft login. After login, tokens are stored and auto-refreshed on future calls.
WSL2 note: The script tries cmd.exe /c start to open the browser, then falls back to printing the URL. If the browser opens but the redirect fails, the user may need to paste the full redirect URL — ask them.
On 401 errors: Token auto-refreshes. If refresh fails, instruct the user to run python auth.py login.
# List inbox (default 20 messages)
python scripts/mail.py inbox
python scripts/mail.py inbox --count 50
python scripts/mail.py inbox --folder sentitems
# Read a message (also marks it read)
python scripts/mail.py read <message_id>
# Move a message to a folder (by name or well-known name)
python scripts/mail.py move <message_id> archive
python scripts/mail.py move <message_id> "Newsletters"
# List all folders (shows IDs and unread counts)
python scripts/mail.py folders
# Search email
python scripts/mail.py search "project update"
Folder names: Well-known names (inbox, drafts, sentitems, deleteditems, junk, archive) work directly. Display names are resolved automatically by listing folders.
Calendar
Note: The calendar script is named cal.py (not calendar.py) to avoid a Python stdlib conflict.
# List upcoming events (default 7 days)
python scripts/cal.py list
python scripts/cal.py list --days 14
# Get event detail
python scripts/cal.py get <event_id>
# Create an event
python scripts/cal.py create \
--subject "Team Sync" \
--start "2026-03-10T10:00" \
--end "2026-03-10T11:00" \
--tz "America/New_York" \
--location "Zoom" \
--body "Weekly sync call" \
--attendees "alice@example.com,bob@example.com"
# Delete an event
python scripts/cal.py delete <event_id>
# List available calendars
python scripts/cal.py calendars
Defaults: --tz defaults to America/New_York. --start/--end accept YYYY-MM-DDTHH:MM.
Workflow
- Run
auth.py status— if not authenticated, prompt user to runauth.py login - Call the appropriate script
- Present results in a readable summary (don't dump raw IDs to the user; use subjects/senders)
- For move operations, confirm which folder the email went to
- For event creation, confirm back the created event's subject, time, and ID
User Email Organization (example — update for your setup)
The user's inbox organization system:
- Inbox — open loops only (anything still needing action)
- Events/ — travel plans, reservations (subfolders per trip/event)
- eReceipts — purchase receipts and confirmations
When processing email unprompted, apply this logic before moving anything. When in doubt, leave in inbox and flag for the user.