Skip to main content
Auth0 for AI Agents enables AI agents to asynchronously authorize users using the Client-Initiated Backchannel Authentication Flow (CIBA). AI agents can work in the background, only notifying the user when needed for critical actions. When you add secure human-in-the-loop approvals to your AI agent workflows, you can use Auth0 to request the user’s permission to complete an authorization request. The AI agent can render rich authorization data in the consent prompt so the user knows exactly what they’re authorizing. By the end of this quickstart, you should have an AI agent integrated with the Auth0 AI SDK that can request to buy products from an online shop on the user’s behalf.

What you’ll learn

  • Async Authorization: Use CIBA to let AI agents get user consent securely in the background.
  • User Approvals: Add Auth0 AI SDK for clear, human-in-the-loop authorization.
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

OpenAI Platform

  • https://mintlify.s3.us-west-1.amazonaws.com/auth0-genai-feat-add-diagrams-modal-with-steps/img/nextjs-light.svg Next.js
  • https://mintlify.s3.us-west-1.amazonaws.com/auth0-genai-feat-add-diagrams-modal-with-steps/img/node-light.svg Node.js

Getting started using AI

To get started quickly:
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

Install dependencies

In the root directory of your project, install the following dependencies:
  • @auth0/ai-vercel: Auth0 AI SDK for AI SDK built for AI agents powered by the AI SDK.
  • ai: Core AI SDK module that interacts with various AI model providers.
  • @ai-sdk/openai: OpenAI provider for the AI SDK.
  • @ai-sdk/react: React UI components for the AI SDK.
  • zod: TypeScript-first schema validation library.
npm install @auth0/ai-vercel@4 ai@5.0.33 @ai-sdk/openai@2.0.24 @ai-sdk/react@2.0.33 zod@3.25.76
2

Update the environment file

Copy the .env.example file to .env.local and update the variables with your Auth0 credentials. You can find your Auth0 domain, client ID, and client secret in the application you created in the Auth0 Dashboard.
3

Set up HITL approvals

Integrate the Auth0 AI SDK into your application to secure your async AI agent workflow. For this quickstart, we will use a blocking request flow. In real use cases, often an asynchronous flow is preferred.

Configure the Auth0 AI SDK

To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, withAsyncAuthorization(). Let’s create a helper function to wrap the tool with the Async authorizer.Create a file at src/lib/auth0-ai.ts and instantiate a new Auth0 AI SDK client:
src/lib/auth0-ai.ts
import { Auth0AI } from "@auth0/ai-vercel";
import { AccessDeniedInterrupt } from "@auth0/ai/interrupts";

import { getUser } from "./auth0";

const auth0AI = new Auth0AI();

// Async Authorization flow for user confirmation
export const withAsyncAuthorization = auth0AI.withAsyncAuthorization({
  userID: async () => {
    const user = await getUser();
    return user?.sub as string;
  },
  bindingMessage: async ({ product, qty }) =>
    `Do you want to buy ${qty} ${product}`,
  scopes: ["openid", "product:buy"], // add any scopes you want to use with your API
  audience: process.env["SHOP_API_AUDIENCE"]!,

  /**
   * Controls how long the authorization request is valid for.
   */
  // requestedExpiry: 301,

  /**
   * The behavior when the authorization request is made.
   *
   * - `block`: The tool execution is blocked until the user completes the authorization.
   * - `interrupt`: The tool execution is interrupted until the user completes the authorization.
   * - a callback: Same as "block" but give access to the auth request and executing logic.
   *
   * Defaults to `interrupt`.
   *
   * When this flag is set to `block`, the execution of the tool awaits
   * until the user approves or rejects the request.
   * Given the asynchronous nature of the CIBA flow, this mode
   * is only useful during development.
   *
   * In practice, the process that is awaiting the user confirmation
   * could crash or timeout before the user approves the request.
   */
  onAuthorizationRequest: async (authReq, creds) => {
    console.log(`An authorization request was sent to your mobile device.`);
    await creds;
    console.log(`Thanks for approving the order.`);
  },

  onUnauthorized: async (e: Error) => {
    if (e instanceof AccessDeniedInterrupt) {
      return "The user has denied the request";
    }
    return e.message;
  },
});
This will intercept the tool call to initiate a CIBA request:
  • The CIBA request includes the user ID that will approve the request.
  • Auth0 sends the user a mobile push notification. The AI agent polls the /token endpoint for a user response.
  • The mobile application retrieves the bindingMessage containing the consent details, in this case, the details of the product to purchase.
  • The user responds to the request:
    • If the request is approved, the tool execution will continue.
    • If the request is rejected, the tool execution will not continue.
CIBA sequence diagram
Next, add the following code to src/lib/auth0.ts:
src/lib/auth0.ts
//... existing code
export const getUser = async () => {
  const session = await auth0.getSession();
  return session?.user;
};

Require async authorization for your tool

In this example, we wrap a tool that buys products on the user’s behalf. When the user approves the transaction, the Auth0 AI SDK retrieves an access token to call the shop’s API. Upon completing the CIBA flow, the AI agent responds with a message confirming the purchase.The Auth0 AI SDK returns an error response if the user denies the transaction.Now, create and wrap the tool with the Async authorizer. Create a file src/lib/tools/shop-online.ts and add the following code:
src/lib/tools/shop-online.ts
import { tool } from "ai";
import { z } from "zod";

import { getAsyncAuthorizationCredentials } from "@auth0/ai-vercel";
import { withAsyncAuthorization } from "../auth0-ai";

export const shopOnlineTool = withAsyncAuthorization(
  tool({
    description: "Tool to buy products online",
    parameters: z.object({
      product: z.string(),
      qty: z.number(),
      priceLimit: z.number().optional(),
    }),
    execute: async ({ product, qty, priceLimit }) => {
      console.log(`Ordering ${qty} ${product} with price limit ${priceLimit}`);

      const apiUrl = process.env["SHOP_API_URL"]!;

      if (!apiUrl) {
        // No API set, mock a response or return error
        return `Ordered ${qty} ${product}`;
      }

      const headers = {
        "Content-Type": "application/json",
        Authorization: "",
      };
      const body = {
        product,
        qty,
        priceLimit,
      };

      const credentials = getAsyncAuthorizationCredentials();
      const accessToken = credentials?.accessToken;

      if (accessToken) {
        headers["Authorization"] = "Bearer " + accessToken;
      }

      const response = await fetch(apiUrl, {
        method: "POST",
        headers: headers,
        body: JSON.stringify(body),
      });

      return response.statusText;
    },
  })
);
4

Update environment variables

You need to obtain an API Key from OpenAI or another provider to use an LLM.If you want to use an API, it must be registered with Auth0 and have a valid audience.Update the .env.local file with the following variables:
.env.local
# ... existing variables
# You can use any provider of your choice supported by AI SDK
OPENAI_API_KEY="YOUR_API_KEY"

# API (OPTIONAL)
SHOP_API_URL=<your-shop-api-url>
SHOP_API_AUDIENCE=sample-shop-api
5

Integrate the tool

Call the tool from your AI app to make purchases. Update the src/app/api/chat/route.ts file with the following code:
src/app/api/chat/route.ts
//...
import { setAIContext } from "@auth0/ai-vercel";
import { shopOnlineTool } from "@/lib/tools/shop-online";

//...
export async function POST(req: NextRequest) {
  const { id, messages }: { id: string; messages: Array<UIMessage> } = await req.json();

  const tools = { shopOnlineTool };

  setAIContext({ threadID: id });

  const stream = createUIMessageStream({
    async execute({ writer }) {
      const result = streamText({
        model: openai.chat('gpt-4o-mini'),
        system: AGENT_SYSTEM_TEMPLATE,
        messages: convertToModelMessages(messages),
        tools,
      });

      writer.merge(
        result.toUIMessageStream({
          sendReasoning: true,
        }),
      );
    },
  });

  return createUIMessageStreamResponse({ stream });
}
//...
6

Test the application

Start the application with npm run dev. Then, navigate to http://localhost:3000.You can ask the AI agent to buy a product, for example, “Buy an XYZ phone.” Now, look for a push notification from the Auth0 Guardian app or your custom app integrated with the Auth0 Guardian SDK on your mobile device. Once you approve the notification, you should see the tool being executed and a response from the agent.