├── card-issue-agent ├── src │ ├── client │ │ ├── vite-env.d.ts │ │ ├── main.tsx │ │ ├── App.tsx │ │ ├── components │ │ │ └── ui │ │ │ │ ├── textarea.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── code-block.tsx │ │ │ │ ├── markdown.tsx │ │ │ │ ├── message.tsx │ │ │ │ ├── prompt-suggestion.tsx │ │ │ │ ├── prompt-input.tsx │ │ │ │ └── chat-container.tsx │ │ ├── index.css │ │ └── Chat.tsx │ ├── lib │ │ └── utils.ts │ └── agent │ │ ├── api.ts │ │ ├── helper.ts │ │ ├── app.ts │ │ ├── constants.ts │ │ ├── tools.ts │ │ └── index.ts ├── public │ ├── knock-logo.png │ ├── slope-logo.png │ └── vite.svg ├── tsconfig.worker.json ├── tsconfig.json ├── index.html ├── .gitignore ├── components.json ├── vite.config.ts ├── tsconfig.node.json ├── tsconfig.app.json ├── eslint.config.js ├── README.md ├── wrangler.json └── package.json ├── agent-sdk-chat-with-approval ├── .env.example ├── src │ ├── client │ │ ├── vite-env.d.ts │ │ ├── main.tsx │ │ ├── Notifications.tsx │ │ ├── index.css │ │ └── App.tsx │ ├── lib │ │ └── utils.ts │ ├── components │ │ └── ui │ │ │ ├── textarea.tsx │ │ │ ├── avatar.tsx │ │ │ ├── tooltip.tsx │ │ │ ├── button.tsx │ │ │ ├── code-block.tsx │ │ │ ├── markdown.tsx │ │ │ ├── message.tsx │ │ │ ├── prompt-suggestion.tsx │ │ │ ├── prompt-input.tsx │ │ │ └── chat-container.tsx │ └── agent │ │ ├── tools.ts │ │ ├── helper.ts │ │ └── index.ts ├── tsconfig.worker.json ├── tsconfig.json ├── index.html ├── .gitignore ├── components.json ├── vite.config.ts ├── tsconfig.node.json ├── tsconfig.app.json ├── eslint.config.js ├── public │ └── vite.svg ├── README.md ├── wrangler.json └── package.json ├── README.md └── LICENSE /card-issue-agent/src/client/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/.env.example: -------------------------------------------------------------------------------- 1 | VITE_KNOCK_PUBLIC_KEY= 2 | VITE_KNOCK_FEED_ID= -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/src/client/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /card-issue-agent/public/knock-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knocklabs/ai-agent-examples/HEAD/card-issue-agent/public/knock-logo.png -------------------------------------------------------------------------------- /card-issue-agent/public/slope-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knocklabs/ai-agent-examples/HEAD/card-issue-agent/public/slope-logo.png -------------------------------------------------------------------------------- /card-issue-agent/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /card-issue-agent/tsconfig.worker.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.node.json", 3 | "compilerOptions": { 4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo", 5 | "types": ["vite/client", "./worker-configuration.d.ts"] 6 | }, 7 | "include": ["src/worker"] 8 | } 9 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/tsconfig.worker.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.node.json", 3 | "compilerOptions": { 4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo", 5 | "types": ["vite/client", "./worker-configuration.d.ts"] 6 | }, 7 | "include": ["src/worker"] 8 | } 9 | -------------------------------------------------------------------------------- /card-issue-agent/src/client/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App.tsx"; 5 | 6 | createRoot(document.getElementById("root")!).render( 7 | 8 | 9 | , 10 | ); 11 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/src/client/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App.tsx"; 5 | 6 | createRoot(document.getElementById("root")!).render( 7 | 8 | 9 | , 10 | ); 11 | -------------------------------------------------------------------------------- /card-issue-agent/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" }, 6 | { "path": "./tsconfig.worker.json" } 7 | ], 8 | "compilerOptions": { 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | }, 13 | "types": ["@cloudflare/workers-types/2023-07-01"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" }, 6 | { "path": "./tsconfig.worker.json" } 7 | ], 8 | "compilerOptions": { 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | }, 13 | "types": ["@cloudflare/workers-types/2023-07-01"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /card-issue-agent/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Knock + Cloudflare Agent HITL example 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Knock + Cloudflare Agent HITL example 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /card-issue-agent/src/agent/api.ts: -------------------------------------------------------------------------------- 1 | export type IssuedCard = { 2 | cardId: string; 3 | last4: string; 4 | expiry: string; 5 | userId: string; 6 | name: string; 7 | }; 8 | 9 | export async function issueCard(userId: string, name: string) { 10 | return { 11 | cardId: `card_${Math.random().toString(36).substring(2, 15)}`, 12 | userId, 13 | name, 14 | last4: "4242", 15 | expiry: "12/2028", 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /card-issue-agent/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # wrangler files 27 | .wrangler 28 | .dev.vars* 29 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # wrangler files 27 | .wrangler 28 | .dev.vars* 29 | -------------------------------------------------------------------------------- /card-issue-agent/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/client/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/client/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /card-issue-agent/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import tailwindcss from "@tailwindcss/vite"; 3 | import { defineConfig } from "vite"; 4 | import react from "@vitejs/plugin-react"; 5 | import { cloudflare } from "@cloudflare/vite-plugin"; 6 | 7 | export default defineConfig({ 8 | plugins: [react(), cloudflare(), tailwindcss()], 9 | server: { 10 | allowedHosts: ["26e9-47-185-68-94.ngrok-free.app", "localhost"], 11 | }, 12 | resolve: { 13 | alias: { 14 | "@": path.resolve(__dirname, "./src"), 15 | }, 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import tailwindcss from "@tailwindcss/vite"; 3 | import { defineConfig } from "vite"; 4 | import react from "@vitejs/plugin-react"; 5 | import { cloudflare } from "@cloudflare/vite-plugin"; 6 | 7 | export default defineConfig({ 8 | plugins: [react(), cloudflare(), tailwindcss()], 9 | server: { 10 | allowedHosts: ["a8b8-141-157-241-19.ngrok-free.app", "localhost"], 11 | }, 12 | resolve: { 13 | alias: { 14 | "@": path.resolve(__dirname, "./src"), 15 | }, 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Knock Agent Toolkit examples 2 | 3 | A repository of AI Agent examples integrating Knock's [Agent Toolkit](https://docs.knock.app/developer-tools/agent-toolkit) across various Agent frameworks and platforms. 4 | 5 | You can use the [Knock Agent Toolkit](https://github.com/knocklabs/agent-toolkit) to integrate Knock into Agent applications, giving your Agent the ability to send cross-channel messaging and easily power deferred tool executions for human-in-the-loop interactions. 6 | 7 | ## Examples 8 | 9 | - [Cloudflare Agent SDK + Vercel AI SDK + HITL approval](/agent-sdk-chat-with-approval/README.md) 10 | -------------------------------------------------------------------------------- /card-issue-agent/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedSideEffectImports": true 22 | }, 23 | "include": ["vite.config.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedSideEffectImports": true 22 | }, 23 | "include": ["vite.config.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /card-issue-agent/src/client/App.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { generateId } from "ai"; 4 | import { useLocalStorage } from "usehooks-ts"; 5 | import { useCallback, useEffect } from "react"; 6 | import Chat from "./Chat"; 7 | 8 | function App() { 9 | const [userId, setUserId] = useLocalStorage( 10 | "userId", 11 | undefined 12 | ); 13 | 14 | const resetUserId = useCallback(() => { 15 | setUserId(generateId()); 16 | }, [setUserId]); 17 | 18 | useEffect(() => { 19 | // Set the initial userId if it's not set 20 | if (!userId) resetUserId(); 21 | }, [resetUserId, userId]); 22 | 23 | return userId ? ( 24 | 25 | ) : null; 26 | } 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /card-issue-agent/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedSideEffectImports": true 24 | }, 25 | "include": ["src/client"] 26 | } 27 | -------------------------------------------------------------------------------- /agent-sdk-chat-with-approval/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedSideEffectImports": true 24 | }, 25 | "include": ["src/client"] 26 | } 27 | -------------------------------------------------------------------------------- /card-issue-agent/src/client/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 | return ( 7 |