🔥Agentic AI Email Bot on AWS Bedrock AgentCore: Full Architecture and O365 Integration (1/2)🔥
aka, yes your inbox can have a robot in it now
This blog series focuses on presenting complex DevOps projects as simple and approachable via plain language and lots of pictures. You can do it!
These articles are supported by readers, please consider subscribing to support writing more of these articles <3 :)
Hey all! I’m Alex, a new contributor to Let’s Do DevOps. At work we’ve been building out a fleet of agentic AI bots backed by AWS Bedrock AgentCore: bots that live in Slack, Teams, and now email. Kyler has covered the Slack bot in depth across several articles. I want to show you the email version: same AgentCore foundation, completely different integration challenge.
The goal was to lower the friction for people to interact with our internal agentic bot. Slack and Teams work great if you’re in them all day, but not everyone is. The C-suite lives in email, and there are great email-native use cases too. Forward a vendor offer and ask the bot if accepting it would violate the company gift policy. Get CC’d on a question you don’t know the answer to? CC the bot and let it respond. The inbox is already where a lot of conversation happens, so we brought the bot there.
This is Part 1 of a 2-part series:
Part 1 (this article): Full architecture and Microsoft 365 integration
Part 2: Building the email thread, sending formatted replies, and operating in production
The Problem: Email Is Not Slack
If you’ve built a Slack bot before, you know how it works. Slack sends you an event when someone messages the bot. You process it, respond, done. It’s push-based so Slack does the work of notifying you.
Email is more complicated.
While Microsoft Graph supports push notifications for mail via a subscription, those subscriptions expire after 7 days and have to be renewed, you have to handle a validation handshake on creation, and if your endpoint is slow or unavailable, Graph will start dropping notifications permanently with no recovery. It’s more moving parts than it looks.
We chose polling instead. Simpler to operate, no subscription lifecycle to manage, and the delta query pattern makes it efficient.
That choice shapes the whole architecture. Instead of an event-driven Lambda that wakes up when Graph pings it, you need a polling layer that runs on a schedule, checks for new messages, and decides what to do with them.
But once you have polling, you immediately have two new problems: efficiency (you don’t want to re-fetch every email every minute) and idempotency (you don’t want to process the same email twice if something goes wrong).
We solved both. Let me show you how.


