AgentOnboard Docs

Using with Supabase Auth

How to authenticate AI agents with Supabase Auth — map verified agent tokens to Supabase users and enable agent signups.

AgentOnboard works alongside Supabase Auth. Supabase handles sessions and Row Level Security (RLS) for human web users; AgentOnboard authenticates AI agents calling your API.


1. Verifying existing Supabase users

Use your Supabase client inside resolveAccount to look up the user by email:

app/api/notes/route.ts
import { createClient } from "@supabase/supabase-js";
import { requireAgentAccount } from "@agentonboard/sdk/next";

// Service role client for server-side lookups
const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!
);

export async function POST(request: Request) {
  const session = await requireAgentAccount(request, {
    audience: "notes.com",
    resolveAccount: async ({ email }) => {
      // Look up the user in your profiles or users table
      const { data } = await supabase
        .from("profiles")
        .select("id")
        .eq("email", email.toLowerCase())
        .maybeSingle();

      return data?.id ?? null;
    },
  });

  // Returns 401 or 403 automatically
  if (!session.ok) return session.response;

  // session.user is your Supabase user ID (UUID)
  return Response.json({ success: true, supabase_user_id: session.user });
}

2. Enabling agent signup with Supabase

To let an agent automatically provision an account in Supabase when visiting your signup route, use the Supabase Admin Auth API:

app/api/signup/route.ts
import { createClient } from "@supabase/supabase-js";
import { createAgentAccount } from "@agentonboard/sdk";

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!
);

export async function POST(request: Request) {
  const outcome = await createAgentAccount({
    token: request.headers.get("Authorization") ?? "",
    audience: "notes.com",
    resolveAccount: async ({ email }) => {
      const { data } = await supabase
        .from("profiles")
        .select("id")
        .eq("email", email.toLowerCase())
        .maybeSingle();
      return data?.id ?? null;
    },
    createAccount: async ({ email }) => {
      // Provision user via admin API with email_confirm: true
      const { data, error } = await supabase.auth.admin.createUser({
        email: email.toLowerCase(),
        email_confirm: true,
      });

      if (error) throw error;
      return data.user.id;
    },
  });

  if (!outcome.ok) {
    return Response.json(
      { code: outcome.code, error: outcome.error },
      { status: outcome.code === "RESOLVER_ERROR" ? 500 : 401 }
    );
  }

  return Response.json(
    { user_id: outcome.user, created: outcome.created },
    { status: 201 }
  );
}

email_confirm: true

Because AgentOnboard asserts that the human verified ownership of the inbox, you can safely set email_confirm: true without sending a duplicate confirmation email.

On this page