Skip to content

Commit 1c8e905

Browse files
AIDX-313 Add update for Cloudflare example docs
1 parent 356aac4 commit 1c8e905

File tree

4 files changed

+457
-215
lines changed

4 files changed

+457
-215
lines changed

auth4genai/snippets/get-started/cloudflare-agents-js/call-your-api.mdx

Lines changed: 163 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,27 @@ npm install hono \
4242

4343
In the root directory of your project, copy the `.dev.vars.example` into `.dev.vars` file and configure the Auth0 and OpenAI variables.
4444

45+
```bash .dev.vars wrap lines
46+
# ...
47+
# You can use any provider of your choice supported by Vercel AI
48+
OPENAI_API_KEY="OPENAI API KEY"
49+
50+
SESSION_STORE=cloudflare-kv
51+
SESSION_STORE_NAMESPACE=Session
52+
53+
54+
#auth0
55+
AUTH0_DOMAIN="YOUR-ACCOUNT.us.auth0.com"
56+
AUTH0_CLIENT_ID="YOUR CLIENT ID"
57+
AUTH0_CLIENT_SECRET="YOUR CLIENT SECRET"
58+
AUTH0_SESSION_ENCRYPTION_KEY="RANDOM 32 CHARS"
59+
AUTH0_AUDIENCE="YOUR AUDIENCE"
60+
61+
BASE_URL="http://localhost:3000"
62+
```
63+
64+
If you use another provider for your LLM, adjust the variable name in `.dev.vars` accordingly.
65+
4566
### Define a tool to call your API
4667

4768
In this step, you'll create a Vercel AI tool to make the first-party API call to the Auth0 API. You will do the same for third-party APIs.
@@ -53,41 +74,159 @@ Since the Agent defined in the class Chat in `src/agent/chat.ts` uses the **Auth
5374
The tool we are defining here uses the same access token to call Auth0's [`/userinfo`](https://auth0.com/docs/api/authentication/user-profile/get-user-info) endpoint.
5475

5576
```tsx src/agent/tools.ts wrap lines
56-
const getUserInfoTool = tool({
57-
description: "Get information about the current logged in user.",
58-
parameters: z.object({}),
59-
execute: async () => {
60-
const { agent } = getCurrentAgent<Chat>();
61-
const tokenSet = agent?.getCredentials();
62-
if (!tokenSet) {
63-
return "There is no user logged in.";
77+
/**
78+
* Tool definitions for the AI chat agent
79+
* Tools can either require human confirmation or execute automatically
80+
*/
81+
import { tool } from "ai";
82+
import { z } from "zod";
83+
84+
import { getCurrentAgent } from "agents";
85+
import { unstable_scheduleSchema } from "agents/schedule";
86+
import { format, toZonedTime } from "date-fns-tz";
87+
import { buyStock } from "./auth0-ai-sample-tools/buy-stock";
88+
import { checkUsersCalendar } from "./auth0-ai-sample-tools/check-user-calendar";
89+
90+
/**
91+
* Weather information tool that requires human confirmation
92+
* When invoked, this will present a confirmation dialog to the user
93+
* The actual implementation is in the executions object below
94+
*/
95+
const getWeatherInformation = tool({
96+
description: "show the weather in a given city to the user",
97+
inputSchema: z.object({ city: z.string() }),
98+
});
99+
100+
/**
101+
* Local time tool that executes automatically
102+
* Since it includes an execute function, it will run without user confirmation
103+
* This is suitable for low-risk operations that don't need oversight
104+
*/
105+
const getLocalTime = tool({
106+
description: "get the local time for a specified location",
107+
inputSchema: z.object({
108+
timeZone: z.string().describe("IANA time zone name"),
109+
}),
110+
execute: async ({ timeZone: location }) => {
111+
const now = new Date();
112+
const zonedDate = toZonedTime(now, location);
113+
const output = format(zonedDate, "yyyy-MM-dd HH:mm:ssXXX", {
114+
timeZone: location,
115+
});
116+
return output;
117+
},
118+
});
119+
120+
const scheduleTask = tool({
121+
description: "A tool to schedule a task to be executed at a later time",
122+
inputSchema: unstable_scheduleSchema,
123+
execute: async ({ when, description }) => {
124+
const { agent } = getCurrentAgent();
125+
126+
function throwError(msg: string): string {
127+
throw new Error(msg);
128+
}
129+
if (when.type === "no-schedule") {
130+
return "Not a valid schedule input";
131+
}
132+
const input =
133+
when.type === "scheduled"
134+
? when.date // scheduled
135+
: when.type === "delayed"
136+
? when.delayInSeconds // delayed
137+
: when.type === "cron"
138+
? when.cron // cron
139+
: throwError("not a valid schedule input");
140+
try {
141+
agent!.schedule(input!, "executeTask" as keyof typeof agent, description);
142+
} catch (error) {
143+
console.error("error scheduling task", error);
144+
return `Error scheduling task: ${error}`;
64145
}
146+
return `Task scheduled for type "${when.type}" : ${input}`;
147+
},
148+
});
65149

66-
const response = await fetch(
67-
`https://${process.env.AUTH0_DOMAIN}/userinfo`,
68-
{
69-
headers: {
70-
Authorization: `Bearer ${tokenSet.access_token}`,
71-
},
72-
}
73-
);
150+
/**
151+
* Tool to list all scheduled tasks
152+
* This executes automatically without requiring human confirmation
153+
*/
154+
const getScheduledTasks = tool({
155+
description: "List all tasks that have been scheduled",
156+
inputSchema: z.object({}),
157+
execute: async () => {
158+
const { agent } = getCurrentAgent();
74159

75-
if (response.ok) {
76-
return { result: await response.json() };
160+
try {
161+
const tasks = agent!.getSchedules();
162+
if (!tasks || tasks.length === 0) {
163+
return "No scheduled tasks found.";
164+
}
165+
return tasks;
166+
} catch (error) {
167+
console.error("Error listing scheduled tasks", error);
168+
return `Error listing scheduled tasks: ${error}`;
77169
}
170+
},
171+
});
78172

79-
return "I couldn't verify your identity";
173+
/**
174+
* Tool to cancel a scheduled task by its ID
175+
* This executes automatically without requiring human confirmation
176+
*/
177+
const cancelScheduledTask = tool({
178+
description: "Cancel a scheduled task using its ID",
179+
inputSchema: z.object({
180+
taskId: z.string().describe("The ID of the task to cancel"),
181+
}),
182+
execute: async ({ taskId }) => {
183+
const { agent } = getCurrentAgent();
184+
try {
185+
await agent!.cancelSchedule(taskId);
186+
return `Task ${taskId} has been successfully canceled.`;
187+
} catch (error) {
188+
console.error("Error canceling scheduled task", error);
189+
return `Error canceling task ${taskId}: ${error}`;
190+
}
80191
},
81192
});
193+
194+
/**
195+
* Export all available tools
196+
* These will be provided to the AI model to describe available capabilities
197+
*/
198+
export const tools = {
199+
getWeatherInformation,
200+
getLocalTime,
201+
scheduleTask,
202+
getScheduledTasks,
203+
cancelScheduledTask,
204+
checkUsersCalendar,
205+
buyStock,
206+
};
207+
208+
/**
209+
* Implementation of confirmation-required tools
210+
* This object contains the actual logic for tools that need human approval
211+
* Each function here corresponds to a tool above that doesn't have an execute function
212+
*/
213+
export const executions = {
214+
getWeatherInformation: async ({ city }: { city: string }) => {
215+
console.log(`Getting weather information for ${city}`);
216+
return `The weather in ${city} is sunny`;
217+
},
218+
};
82219
```
83220

84-
Then in the `tools` export of the `src/agent/chat.ts` file, add the `getUserInfoTool` to the tools array:
221+
Then in the `tools` export of the `src/agent/chat.ts` file, add the `tools` to the `allTools` array:
85222

86223
```tsx src/agent/chat.ts wrap lines
87-
export const tools = {
88-
// Your other tools...
89-
getUserInfoTool,
90-
};
224+
async onChatMessage() {
225+
const allTools = {
226+
...tools,
227+
...(this.mcp?.getAITools?.() ?? {}),
228+
};
229+
... // The rest of the code
91230
```
92231
93232
### Test your application

auth4genai/snippets/how-tos/github/cloudflare-agents.mdx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,50 +19,55 @@ npm install @auth0/ai-vercel @auth0/ai-cloudflare @auth0/ai
1919

2020
Then, you need to initialize Auth0 AI and set up the connection to request access tokens with the required Github scopes.
2121

22-
```typescript ./src/lib/auth0-ai.ts wrap lines
22+
```typescript ./src/agent/auth0-ai.ts wrap lines
2323
import { Auth0AI, setGlobalAIContext } from "@auth0/ai-vercel";
2424
import { getCurrentAgent } from "agents";
25-
import type { Chat } from "./chat";
25+
26+
setGlobalAIContext(() => ({ threadID: getAgent().name }));
27+
28+
const auth0AI = new Auth0AI({
29+
store: () => {
30+
return (getAgent() as any).auth0AIStore;
31+
},
32+
});
2633

2734
const getAgent = () => {
28-
const { agent } = getCurrentAgent<Chat>();
35+
const { agent } = getCurrentAgent();
2936
if (!agent) {
3037
throw new Error("No agent found");
3138
}
3239
return agent;
3340
};
3441

35-
setGlobalAIContext(() => ({ threadID: getAgent().name }));
36-
37-
const auth0AI = new Auth0AI();
42+
const refreshToken = async () => {
43+
const credentials = (getAgent() as any).getCredentials();
44+
return credentials?.refresh_token;
45+
};
3846

3947
export const withGitHub = auth0AI.withTokenVault({
48+
refreshToken,
4049
connection: "github",
4150
scopes: ["repo"],
42-
refreshToken: async () => {
43-
const credentials = getAgent().getCredentials();
44-
return credentials?.refresh_token;
45-
},
4651
});
4752
```
4853

4954
### 2. Integrate your tool with the Github API
5055

5156
Wrap your tool using the Auth0 AI SDK to obtain an access token for the Github API.
5257

53-
```typescript ./src/agent/tools/listRepositories.ts wrap lines highlight={2-4,9,15,19-21,31-33}
58+
```typescript ./src/agent/tools/listRepositories.ts wrap lines highlight={6-7,9,15,19-21,28-30}
59+
import { tool } from "ai";
60+
import { z } from "zod/v3";
61+
5462
import { Octokit, RequestError } from "octokit";
5563
import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel";
5664
import { TokenVaultError } from "@auth0/ai/interrupts";
57-
import { withGitHub } from "@/lib/auth0-ai";
58-
import { tool } from "ai";
59-
import { z } from "zod";
60-
65+
import { withGitHub } from "@/agent/auth0-ai";
6166

6267
export const listRepositories = withGitHub(
6368
tool({
6469
description: "List respositories for the current user on GitHub",
65-
parameters: z.object({}),
70+
inputSchema: z.object({}),
6671
execute: async () => {
6772
// Get the access token from Auth0 AI
6873
const accessToken = getAccessTokenFromTokenVault();
@@ -72,17 +77,14 @@ export const listRepositories = withGitHub(
7277
const octokit = new Octokit({
7378
auth: accessToken,
7479
});
75-
7680
const { data } = await octokit.rest.repos.listForAuthenticatedUser();
7781

7882
return data.map((repo) => repo.name);
7983
} catch (error) {
80-
console.log("Error", error);
81-
8284
if (error instanceof RequestError) {
8385
if (error.status === 401) {
8486
throw new TokenVaultError(
85-
`Authorization required to access the Token Vault connection`
87+
`Authorization required to access the Token Vault`
8688
);
8789
}
8890
}
@@ -92,6 +94,7 @@ export const listRepositories = withGitHub(
9294
},
9395
})
9496
);
97+
9598
```
9699

97100
### 3. Handle authentication redirects

0 commit comments

Comments
 (0)