Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b7e5ea1
feat(agent-toolkit): Introduce @clerk/agent-toolkit package
nikosdouvlis Feb 11, 2025
592773f
feat(agent-toolkit): Introduce @clerk/agent-toolkit package
nikosdouvlis Feb 11, 2025
fa2a164
Merge remote-tracking branch 'origin/nikos/agent-toolkit' into nikos/…
nikosdouvlis Feb 11, 2025
b7cdac6
feat(agent-toolkit): Drop CJS
nikosdouvlis Feb 11, 2025
bd02552
Update LICENSE
nikosdouvlis Feb 11, 2025
e23bd19
Update .changeset/many-pumpkins-double.md
nikosdouvlis Feb 11, 2025
ca9b72b
Update .changeset/many-pumpkins-double.md
nikosdouvlis Feb 11, 2025
fd46df1
Update packages/agent-toolkit/README.md
nikosdouvlis Feb 11, 2025
773c4b9
Update packages/agent-toolkit/README.md
nikosdouvlis Feb 11, 2025
ef2b283
Update packages/agent-toolkit/README.md
nikosdouvlis Feb 11, 2025
b3e2bf2
Update packages/agent-toolkit/README.md
nikosdouvlis Feb 11, 2025
81d3728
Update packages/agent-toolkit/README.md
nikosdouvlis Feb 11, 2025
48c5cd9
Update packages/agent-toolkit/README.md
nikosdouvlis Feb 11, 2025
b75b0ac
Apply suggestions from code review
nikosdouvlis Feb 11, 2025
66508a0
Resolve comments
nikosdouvlis Feb 11, 2025
6b8ece9
Merge branch 'main' into nikos/agent-toolkit
nikosdouvlis Feb 11, 2025
40fa7f1
Resolve comments
nikosdouvlis Feb 11, 2025
2bb61db
Resolve comments
nikosdouvlis Feb 11, 2025
6cb815c
Merge branch 'main' into nikos/agent-toolkit
nikosdouvlis Feb 12, 2025
3dd4f21
Resolve comments
nikosdouvlis Feb 12, 2025
ca1f069
Merge branch 'main' into nikos/agent-toolkit
nikosdouvlis Feb 12, 2025
80d6835
Merge branch 'main' into nikos/agent-toolkit
nikosdouvlis Feb 12, 2025
a9913f2
chore(repo): Format
nikosdouvlis Feb 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/many-pumpkins-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@clerk/agent-toolkit': patch
---

Introduce `@clerk/agent-toolkit` package. The Clerk Agent Toolkit enables popular agent frameworks, including Vercel's AI SDK and LangChain, to integrate with Clerk using tools (also known as function calling).

This package exposes a subset of Clerk's functionality to agent frameworks, allowing you to build powerful agentic systems capable of managing users, user data, organizations, and more.

**Please note:** All relevant information and instructions on how to set it up can be found in the package's README. It's an early developer preview and can't be considered stable yet.

5 changes: 5 additions & 0 deletions .changeset/metal-gorillas-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/backend': patch
---

Adds an internal `raw()` getter method to the `User` resource that returns the raw JSON payload of the request that instantiated the resource.
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@ actions:

integration:
- integration/**

agent-toolkit:
- packages/agent-toolkit/**
21 changes: 21 additions & 0 deletions packages/agent-toolkit/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Clerk, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
230 changes: 230 additions & 0 deletions packages/agent-toolkit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
<p align="center">
<a href="https://clerk.com?utm_source=github&utm_medium=clerk_agent_toolkit" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://images.clerk.com/static/logo-dark-mode-400x400.png">
<img src="https://images.clerk.com/static/logo-light-mode-400x400.png" height="64">
</picture>
</a>
<br />
<h1 align="center">@clerk/agent-toolkit</h1>
</p>

<div align="center">

[![Chat on Discord](https://img.shields.io/discord/856971667393609759.svg?logo=discord)](https://clerk.com/discord)
[![Clerk documentation](https://img.shields.io/badge/documentation-clerk-green.svg)](https://clerk.com/docs?utm_source=github&utm_medium=clerk_agent_toolkit)
[![Follow on Twitter](https://img.shields.io/twitter/follow/ClerkDev?style=social)](https://twitter.com/intent/follow?screen_name=ClerkDev)

[Changelog](https://github.com/clerk/javascript/blob/main/packages/agent-toolkit/CHANGELOG.md)
·
[Report a Bug](https://github.com/clerk/javascript/issues/new?assignees=&labels=needs-triage&projects=&template=BUG_REPORT.yml)
·
[Request a Feature](https://feedback.clerk.com/roadmap)
·
[Get Help](https://clerk.com/contact/support?utm_source=github&utm_medium=clerk_agent_toolkit)

</div>

> [!IMPORTANT]
>
> Agent behavior is typically non-deterministic. Ensure you thoroughly test your integration and evaluate your application's performance. Additionally, consider scoping this toolkit's tools to specific users to limit resource access.
>
> If your app's code path is predetermined, it's always preferable to call APIs directly instead of using agents and tool calling.
>
> This SDK is recommended for testing purposes only unless you are confident in the agent's behavior and have implemented necessary security measures such as guardrails and best practices.

## Table of Contents

1. [Getting Started](#getting-started)
2. [Public APIs](#public-apis)
3. [Use with Vercel's AI SDK](#use-with-vercels-ai-sdk)
4. [Use with Langchain](#use-with-langchain)
5. [Advanced Usage](#advanced-usage)
6. [Support](#support)
Comment on lines +36 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub already generated this ToC by default so you could also leave it out completely


## Getting Started

Use this SDK to integrate [Clerk](https://clerk.com/?utm_source=github&utm_medium=clerk_agent_toolkit) into your agentic workflows. The Clerk Agent Toolkit enables popular agent frameworks, including Vercel's AI SDK and LangChain, to integrate with Clerk using tools (also known as function calling).

This package exposes a subset of Clerk's functionality to agent frameworks, allowing you to build powerful agentic systems capable of managing users, user data, organizations, and more.

## Public APIs

The Clerk Agent Toolkit package provides two main import paths:

- `@clerk/agent-toolkit/ai-sdk`: Helpers for integrating with Vercel's AI SDK.
- `@clerk/agent-toolkit/langchain`: Helpers for integrating with Langchain.

The toolkit offers the same tools and core APIs across frameworks, but their public interfaces may vary slightly to align with each framework's design:

- `createClerkToolkit(options)`: Instantiates a new Clerk toolkit.
- `toolkit.injectSessionClaims(systemPrompt)`: Injects session claims (`userId`, `sessionId`, `orgId`, etc.) into the system prompt, making them accessible to the AI model.
- `toolkit.users()`: Provides tools for managing users.
- `toolkit.organizations()`: Provides tools for managing organizations.
- `toolkit.allTools()`: Returns all available tools.
- `toolkit.toolMap()`: **(Langchain only)** Returns an object mapping available tools, useful for calling tools by name.

For more details on each tool, refer to the framework-specific directories or the [Clerk Backend API documentation](https://clerk.com/docs/reference/backend-api).

### Prerequisites

- `ai-sdk`: `"^3.4.7 || ^4.0.0"`, or `langchain`: `"^0.3.6"`
- An existing Clerk application. [Create your account for free](https://dashboard.clerk.com/sign-up?utm_source=github&utm_medium=clerk_agent_toolkit).
- An API key for an AI model compatible with Langchain

### Example Repository

- [Clerk AI SDK Example](https://github.com/clerk/agent-toolkit-example)

## Using Vercel's AI SDK

1. Install the Clerk Agent Toolkit package:

```shell
npm install @clerk/agent-toolkit
```

2. Set the Clerk secret key as an environment variable in your project. Ensure you also configure any required LLM model keys.

```
CLERK_SECRET_KEY=sk_
```

3. Import the helper from the `/ai-sdk` path, instantiate a new Clerk `toolkit`, and use it in your agent function:

```typescript
// Import the helper from the ai-sdk path
import { createClerkToolkit } from '@clerk/agent-toolkit/ai-sdk';
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { auth } from '@clerk/nextjs/server';
import { systemPrompt } from '@/lib/ai/prompts';

export const maxDuration = 30;

export async function POST(req: Request) {
const { messages } = await req.json();
// Optional - get the userId from the request
const { userId } = await auth.protect();

// Instantiate a new Clerk toolkit
// Optional - scope the toolkit to a specific user
const toolkit = await createClerkToolkit({ context: { userId } });

const result = streamText({
model: openai('gpt-4o'),
messages,
// Optional - inject session claims into the system prompt
system: toolkit.injectSessionClaims(systemPrompt),
tools: {
// Provide the tools you want to use
...toolkit.users(),
...toolkit.organizations(),
},
});

return result.toDataStreamResponse();
}
```

## Using Langchain

1. Install the Clerk Agent Toolkit package:

```shell
npm install @clerk/agent-toolkit
```

2. Set the Clerk secret key as an environment variable:

```shell
CLERK_SECRET_KEY=sk_
```

3. Import the helper from the `/langchain` path, instantiate a new Clerk `toolkit`, and use it in your agent function:

```typescript
// Import the helper from the langchain path
import { createClerkToolkit } from '@clerk/agent-toolkit/langchain';
import { ChatOpenAI } from '@langchain/openai';
import { auth } from '@clerk/nextjs/server';
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
import { LangChainAdapter } from 'ai';
import { systemPrompt } from '@/lib/ai/prompts';

export const maxDuration = 30;

export async function POST(req: Request) {
const { prompt } = await req.json();
const { userId } = await auth.protect();

// Instantiate a new Clerk toolkit
// Optional - scope the toolkit to a specific user
const toolkit = await createClerkToolkit({ context: { userId } });

const model = new ChatOpenAI({ model: 'gpt-4o', temperature: 0 });

// Bind the tools you want to use to the model
const modelWithTools = model.bindTools(toolkit.users());

const messages = [new SystemMessage(toolkit.injectSessionClaims(systemPrompt)), new HumanMessage(prompt)];
const aiMessage = await modelWithTools.invoke(messages);
messages.push(aiMessage);

for (const toolCall of aiMessage.tool_calls || []) {
// Call the selected tool
const selectedTool = toolkit.toolMap()[toolCall.name];
const toolMessage = await selectedTool.invoke(toolCall);
messages.push(toolMessage);
}

// To simplify the setup, this example uses the ai-sdk langchain adapter
// to stream the results back to the /langchain page.
// For more details, see: https://sdk.vercel.ai/providers/adapters/langchain
const stream = await modelWithTools.stream(messages);
return LangChainAdapter.toDataStreamResponse(stream);
}
```

## Advanced Usage

### Using a Custom `clerkClient`

If you need to set the Clerk secret key dynamically or use different Clerk instances, pass a custom `clerkClient`. Install `@clerk/backend` into your project and call the `createClerkClient` function:

```typescript
import { createClerkToolkit } from '@clerk/agent-toolkit/ai-sdk';
import { createClerkClient } from '@clerk/backend';

export async function POST(req: Request) {
// Create a new Clerk client
const clerkClient = createClerkClient({ secretKey: 'sk_' });

// Instantiate a new Clerk toolkit with the custom client
const toolkit = await createClerkToolkit({ clerkClient });

// Use the toolkit as usual
const result = streamText({
model: openai('gpt-4o'),
messages,
tools: toolkit.users(),
});
}
```

## Support

You can get in touch with us in any of the following ways:

- Join our official community [Discord server](https://clerk.com/discord)
- On [our support page](https://clerk.com/contact/support?utm_source=github&utm_medium=clerk_agent_toolkit)

## Contributing

We're open to all community contributions! If you'd like to contribute in any way, please read [our contribution guidelines](https://github.com/clerk/javascript/blob/main/docs/CONTRIBUTING.md) and [code of conduct](https://github.com/clerk/javascript/blob/main/docs/CODE_OF_CONDUCT.md).

## License

This project is licensed under the **MIT license**.

See [LICENSE](https://github.com/clerk/javascript/blob/main/packages/agent-toolkit/LICENSE) for more information.
67 changes: 67 additions & 0 deletions packages/agent-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"name": "@clerk/agent-toolkit",
"version": "0.0.1",
"private": true,
"description": "Clerk Toolkit for AI Agents",
"homepage": "https://clerk.com/",
"bugs": {
"url": "https://github.com/clerk/javascript/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/clerk/javascript.git",
"directory": "packages/agent-toolkit"
},
"license": "MIT",
"author": "Clerk",
"sideEffects": false,
"type": "module",
"exports": {
"./langchain": {
"types": "./dist/langchain/index.d.ts",
"import": "./dist/langchain/index.js"
},
"./ai-sdk": {
"types": "./dist/ai-sdk/index.d.ts",
"import": "./dist/ai-sdk/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup --env.NODE_ENV production",
"clean": "rimraf ./dist",
"dev": "tsup --watch",
"lint": "eslint src",
"lint:attw": "attw --pack . --ignore-rules cjs-resolves-to-esm no-resolution",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these --ignore-rules necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. I think we need to update attw to use the --profile node16 option, but that's not available ATM locally.
I will open a new PR for this

"lint:publint": "publint"
},
"dependencies": {
"@clerk/backend": "workspace:^",
"@clerk/shared": "workspace:^",
"@clerk/types": "workspace:^",
"zod": "^3.24.1"
},
"devDependencies": {
"esbuild-plugin-file-path-extensions": "^2.1.4"
},
"peerDependencies": {
"@langchain/core": "^0.3.6",
"ai": "^3.4.7 || ^4.0.0"
},
"peerDependenciesMeta": {
"@langchain/core": {
"optional": true
},
"ai": {
"optional": true
}
},
"engines": {
"node": ">=20"
},
"publishConfig": {
"access": "public"
}
}
15 changes: 15 additions & 0 deletions packages/agent-toolkit/src/ai-sdk/adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Tool } from 'ai';
import { tool } from 'ai';

import type { SdkAdapter } from '../lib/types';

/**
* Converts a `ClerkTool` to an AI SDK `Tool`.
*/
export const adapter: SdkAdapter<Tool> = (clerkClient, context, clerkTool) => {
return tool({
description: clerkTool.description,
parameters: clerkTool.parameters,
execute: clerkTool.bindRunnable(clerkClient, context),
});
};
Loading