Skip to main content
Docs

Warning

Agent Tasks are currently in beta. If you run into any issues, please reach out to our support team.

Agent Tasks provide a way to create authenticated sessions on behalf of users without going through the standard sign-in flow. When you create an Agent Task, Clerk returns a URL that, when visited, creates a session for the specified user and redirects to the URL of your choice.

This is useful for:

  • Automated end-to-end testing where you need a signed-in user
  • AI agent workflows that act on behalf of a user

Create an Agent Task

Use the clerkClient.agentTasks.create() method to create an Agent Task. The returned url can then be visited to establish the session.

example.js
import { createClerkClient } from '@clerk/backend'

const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY })

async function createAgentTask(request) {
  // Use the `request.auth` object to access `isAuthenticated` and the user's ID
  const { isAuthenticated, userId } = request.auth

  // Protect the route from unauthenticated users
  if (!isAuthenticated) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }

  const agentTask = await clerkClient.agentTasks.create({
    onBehalfOf: {
      userId,
    },
    permissions: '*',
    agentName: 'my-agent',
    taskDescription: 'Automated test login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  // agentTask.url is the URL to visit to authenticate the user
  return agentTask
}
app/api/example/route.ts
import { auth, clerkClient } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'

export async function POST() {
  // Use the `auth()` helper to access the `isAuthenticated` and the user's ID
  const { isAuthenticated, userId } = await auth()

  // Protect the route from unauthenticated users
  if (!isAuthenticated) {
    return new NextResponse('Unauthorized', { status: 401 })
  }

  // Instantiate the `clerkClient`
  const client = await clerkClient()

  // Use the `createAgentTask()` method to create the Agent Task
  const agentTask = await client.agentTasks.create({
    onBehalfOf: {
      userId,
    },
    permissions: '*',
    agentName: 'my-agent',
    taskDescription: 'Automated test login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  return NextResponse.json({ message: 'Agent Task created', agentTask })
}
src/api/example.ts
import type { APIRoute } from 'astro'
import { clerkClient } from '@clerk/astro/server'

export const POST: APIRoute = async (context) => {
  // Use the `locals.auth()` function to access the `isAuthenticated` and the user's ID
  const { isAuthenticated, userId } = context.locals.auth()

  // Protect the route from unauthenticated users
  if (!isAuthenticated) {
    return new Response('Unauthorized', { status: 401 })
  }

  // Use the `createAgentTask()` method to create the Agent Task
  const agentTask = await clerkClient(context).agentTasks.create({
    onBehalfOf: {
      userId,
    },
    permissions: '*',
    agentName: 'my-agent',
    taskDescription: 'Automated test login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  return new Response(JSON.stringify({ message: 'Agent Task created', agentTask }), { status: 200 })
}
public.ts
import { getAuth, clerkClient } from '@clerk/express'

app.post('/createAgentTask', async (req, res) => {
  // Use the `getAuth()` helper to access the `isAuthenticated` and the user's ID
  const { isAuthenticated, userId } = getAuth(req)

  // Protect the route from unauthenticated users
  if (!isAuthenticated) {
    return res.status(401).json({ error: 'Unauthorized' })
  }

  // Use the `createAgentTask()` method to create the Agent Task
  const agentTask = await clerkClient.agentTasks.create({
    onBehalfOf: {
      userId,
    },
    permissions: '*',
    agentName: 'my-agent',
    taskDescription: 'Automated test login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  res.status(200).json({ message: 'Agent Task created', agentTask })
})
src/routes/example.ts
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
import { clerkClient, getAuth } from '@clerk/fastify'

export const exampleRoutes = (fastify: FastifyInstance) => {
  fastify.post('/createAgentTask', async (req: FastifyRequest, res: FastifyReply) => {
    // Use the `getAuth()` helper to access the `isAuthenticated` and the user's ID
    const { isAuthenticated, userId } = getAuth(req)

    // Protect the route from unauthenticated users
    if (!isAuthenticated) {
      return res.status(401).json({ error: 'Unauthorized' })
    }

    // Use the `createAgentTask()` method to create the Agent Task
    const agentTask = await clerkClient.agentTasks.create({
      onBehalfOf: {
        userId,
      },
      permissions: '*',
      agentName: 'my-agent',
      taskDescription: 'Automated test login',
      redirectUrl: 'http://localhost:3000/dashboard',
    })

    res.status(200).json({ message: 'Agent Task created', agentTask })
  })
}
server/api/example.ts
import { clerkClient } from '@clerk/nuxt/server'

export default defineEventHandler(async (event) => {
  // Use the `event.context.auth()` function to access the `isAuthenticated` and the user's ID
  const { isAuthenticated, userId } = event.context.auth()

  // Protect the route from unauthenticated users
  if (!isAuthenticated) {
    return createError({ statusCode: 401, statusMessage: 'Unauthorized' })
  }

  // Use the `createAgentTask()` method to create the Agent Task
  const agentTask = await clerkClient(event).agentTasks.create({
    onBehalfOf: {
      userId,
    },
    permissions: '*',
    agentName: 'my-agent',
    taskDescription: 'Automated test login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  return { message: 'Agent Task created', agentTask }
})
app/routes/example.tsx
import { clerkClient, getAuth } from '@clerk/react-router/server'
import type { Route } from './+types/example'

export async function action(args: Route.ActionArgs) {
  // Use the `getAuth()` helper to access the `isAuthenticated` and the user's ID
  const { isAuthenticated, userId } = await getAuth(args)

  // Protect the route from unauthenticated users
  if (!isAuthenticated) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }

  // Use the `createAgentTask()` method to create the Agent Task
  const agentTask = await clerkClient(args).agentTasks.create({
    onBehalfOf: {
      userId,
    },
    permissions: '*',
    agentName: 'my-agent',
    taskDescription: 'Automated test login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  return Response.json({ message: 'Agent Task created', agentTask })
}
app/routes/api/example.tsx
import { json } from '@tanstack/react-start'
import { createFileRoute } from '@tanstack/react-router'
import { auth, clerkClient } from '@clerk/tanstack-react-start/server'

export const ServerRoute = createFileRoute('/api/example')({
  server: {
    handlers: {
      POST: async () => {
        // Use the `auth()` helper to access the `isAuthenticated` and the user's ID
        const { isAuthenticated, userId } = await auth()

        // Protect the route from unauthenticated users
        if (!isAuthenticated) {
          return json({ error: 'Unauthorized' }, { status: 401 })
        }

        // Use the `createAgentTask()` method to create the Agent Task
        const agentTask = await clerkClient().agentTasks.create({
          onBehalfOf: {
            userId,
          },
          permissions: '*',
          agentName: 'my-agent',
          taskDescription: 'Automated test login',
          redirectUrl: 'http://localhost:3000/dashboard',
        })

        return json({ message: 'Agent Task created', agentTask })
      },
    },
  },
})

In Playwright tests, instantiate the client with createClerkClient() from @clerk/backend rather than importing clerkClient from your framework SDK (e.g., @clerk/nextjs/server). Framework SDK exports aren't available outside your app's request context.

e2e/app.spec.ts
import { createClerkClient } from '@clerk/backend'
import { test, expect } from '@playwright/test'

const clerkClient = createClerkClient({
  secretKey: process.env.CLERK_SECRET_KEY,
})

test('authenticated user flow', async ({ page }) => {
  const agentTask = await clerkClient.agentTasks.create({
    onBehalfOf: {
      userId: 'user_xxx',
      // or { identifier: 'test@example.com' }
    },
    permissions: '*',
    agentName: 'test-agent',
    taskDescription: 'test-login',
    redirectUrl: 'http://localhost:3000/dashboard',
  })

  await page.goto(agentTask.url)
  await expect(page.locator('header')).toContainText('Welcome')
})

Revoke an Agent Task

If you need to invalidate an Agent Task before it's used, you can revoke it.

Feedback

What did you think of this content?

Last updated on