Build Your First AI Agent · Lesson 5 of 8

Lesson 5 — Hooking the agent to real services

60 minutes. Gmail, Calendar, your CRM. How to give the agent real-world reach.

---

The wiring pattern

Each tool implementation is just a function. What's inside doesn't matter to the model — only the contract (inputs, outputs) matters.

```js async function readInbox({ since }) { // Could be Gmail API, IMAP, Microsoft Graph, or a local file const messages = await gmail.users.messages.list({ userId: 'me', q: `is:unread after:${since}`, }) return messages.map(m => ({ id: m.id, from: m.from, subject: m.subject, body: m.snippet, })) } ```

The model doesn't care that you're calling the Gmail API. It just gets a JSON array of emails.

Three integrations every SMB agent needs

1. Email (Gmail / Microsoft Graph) — for reading and drafting. Microsoft Graph is the M365 path; Gmail API is the Google path. Both use OAuth2.

2. Calendar — for scheduling follow-ups. Same OAuth flow; different endpoint.

3. A datastore — SQLite for local dev, Postgres or MariaDB for production. Stores customer records, action log, processed-email markers.

OAuth — the one-time pain

Every Google or Microsoft API requires OAuth. Plan for 1-2 hours the first time:

  • Create an app in the provider's developer console
  • Set redirect URIs
  • Generate client_id + client_secret
  • Run a one-time auth flow to get a refresh token
  • Store the refresh token; refresh access tokens as needed

After the first time, you'll have a template you can clone for the next agent.

Don't let the agent send yet

Even now — when the integrations work, when the agent could send the reply, when everything seems ready — *don't let it send*. Wire `send_email` to a `drafts` folder. The next two lessons (errors, approval gates) are how you eventually let the agent transmit. Not yet.

→ Lesson 6 — Errors, retries, and recovery

Previous: Lesson 4 — State, memory, and context · Next: Lesson 6 — Errors, retries, and recovery