Connect Hermes to Gmail and Calendar
Authorize your AI agent to search, send emails, and manage calendar events.
Introduction
30 Second Summary
You already talk to your AI agent from your phone. But every time you need to check an email or look at your schedule, you still have to leave the conversation, open another app, and lose your train of thought.
In this project, you will connect your Hermes Agent to your Gmail inbox and Google Calendar. By the end, you can search emails, send replies, and create calendar events through natural language from anywhere.
What You'll Build
You open Hermex on your phone, say "show me today's unread emails," and your agent pulls them from your real Gmail inbox in seconds.
By the end of this project, you'll have:
- A working email workflow where you search, read, and send emails through your agent using natural language.
- A working calendar workflow where you list upcoming events and create new ones with proper timezone handling.
- A secure OAuth2 connection between your agent and your Google account with tokens that auto-refresh.
- Secret Mission: an automated morning briefing that checks your emails and calendar daily and writes a summary file.
Are there any prerequisites?
This project builds on the "Talk to Your AI Agent from Your Phone" project. You need Hermes Agent, Hermes WebUI, Tailscale, and Hermex already installed and connected before starting.
Before We Start
Before We Start...
Before we dive in, let's lock in what you're about to build and why it matters.
Your Hermes Agent already talks to you from your phone. Now you're giving it the keys to your real email and calendar so it can act on your behalf.
Create a Google Cloud Project and OAuth Credentials
Your Hermes Agent is running and reachable from your phone, but it has no way to access your email or calendar yet. Google protects your data behind OAuth 2.0, a standard that requires any app to prove its identity before touching your account.
In this step, you will create a Google Cloud project, enable the APIs your agent needs, and generate the credentials that identify it to Google. These credentials alone do not grant access. The actual authorization happens in the next step.
In this step, get ready to:
- Create a Google Cloud project and enable the Gmail, Calendar, and People APIs.
- Configure an OAuth consent screen so Google knows your app's identity.
- Create OAuth 2.0 Desktop credentials and download the client secret file.
Create a new Google Cloud project
A Google Cloud project is the container that holds your APIs and credentials. You need one dedicated project for your Hermes Agent.
- Open the Google Cloud Console in your browser.
- Sign in with your Google account if prompted.
- Click Create Project near the top of the page.
- In the Project name field, enter Hermes Agent.
- Leave all other fields at their defaults and click Create.
- Wait a few seconds for the project to be created. Confirm it is selected in the project dropdown at the top of the page (you should see Hermes Agent displayed there).
What is a Google Cloud project?
A Google Cloud project groups all your API access, credentials, and usage quotas together. Think of it like a folder that keeps everything related to one app in one place.
No billing account is required for this project. The Gmail and Calendar APIs have free usage quotas that are more than sufficient for personal agent use.
Enable the required APIs
Google disables most APIs by default. You need to explicitly turn on the three APIs your agent will use.
- Navigate to the API Library in the Google Cloud Console.
- Search for Gmail API in the search bar.
- Click on Gmail API in the results, then click Enable.
- Click the back arrow or navigate back to the API Library.
- Search for Google Calendar API, click it, then click Enable.
- Navigate back to the API Library one more time.
- Search for People API, click it, then click Enable.
You should now see all three APIs listed as enabled. You can confirm this by navigating to the Enabled APIs & services page from the left sidebar and checking that Gmail API, Google Calendar API, and People API all appear.
Why three APIs?
The Gmail API handles email search, read, and send. The Google Calendar API handles listing and creating events. The People API is used for contact resolution when your agent adds attendees to calendar events.
🙋♀️ Don't see the API in search results?
Make sure your newly created Hermes Agent project is selected in the project dropdown at the top of the page. APIs are enabled per-project, so the wrong project selection means the API won't be available to your agent.
Help me find and enable the Gmail API in Google Cloud Console.
Create OAuth 2.0 Desktop credentials
Before Google issues credentials, it needs to know what your app is called and who to contact. This is configured through the OAuth consent screen.
- Navigate to the Credentials page in the Google Cloud Console.
- You will be prompted to configure a consent screen. Click Configure consent screen.
- Enter Hermes Agent in the App name field.
- Click Next.
- Select External as the user type. This works for any Google account, including personal accounts.
- Click Next.
- Enter your email address in the User support email field.
- Scroll down to Developer contact information and enter your email address again.
- Click Next.
- Review the summary and click Create to finish.
What is the OAuth consent screen?
The consent screen is what you see when an app asks "Allow this app to access your Gmail?" It displays the app name and contact info you just entered. Since your app is in testing mode, only you (and any test users you add later) will see it.
Now create the actual credentials your agent will use.
- Navigate back to the Credentials page.
- Click Create Credentials at the top of the page.
- Select OAuth client ID from the dropdown.
- For Application type, select Desktop app.
- In the Name field, enter Hermes Agent Desktop.
- Click Create.
- A dialog appears showing your client ID and secret. Click Download JSON to save the client secret file to your Downloads folder.
- Click OK to close the dialog.
Remember your filename
The downloaded file has a long name like client_secret_123456789.apps.googleusercontent.com.json. You will need the exact filename in the next step when you tell your agent where to find it.
Before you move on, do you think you can confirm the file exists on your machine using the terminal?
- Verify the client secret file was downloaded by running this command in your terminal:
macOS
ls ~/Downloads/client_secret_*.json
Windows
dir $env:USERPROFILE\Downloads\client_secret_*.json
Linux
ls ~/Downloads/client_secret_*.json
You should see the full path to your client secret JSON file printed in the output. If you see a filename that starts with client_secret_ and ends with .json, your credentials are ready.
No file found?
If the command returns nothing, check your browser's download location. Some browsers save to a different folder. On macOS/Linux, move the file to ~/Downloads/. On Windows, confirm it is in %USERPROFILE%\Downloads\ or note its actual path for the next step.
If you missed the Download JSON button, go back to the Credentials page, find your Hermes Agent Desktop client under OAuth 2.0 Client IDs, click the download icon on the right side of the row, and save the file.
Help me find and download my OAuth client secret JSON file from Google Cloud Console.
Your credentials are created and waiting. Next up, you will authorize your agent to actually use these credentials and prove you are an allowed user.
Authorize Your Agent with Google
Your Google Cloud project has OAuth credentials ready, but credentials alone don't grant access. Google puts new OAuth apps into "Testing" mode by default, which blocks all users who aren't explicitly approved.
In this step, you'll walk through the full OAuth2 authorization flow with your agent. You'll hit Google's testing-mode restriction head on, fix it, and complete the flow so your agent has live access to your Gmail and Calendar.
In this step, get ready to:
- Start the Google Workspace skill setup through your agent.
- Complete the OAuth2 authorization flow (after fixing a designed obstacle).
- Verify the connection by searching your real inbox.
Tell your agent to set up Google Workspace
Your agent already knows how to set up the Google Workspace skill. You just need to tell it where your client secret file is, and it handles the rest.
- Switch back to the Hermes WebUI at http://localhost:8787 (or open it through Hermex on your phone).
- Start a new session.
- Send this message to your agent (replace the filename with the actual file you downloaded in the previous step):
macOS
I want to set up the Google Workspace skill for email and calendar. The client secret JSON file is at: ~/Downloads/[[CLIENT_SECRET_FILE="client_secret_XXXXX.apps.googleusercontent.com.json"]]
Windows
I want to set up the Google Workspace skill for email and calendar. The client secret JSON file is at: C:\Users\[[WINDOWS_USERNAME="YourUsername"]]\Downloads\[[CLIENT_SECRET_FILE="client_secret_XXXXX.apps.googleusercontent.com.json"]]
Linux
I want to set up the Google Workspace skill for email and calendar. The client secret JSON file is at: ~/Downloads/[[CLIENT_SECRET_FILE="client_secret_XXXXX.apps.googleusercontent.com.json"]]
What does the agent do with this?
The agent runs $GSETUP --client-secret with your file path to import the credentials into the skill's configuration.
Then it generates an authorization URL by running $GSETUP --auth-url --services email,calendar --format json. This URL is what you'll click to grant your agent permission to access Gmail and Calendar.
Your agent will respond with a long URL starting with https://accounts.google.com/o/oauth2/auth.
Before you click it, what do you think will happen? Will Google let you authorize right away with a brand-new OAuth app in testing mode?
- Click the authorization URL the agent provides.
You see a page that says Error 403: access_denied. The page tells you the developer hasn't given you access to this app.
Why did this fail?
This is the designed obstacle of this step. When an OAuth app is in "Testing" mode, Google blocks every user who isn't explicitly listed as a test user. Your OAuth consent screen exists, but it doesn't know YOU are allowed to use it yet.
You need to add your own Google email address as a test user in the Cloud Console. Then the authorization will work.
Fix the testing-mode block and complete the flow
Now that you've seen why it failed, the fix is a quick addition in the Google Cloud Console.
- Open https://console.cloud.google.com/auth/audience in your browser.
- Under Test users, click Add users.
- Enter your Google email address (the same one you use for Gmail).
- Click Save.
Now you need a fresh authorization URL because the old one is expired.
- Return to your agent session in the Hermes WebUI.
- Send this message: "Generate a fresh authorization URL for Google Workspace."
- Click the new authorization URL the agent provides.
This time, Google shows you the consent screen. You see the scopes your agent is requesting (Gmail read/send, Calendar read/write).
- Click Continue to approve all requested scopes.
Your browser redirects to a page that says something like "This site can't be reached" at http://localhost:1. This is completely expected.
Why does the redirect page fail?
Desktop OAuth apps use http://localhost:1 as a redirect URI. Nothing is listening on that port, so the page can't load. The important part is the URL in your address bar. It contains an authorization code after ?code= that your agent needs.
- Copy the entire URL from your browser's address bar (it contains ?code=... at the end).
- Paste the full URL back to your agent in the chat.
The agent runs $GSETUP --auth-code with the URL you pasted to exchange the code for an access token. Your OAuth token is now saved at ~/.hermes/google_token.json on macOS/Linux or %USERPROFILE%\.hermes\google_token.json on Windows and auto-refreshes whenever it expires.
Auth code exchange failed?
If the agent reports the code is expired or already used, it will provide a fresh authorization URL in its response. Click the new URL, approve again, and paste the new redirect URL back. Authorization codes expire quickly, so copy and paste promptly.
help me troubleshoot my Google OAuth code exchange
Verify the connection and search your inbox
The token exchange is complete. Now confirm your agent can actually reach Google's APIs.
- Send this message to your agent: "Check if Google Workspace is set up."
The agent runs $GSETUP --check and prints AUTHENTICATED to confirm the token is valid and connected to your Google account.
Now for the real test. What do you think will happen if you ask your agent to search your inbox? Will it return real emails, or placeholder data?
- Send this message to your agent: "Search my Gmail for unread emails, show me the 5 most recent."
Your agent returns real emails from your inbox. Each result includes the sender, subject, date, and a short snippet of the email body, all in JSON format.
Not seeing any emails?
If your inbox has no unread emails, that's fine. Try a broader search: "Search Gmail for emails from the last 7 days" to confirm the connection works with any messages.
If you see a permissions error, your token may not have the right scopes. Tell your agent: "Revoke Google Workspace access and set it up again" to restart the flow.
help me fix my Gmail search not returning results
Your agent now has live access to your Gmail inbox. Next up, you'll use it to read full emails, send messages, and turn it into a complete email assistant you control from your phone.
Control Your Inbox Through Your Agent
Your agent can now search your Gmail inbox and pull back real emails. Searching proves the connection works, but a true email assistant does more than list results.
In this step, you'll read full email bodies, send an email on your behalf, and search with powerful Gmail operators. By the end, you'll be controlling your inbox entirely through natural language from your phone.
In this step, get ready to:
- Read the full body of an email through your agent.
- Send a test email from Hermex on your phone.
- Search your inbox using advanced Gmail operators.
Read a full email
The search results you saw in the previous step only show snippets. To see the entire message, you need to ask your agent to fetch the full body of a specific email.
- Return to the Hermes WebUI session where you searched your inbox in the previous step.
- Pick an email from the search results you want to read in full.
- Tell your agent to read that email by referencing its subject line or sender. For example:
Read the full message for the email about [subject from your results]
Your agent runs $GAPI gmail get MESSAGE_ID behind the scenes and returns the complete email body as text.
What does the agent do here?
When you ask to read a specific email, the agent identifies the correct message ID from your earlier search results, then fetches the full content. It prefers plain text but falls back to HTML if no plain text version exists.
You should see the full email body displayed in the chat, including any greeting, main content, and signature.
Not seeing the full email body?
Make sure you're referencing an email that appeared in your earlier search results. If the session has expired or you started a new one, run a fresh search first so the agent has message IDs to work with.
help me read a full email through my Hermes agent
Send a test email from your phone
Reading emails is half the story. An agent that can send emails on your behalf turns it into a full communication tool you can operate from anywhere.
- Open Hermex on your iPhone.
- Start a new session (or continue your existing one).
- Send this message to your agent:
Send an email to [[YOUR_EMAIL="your own email address"]] with subject 'Test from Hermes' and body 'Hello! This email was sent by my AI agent from my phone.'
- The agent will show you the email details and ask for confirmation before sending.
- Review the details and approve the send.
Why does the agent ask for confirmation?
The Google Workspace skill has a safety rule: the agent must never send email without confirming with you first. This applies to all write operations like sending emails, creating calendar events, or deleting files.
This means you always get a chance to review exactly what will be sent before it goes out. No accidental emails.
Before you check your Gmail, do you expect to find the test email in your Inbox, your Sent folder, or both?
- Open Gmail in your browser or the Gmail app on your phone.
- Check your Inbox. You should see the email with subject Test from Hermes because you sent it to yourself.
- Check your Sent folder. The same email should appear there, confirming your agent sent it from your account.
The answer is both. Since you sent the email to yourself, it appears in your Sent folder (you sent it) and your Inbox (you received it).
Email not showing up in Gmail?
Make sure you approved the confirmation prompt in Hermex. If you dismissed it or the session timed out, try sending the message again.
Check that the email address you used matches your actual Gmail address exactly. A typo will send the email to a different address without an error.
help me troubleshoot sending email through my Hermes agent
Search with specific queries
Your agent translates natural language into Gmail search syntax behind the scenes. This means you can describe what you're looking for in plain English and the agent handles the technical query.
- Switch back to the Hermes WebUI or continue in Hermex.
- Try this search to find emails from a specific person:
Search Gmail for emails from [[CONTACT_NAME="someone you know"]] in the last week
You should see results filtered to just that sender's messages from the past seven days.
- Now try searching for emails with attachments:
Search Gmail for emails with attachments from the last 3 days
- Try one more search using a keyword:
Search Gmail for emails with the word invoice
Each time, your agent translates your request into Gmail search operators like from:, newer_than:, and has:attachment to get you the right results.
What Gmail operators can I use?
You don't need to memorize Gmail search syntax. Just describe what you want in natural language and your agent figures out the right operators. It supports filtering by sender, date ranges, attachments, labels, read/unread status, and keywords.
🙋♀️ Getting empty results?
Empty results usually mean your inbox genuinely has no matching emails for that query. Try broadening the date range (e.g., "last month" instead of "last 3 days") or searching for a term you know exists in your inbox.
help me search Gmail through my Hermes agent
You now have a fully functional email assistant. You can search, read, and send emails through your agent using nothing but natural language from your phone or computer.
Your inbox is handled. Next up, you'll give your agent control over your calendar so it can list upcoming events and create new ones with a single command.
Manage Your Calendar Through Your Agent
Your agent now handles your inbox. You can search, read, and send emails from your phone without ever opening Gmail.
Your schedule is equally important. In this step, you'll teach your agent to list and create calendar events through natural language. Instead of switching to a calendar app and filling out form fields, you'll just tell your agent what to schedule.
In this step, get ready to:
- List your upcoming calendar events for the next 7 days.
- Create a calendar event with proper timezone handling.
- Create a detailed event with a location field.
List your upcoming events
Before creating anything new, let's see what's already on your calendar. This confirms the Calendar API connection works the same way your first Gmail search confirmed the email connection.
- Return to your Hermes WebUI session at http://localhost:8787.
- Send this message to your agent: "Show me my calendar events for the next 7 days".
- The agent runs $GAPI calendar list and returns your upcoming events as JSON with summary, start time, end time, and location.
What does $GAPI calendar list return?
The command defaults to the next 7 days and returns a JSON array. Each event includes fields like id, summary, start, end, location, description, and htmlLink.
If you have no events in the next 7 days, you'll see an empty array. That's perfectly fine. You'll create one next.
🙋♀️ Not seeing any calendar data?
Make sure the Google Calendar API is enabled in your Google Cloud project. You enabled it in Step 1, but you can double-check at https://console.cloud.google.com/apis/library by searching for "Google Calendar API" and confirming it says "Enabled".
If your agent says the token is invalid, ask it to check the Google Workspace status by saying "Check if Google Workspace is set up". The agent runs $GSETUP --check and should print AUTHENTICATED.
help me debug why my agent can't access Google Calendar
Create an event with proper timezone
Listing events proves the connection works. Now let's create one. Timezone handling is critical here. If your agent sends a bare datetime without a timezone offset, Google treats it as UTC, and your event shows up at the wrong local time.
- Send this message to your agent: "Create a calendar event called 'Test Event' for tomorrow at 2:00 PM to 2:30 PM in my local timezone".
- The agent will show you the event details and ask for confirmation before creating it.
- Approve the creation.
Why does the agent ask for confirmation?
The Google Workspace skill has a safety rule. The agent must never create or delete calendar events without confirming with you first. This prevents accidental or misinterpreted scheduling commands from modifying your real calendar.
You'll see this confirmation prompt for all write operations, including sending emails and creating events.
After you approve, the agent runs $GAPI calendar create with timezone-aware ISO 8601 timestamps. The start time will look something like --start 2026-07-17T14:00:00-07:00 where -07:00 is the timezone offset.
Why does timezone matter?
Times must include a timezone offset (e.g., -07:00) or use UTC (Z). Bare datetimes are ambiguous and treated as UTC. That means a "2:00 PM" event without an offset would show up at 2:00 PM UTC, which could be 7:00 AM or 9:00 AM in your local timezone.
Before you check your calendar, think about this: do you expect the event to show up at 2:00 PM in your local time, or could it appear shifted to a different hour?
- Open your Google Calendar (web at calendar.google.com, or the mobile app).
- Navigate to tomorrow's date.
- Confirm the "Test Event" appears at 2:00 PM to 2:30 PM in your local time.
You should see "Test Event" sitting at exactly 2:00 PM to 2:30 PM in your timezone. The agent handled the offset correctly.
Event showing at the wrong time?
If the event appears shifted (e.g., early morning instead of 2:00 PM), the agent may have sent a bare datetime without a timezone offset. Ask your agent: "Delete the Test Event and recreate it, making sure to include my local timezone offset in the start and end times." The agent uses $GAPI calendar delete EVENT_ID to remove the incorrect event before recreating it.
help me fix timezone issues with my calendar events
Create a more detailed event
A basic event works. Now create one with extra details like a location. This proves your agent can handle the optional fields that make calendar entries actually useful.
- Send this message to your agent: "Create a calendar event called 'Lunch with Alex' for [pick a specific date] from 12:00 PM to 1:00 PM, location 'The Corner Cafe'".
- The agent will show you the event details including the location. Approve when prompted.
The agent runs $GAPI calendar create with the --location flag to attach the location field to the event.
- Open Google Calendar and navigate to the date you chose.
- Click or tap on the "Lunch with Alex" event.
- Confirm the location field shows "The Corner Cafe".
You should see "Lunch with Alex" at 12:00 PM to 1:00 PM with "The Corner Cafe" as the location. Your agent can now create fully detailed calendar entries from a single natural language command.
Location field empty in Google Calendar?
If the event was created but the location is missing, the agent may not have included the --location flag. Ask your agent: "Delete the Lunch with Alex event and recreate it with location set to 'The Corner Cafe'." Make sure the agent confirms the location in the details before you approve.
help me get location to show up in my calendar events
Secret mission
Set Up an Automated Morning Briefing
Your agent responds when you ask, but what if it could prepare a daily summary before you even wake up? In this secret mission, you will combine Gmail search, Calendar list, and file writing into a single autonomous scheduled task using Hermes cron.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs on Google Cloud's free tier with no billing account required, so there are no ongoing costs.
Resources you used:
- Google Cloud project ("Hermes Agent") with OAuth credentials and enabled APIs.
- OAuth token stored at ~/.hermes/google_token.json (local file).
- Client secret stored in the Hermes skills directory (local file).
- Morning briefing file at ~/hermes-app/morning-briefing.md (local file).
Keep everything running
No action needed. Choose this if you are still actively using your agent for email and calendar.
- Your OAuth token auto-refreshes whenever you use Gmail or Calendar commands.
- Your agent can access Gmail and Calendar any time the Hermes WebUI is running.
- The Morning Briefing cron job runs daily at 7:00 AM if hermes gateway is active.
Pause - I'll come back to this later
Stop background processes to free up resources. Your credentials persist and will work next time you launch.
- Stop hermes gateway if it is running by pressing Ctrl+C in that terminal window.
- The OAuth token stays at ~/.hermes/google_token.json and will refresh automatically the next time you use a Gmail or Calendar command.
- No ongoing cost. Google Cloud does not charge for an idle project with no billing account.
Delete - I don't want to use this again
Remove all project resources entirely. This revokes your agent's Google access and deletes the Cloud project.
- Revoke your agent's Google access by telling your agent: "Revoke Google Workspace access." The agent runs $GSETUP --revoke which removes the OAuth token and credentials.
- Delete the Google Cloud project by navigating to https://console.cloud.google.com/iam-admin/settings in your browser.
- Select the Hermes Agent project, then click Shut down.
- Enter the project ID when prompted and click Shut down again to confirm.
- Remove the morning briefing file by running:
rm ~/hermes-app/morning-briefing.md
Nice Work!
Nice Work!
Nice work! You just turned your Hermes Agent into a personal email and calendar assistant that you control from your phone, anywhere in the world.
You've learned how to:
- Set up a Google Cloud project with OAuth 2.0 Desktop credentials and authorized your agent to access your Google account through the agent-guided OAuth2 flow, with tokens that auto-refresh.
- Searched, read, and sent emails through your agent using Gmail search operators, all from your phone via Hermex.
- Listed and created calendar events with proper timezone handling through natural language commands.
- (Secret Mission) Configured an automated daily morning briefing that summarizes unread emails and today's calendar events to a file on a cron schedule.
Ready to quiz yourself?