Agent Tasks
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.
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
}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 })
}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 })
}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 })
})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 })
})
}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 }
})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 })
}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.
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
Last updated on