Skip to main content

What you’ll learn

  • Authenticate with Auth0 AI: configure Auth0 AI and obtain federated access tokens for Google APIs.
  • Call external APIs securely: use the token to query Google Calendar through a Cloudflare tool.
  • Handle auth interruptions: enable dynamic user consent and reauthorization within chat flows.
Before getting started, make sure you have completed the following steps:
1

Create an Auth0 Account

To continue with this quickstart, you need to have an Auth0 account.
2

Create an Auth0 Application

Go to your Auth0 Dashboard to create a new Auth0 Application.
  • Navigate to Applications > Applications in the left sidebar.
  • Click the Create Application button in the top right.
  • In the pop-up select Regular Web Applications and click Create.
  • Once the Application is created, switch to the Settings tab.
  • Scroll down to the Application URIs section.
  • Set Allowed Callback URLs as: http://localhost:3000/auth/callback
  • Set Allowed Logout URLs as: http://localhost:3000
  • Click Save in the bottom right to save your changes.
3

Configure Google Social Integration

Set up a Google developer account that allows for third-party API calls by following the Google Social Integration instructions.
4

OpenAI Platform

  • https://mintlify.s3.us-west-1.amazonaws.com/auth0-genai-feat-add-diagrams-modal-with-steps/img/hono-light.svg Hono

Getting started using AI

To get started quickly:
Clone auth0-lab/auth0-ai-js and navigate to examples/calling-apis/spa-with-backend-api/react-hono-ai-sdk directory.
Then, integrate Auth0 AI docs into your preferred AI tool:

  • VS Code
  • Cursor
  • Claude Code
  • Claude
Create a .vscode/mcp.json file and add:
{
  "servers": {
    "Auth0 for AI Agents": {
      "type": "http",
      "url": "https://auth0.com/ai/docs/mcp"
    }
  }
}
To learn more, read the VS Code documentation.

or Follow manual steps

1

Configure Auth0 AI

If you started from the Auth0 Cloudflare Agents starter kit, you can skip this step as the Auth0 AI SDK is already configured.
First, you must configure your Cloudflare Agent to use Auth0 and both in the Worker and in the Chat Agent itself. We recommend the following two sdks:You can also check our Starter Kit to understand how to configure this.Then, you need to install the Auth0 AI SDK for Cloudflare Agents:
npm install @auth0/ai-vercel @auth0/ai-cloudflare @auth0/ai
Then, you need to initialize Auth0 AI and set up the connection to request access tokens with the required Google Calendar scopes.
./src/lib/auth0-ai.ts
import { Auth0AI, setGlobalAIContext } from "@auth0/ai-vercel";
import { getCurrentAgent } from "agents";
import type { Chat } from "./chat";

const getAgent = () => {
  const { agent } = getCurrentAgent<Chat>();
  if (!agent) {
    throw new Error("No agent found");
  }
  return agent;
};

setGlobalAIContext(() => ({ threadID: getAgent().name }));

const auth0AI = new Auth0AI();

export const withGoogleCalendar = auth0AI.withTokenVault({
  connection: "google-oauth2",
  scopes: ["https://www.googleapis.com/auth/calendar.freebusy"],
  refreshToken: async () => {
    const credentials = getAgent().getCredentials();
    return credentials?.refresh_token;
  },
});
2

Integrate your tool with Google Calendar

Wrap your tool using the Auth0 AI SDK to obtain an access token for the Google Calendar API.
./src/agent/tools/checkUsersCalendar.ts
import { addHours, formatISO } from "date-fns";
import { GaxiosError } from "gaxios";
import { google } from "googleapis";
import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel";
import { TokenVaultError } from "@auth0/ai/interrupts";
import { withGoogleCalendar } from "@/lib/auth0-ai";
import { tool } from "ai";
import { z } from "zod";

export const checkUsersCalendar = withGoogleCalendar(
  tool({
    description:
      "Check user availability on a given date time on their calendar",
    parameters: z.object({
      date: z.coerce.date(),
    }),
    execute: async ({ date }) => {
      // Get the access token from Auth0 AI
      const accessToken = getAccessTokenFromTokenVault();

      // Google SDK
      try {
        const calendar = google.calendar("v3");
        const auth = new google.auth.OAuth2();

        auth.setCredentials({
          access_token: accessToken,
        });

        const response = await calendar.freebusy.query({
          auth,
          requestBody: {
            timeMin: formatISO(date),
            timeMax: addHours(date, 1).toISOString(),
            timeZone: "UTC",
            items: [{ id: "primary" }],
          },
        });

        return {
          available: response.data?.calendars?.primary?.busy?.length === 0,
        };
      } catch (error) {
        if (error instanceof GaxiosError) {
          if (error.status === 401) {
            throw new TokenVaultError(
              `Authorization required to access the Token Vault connection`
            );
          }
        }

        throw error;
      }
    },
  })
);
3

Handle authentication redirects

Interrupts are a way for the system to pause execution and prompt the user to take an action—such as authenticating or granting API access—before resuming the interaction. This ensures that any required access is granted dynamically and securely during the chat experience. In this context, Auth0-AI SDK manages authentication redirects in the AI SDK via these interrupts.
If you started from the Auth0 Cloudflare Agents starter kit, you can skip this section as the Auth0 AI SDK is already configured to handle interrupts.

Server Side

On the Chat agent class, you need to set up the tool invocation and handle the interruption messaging via the errorSerializer.
./src/agent/chat.ts
import { setAIContext } from "@auth0/ai-vercel";
import { errorSerializer, withInterruptions } from "@auth0/ai-vercel/interrupts";
// Other dependencies
import { AuthAgent, OwnedAgent } from "@auth0/auth0-cloudflare-agents-api";
import { openai } from "@ai-sdk/openai";
import { AIChatAgent } from "agents/ai-chat-agent";

const SuperAgent = OwnedAgent(AuthAgent(AIChatAgent<Env>));

export class Chat extends SuperAgent {
 async onChatMessage(
    onFinish: StreamTextOnFinishCallback<ToolSet>,
    options?: { abortSignal?: AbortSignal }
  ) {
    // Collect all tools, including MCP tools
    const allTools = {
      ...tools,
      ...this.mcp.unstable_getAITools(),
    };
    const claims = this.getClaims();
    // Create a streaming response that handles both text and tool outputs
    const dataStreamResponse = createDataStreamResponse({
      execute: withInterruptions(async (dataStream) => {
        // Process any pending tool calls from previous messages
        // This handles human-in-the-loop confirmations for tools
        const processedMessages = await processToolCalls({
          messages: this.messages,
          dataStream,
          tools: allTools,
          executions,
        });

        // Stream the AI response using GPT-4
        const result = streamText({
          model,
          system: `You are a helpful assistant that can do various tasks...

${unstable_getSchedulePrompt({ date: new Date() })}

If the user asks to schedule a task, use the schedule tool to schedule the task.

The name of the user is ${claims?.name ?? "unknown"}.
`,
          messages: processedMessages,
          tools: allTools,
          onFinish: async (args) => {
            onFinish(
              args as Parameters<StreamTextOnFinishCallback<ToolSet>>[0]
            );
          },
          onError: (error) => {
            if (!Auth0Interrupt.isInterrupt(error)) {
              return;
            }
            console.error("Error while streaming:", error);
          },
          maxSteps: 10,
        });

        // Merge the AI response stream with tool execution outputs
        result.mergeIntoDataStream(dataStream);
      }),
      onError: errorSerializer((err) => {
        console.log(err);
        return "Oops, an error occured!";
      }),
    });

    return dataStreamResponse;
  }
}

Client Side

In this example, we utilize the TokenVaultConsentPopup component to show a pop-up that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You’ll first need to install the @auth0/ai-components package:
npx @auth0/ai-components add TokenVault
Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK:
./src/components/chat.tsx
"use client";

import { useChat } from "@ai-sdk/react";
import { useAgentChatInterruptions } from "@auth0/ai-cloudflare/react";
import { TokenVaultInterrupt } from "@auth0/ai/interrupts";
import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup";

export default function Chat() {

  const {
    messages: agentMessages,
    input: agentInput,
    handleInputChange: handleAgentInputChange,
    handleSubmit: handleAgentSubmit,
    addToolResult,
    clearHistory,
    toolInterrupt,
  } = useAgentChatInterruptions({
    agent,
    maxSteps: 5,
    id: threadID,
  });

  return (
    <div>
      {messages.map((message) => (
        <div key={message.id}>
          {message.role === "user" ? "User: " : "AI: "}
          {message.content}
        </div>
      ))}

      {TokenVaultInterrupt.isInterrupt(toolInterrupt) && (
        <TokenVaultConsentPopup
          interrupt={toolInterrupt}
          connectWidget={{
            title: "Check your availability in Google Calendar",
            description:"description ...",
            action: { label: "Check" },
          }}
        />
      )}

      <form onSubmit={handleSubmit}>
        <input value={input} placeholder="Say something..." onChange={(e) => setInput(e.target.value)} />
      </form>
    </div>
  );
}

Account Linking

If you're integrating with Google, but users in your app or agent can sign in using other methods (e.g., a username and password or another social provider), you'll need to link these identities into a single user account. Auth0 refers to this process as Account Linking.Account Linking logic and handling will vary depending on your app or agent. You can find an example of how to implement it in a Next.js chatbot app here. If you have questions or are looking for best practices, join our Discord and ask in the #auth0-for-gen-ai channel.

How-Tos