DEPENDENCY RESILIENCE · PRACTICAL FIELD GUIDE

When Outlook goes down, your AI agent loses its tools

The model may still answer while its mailbox connection fails. Build an agent that knows the difference, stops retrying safely, and tells people what actually happened.

AIConnector editorial · · 12 minute read · Runnable synthetic demo

← All field guides
An engineer considers an interrupted email workflow, illustrated by a broken amber connection and a mint path
Keep the human informed when a dependency fails. The alternate path represents safe degraded work, not a way around the mailbox outage. AI-generated conceptual illustration, not an image of the incident.

Imagine a customer-success manager preparing for a client call. She asks her assistant to find the latest email, check the meeting time and send a short confirmation. The assistant can still write beautifully. Its connection to the mailbox, however, is unavailable.

This is where a useful agent can become a dangerous narrator. “Nothing urgent in your inbox” is not a valid answer to a failed search. “Sent” is not a valid answer to a timed-out send. Reliability means preserving these distinctions when the system is under pressure.

1. What do we know about the November outage?

The Microsoft-origin service-health extract published by the University of Pennsylvania identifies incidents MO1550821 and EX1550543. The suite update describes Exchange-related disruption, including mailbox access and Graph requests for email, calendars and contacts. It distinguishes those dependencies from functionality that does not use Exchange. Its latest located update discusses remediation involving an upstream authentication and routing configuration component, with improving stability. That is a mitigation update, not a complete causal account. Microsoft incident extract hosted by Penn.

Source limitation: this is a university-hosted extract of Microsoft administrative-console notices, not a Microsoft-hosted public postmortem. Its generated-at line and incident update timestamps are not consistent enough to infer a precise collection timeline. Microsoft administrators should check tenant-specific service health; public readers can consult Microsoft's public status page. A final public RCA was not located in this research pass.

There is a direct agentic-AI connection. Anthropic's 12 November, 22:23 UTC update attributed Microsoft 365 connector failures to the Microsoft service incident; mail, calendar and search tools, plus Claude for Outlook, remained affected in that update. Anthropic incident report.

OpenAI separately reported Microsoft connector connection and tool problems, with its incident marked investigating when checked. That is evidence of a connector problem, not evidence that every ChatGPT feature, model or API was unavailable. OpenAI connector incident.

What remains unknown here: the final causal sequence, complete blast radius, definitive recovery time, and prevention commitments. We should update the incident section when Microsoft publishes a final report rather than fill those gaps with plausible architecture stories.

2. Start with the basics: an agent is a chain of dependencies

A model generates language and proposes actions. A tool performs a concrete operation, such as searching messages. A connector links that tool to a service and its authorization. A healthy model cannot repair an unavailable mailbox simply by reasoning harder.

Person → agent → authorized mail tool → connector → Microsoft 365
                    ↑
          policy checks, deadline, result status
                    ↓
          truthful answer or safe degraded mode

Switching model providers is not necessarily a fallback. If two agents depend on the same Microsoft mailbox service, the common dependency remains. The useful fallback might instead be a locally prepared draft, a clearly dated authorized cache, or a candid explanation that live data is unavailable.

In our example, the assistant can help write the confirmation using facts the manager supplies. It must not invent the latest email or silently move private work data to another provider. It should keep the draft separate from permission to send it.

3. Decide what failure means before adding retries

Observed resultSuggested policyTell the person
Successful readUse returned records, with observation time.What the tool actually found.
429 or transient read failureRetry within a small shared budget; respect server delay.Live check failed if the budget expires.
401 or 403Inspect authentication or permission state, not an outage retry loop.Access was not established.
Repeated dependency failuresOpen a circuit breaker and stop new calls temporarily.This tool is temporarily unavailable.
Write response lostMark outcome unknown and reconcile before resending.Do not claim either success or non-delivery.

Backoff means waiting longer between attempts; jitter means varying the wait so clients do not all restart together. Microsoft Graph's throttling guidance says to respect Retry-After, and to use exponential backoff when that header is absent. A server's delay can exceed the user's time budget: stop rather than shorten that delay. This is general defensive design, not a claim that throttling caused this outage. Microsoft Graph throttling guidance.

A circuit breaker temporarily blocks calls after repeated failures. Closed allows calls; open rejects them quickly; half-open admits a limited recovery probe. Retrying attempts to recover a particular call. A breaker protects the wider application from repeatedly making calls likely to fail. Microsoft's circuit-breaker pattern.

The numbers in the demo are deliberately small teaching parameters, not universal production recommendations: three attempts, a three-second read budget, a breaker after two transient failures, and a five-second cooldown. Your workflow and measured dependency behavior should determine real limits.

4. Run the synthetic failure lab

Download the runnable JavaScript demo. It requires Node.js 18 or newer, no packages and no API key. All responses are fixtures. No Microsoft account is accessed and no email is sent.

node examples/outlook-resilience/resilience-demo.mjs

The harness uses an injected clock and fake sleep, so it does not actually wait. Its 36 assertions cover bounded retries, numeric and date-form retry delays, access errors, circuit opening and recovery, one recovery probe at a time, stale concurrent responses after circuit opening, rejected-send messaging, a late response beyond the deadline, uncertain writes, mock receiver deduplication, and honest user-facing messages.

PASS: 36 assertions; synthetic read retry, circuit recovery,
uncertain writes, mock deduplication, honest responses.

Read the code in three passes. First inspect safeReply: it is the user contract. Next inspect readWithPolicy: it retries only classified transient failures, and stops at its budget or circuit boundary. Finally inspect sendOnce: its different behavior is intentional.

The harness expects an adapter to enforce the supplied remaining request deadline. It does not implement real HTTP cancellation. Before integrating it, use an abortable transport with bounded timeouts and avoid stacking this loop on top of an SDK's own retry loop. A promise timeout alone does not cancel a request at the remote service.

5. Reading twice is not the same as sending twice

Idempotency means repeating an operation does not create an additional effect. Reading the same message twice usually does not change the mailbox. Sending the same email twice can create two messages. Even read results may change between attempts; a retry is not a guarantee of the same snapshot.

Consider a timeout after a send request leaves the application. The provider might have accepted it before the response disappeared. Blindly resending risks duplication. The demo reports unknown, preserves a reconciliation step, and makes only one call.

Microsoft Graph's sendMail documentation says a successful request returns 202 Accepted, which does not mean processing or delivery has completed. The documented endpoint does not provide a generic idempotency-key contract. Do not invent one by attaching an arbitrary header. Microsoft Graph sendMail reference.

The final test demonstrates a separate mock receiver that explicitly enforces deduplication. Sending the same key to that receiver creates one effect. This illustrates the guarantee you need; it does not confer that guarantee on Microsoft Graph. In a real system, persist the operation identity and intent, enforce concurrent uniqueness, and use a supported reconciliation workflow. Finding no Sent Items match immediately is not proof that nothing was accepted.

Do not let recovery drain every queued action automatically. An email approved before an outage may be irrelevant hours later. Preserve recipients, approved content and expiry, then revalidate whether the original authorization still applies. If you cannot establish a safe outcome, leave the item for human review.

6. Design the degraded experience around the person

Bad: “You have no unread messages.”
Better: “I could not check your mailbox. This is not evidence that there are no messages.”

Bad: “Your confirmation was sent.”
Better: “The send outcome is unknown. I will not resend automatically; the original request needs reconciliation.”

Bad: quietly using yesterday's mailbox snapshot.
Better: “Live access is unavailable. I can use the authorized snapshot from yesterday at 16:00, but it may omit new messages.”

Only offer a cache if your product actually has one, the user remains authorized, retention permits it, and its timestamp is available. Do not turn a temporary dependency failure into a reason to weaken access controls or send work data to a new service. An outage does not expand consent.

7. Move from the lab to a production boundary

  • Separate operation classes: read, accepted write, rejected write, unknown write and verified completion are different states.
  • Scope breakers: isolate meaningful dependency and tenant boundaries. One tenant's permission failure should not disable every customer's mailbox access.
  • Coordinate recovery: this demo is single-process and in-memory. Multiple replicas need coordinated probe limits and retry budgets; process restarts must not erase uncertain-write records.
  • Bound resources: add concurrency limits, a queue cap, request cancellation and a maximum age for queued work. Test an outage longer than the queue's retention window.
  • Log safely: record correlation IDs, operation type, status, elapsed time, attempts and final disposition. Avoid storing message bodies, tokens or sensitive prompts in routine diagnostic logs.
  • Measure actual outcomes: track unavailable reads, unknown writes, duplicates prevented and recovery-probe success. The demo supplies no production reliability measurements.
  • Test recovery as well as failure: include 429, persistent 503, invalid authorization, timeout after acceptance, stale cache, concurrent retries, restart and gradual recovery.
  • Keep the model outside enforcement: application code decides retry permission, authorization and whether a send may happen. Prompt instructions alone are not a safety boundary.

What a final RCA should add

A worthwhile post-incident update would separate initiating fault, propagation path, detection gap, mitigation, recovery evidence and prevention work. Until Microsoft supplies that evidence, this guide does not attribute the outage to a particular deployment, team or architecture decision.

The practical lesson does not need speculation: an agent is only as current as the tools it successfully used. When a dependency fails, preserve uncertainty, protect side effects, and give the person a useful next step rather than a confident fiction.