A hands-on walkthrough shows how to add a SendMissingDataEmail tool to a .NET expense-approval AI agent built with Microsoft Agent Framework, using Auth0 Token Vault to securely manage Gmail OAuth tokens. Rather than storing Google access/refresh tokens in the application, Token Vault issues short-lived tokens on demand, and constructor injection keeps the Gmail token invisible to the LLM and its tool schema. The guide covers configuring the Google connection with Token Vault, enabling the My Account API and Multi-Resource Refresh Tokens for a separate Connected Accounts linking flow, updating Blazor components to track link status, building an EmailService, and wiring a backend endpoint that fetches a fresh token per request and immediately discards it. Part three of a series that will add CIBA-based push approval next.
Table of contents
Configuring Auth0 and Your Agent for Token VaultChecking Gmail Link StatusBuilding the Email ServiceSending the EmailUpdating the Agent ToolsUpdating the System PromptUpdating the Chat ComponentHandling the Google Connection FlowTesting the Email FlowWhat Happened Under the HoodWhere This Leaves UsQuestions this post answers
How do I let an AI agent send emails through Gmail without exposing OAuth tokens to the LLM?
Use a credential vault like Auth0 Token Vault to store Google access and refresh tokens outside the application, and fetch a short-lived access token only inside a backend endpoint right before calling the Gmail API, then discard it immediately. Inject the token via constructor injection into the tool class rather than passing it as a tool argument, so it never appears in the model's schema or responses. Developers wiring OAuth into agent tools can compare token-vault patterns like this on daily.dev.
Why does a Blazor Server app need to set BaseAddress explicitly on HttpClient when calling its own API endpoints?
A plain HttpClient in a Blazor Server circuit has no base address of its own, unlike a WebAssembly client that resolves relative URLs against the page it runs in. Without explicitly setting BaseAddress using NavigationManager.BaseUri, a relative request such as /api/send-missing-data-email throws an InvalidOperationException before leaving the process. Blazor developers debugging HttpClient errors can find similar gotchas on daily.dev.
How do you link a Google account for API access after a user already logged in with a different identity provider?
Use Auth0's Connected Accounts flow against the My Account API, a three-step handshake separate from login: initiate the connection to get a ConnectUri and ticket, redirect the browser so the user consents on Google, then complete the connection using a single-use connect_code returned in the URL fragment after Google redirects back. This requires enabling the My Account API, granting the create:me:connected_accounts scope, and configuring a Multi-Resource Refresh Token policy. Engineers building secondary account-linking flows can dig deeper into OAuth patterns on daily.dev.