Here is how I did…
Python Server for Serving Client-IDs
# server.py
import fastapi
import openai
from rich import print
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from openai import OpenAI
import os
# Check the versions of the all libraries
print(f"FastAPI version: {fastapi.__version__}")
print(f"OpenAI version: {openai.__version__}")
WORKFLOW_ID = "YOUR WORKFLOW ID FROM AGENT PLATFORM"
app = FastAPI()
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allow all origins for local testing
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
@app.post("/api/chatkit/session")
def create_chatkit_session():
session = client.beta.chatkit.sessions.create(
user="user",
workflow={
"id": WORKFLOW_ID
},
)
return { "client_secret": session.client_secret }
HTML-Vanilla JS
<!-- Main.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatKit Demo</title>
<script src="https://cdn.platform.openai.com/deployments/chatkit/chatkit.js" async></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f5f5f5;
}
#chat-container {
width: 100%;
max-width: 400px;
height: 600px;
}
#status {
position: fixed;
top: 10px;
right: 10px;
padding: 10px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
font-size: 12px;
}
.error {
color: red;
}
.success {
color: green;
}
</style>
</head>
<body>
<div id="status">Initializing...</div>
<div id="chat-container"></div>
<script>
console.log('[DEBUG] Script loaded');
async function initChatKit() {
const statusEl = document.getElementById('status');
try {
console.log('[DEBUG] Starting ChatKit initialization...');
statusEl.textContent = 'Fetching session token...';
console.log('[DEBUG] Fetching from: http://127.0.0.1:8000/api/chatkit/session');
// Fetch client secret from your FastAPI server
const response = await fetch('http://127.0.0.1:8000/api/chatkit/session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
console.log('[DEBUG] Response status:', response.status);
console.log('[DEBUG] Response ok:', response.ok);
if (!response.ok) {
throw new Error(`Server responded with ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log('[DEBUG] Received data:', data);
const clientSecret = data.client_secret;
console.log('[DEBUG] Client secret:', clientSecret);
statusEl.textContent = 'Initializing ChatKit...';
statusEl.className = 'success';
console.log('[DEBUG] Creating openai-chatkit element...');
// Create and configure ChatKit element
const chatkit = document.createElement('openai-chatkit');
console.log('[DEBUG] ChatKit element created:', chatkit);
console.log('[DEBUG] ChatKit element type:', typeof chatkit);
console.log('[DEBUG] ChatKit setOptions function:', typeof chatkit.setOptions);
if (typeof chatkit.setOptions !== 'function') {
throw new Error('ChatKit element does not have setOptions method. CDN script may not be loaded properly.');
}
console.log('[DEBUG] Setting options with getClientSecret function...');
chatkit.setOptions({
api: {
async getClientSecret(currentClientSecret) {
console.log('[DEBUG] getClientSecret called with:', currentClientSecret);
if (!currentClientSecret) {
// Initial token fetch
console.log('[DEBUG] Returning initial token:', clientSecret);
return clientSecret;
}
// Token refresh - fetch a new one
console.log('[DEBUG] Refreshing token...');
const response = await fetch('http://127.0.0.1:8000/api/chatkit/session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
const data = await response.json();
console.log('[DEBUG] Refreshed token:', data.client_secret);
return data.client_secret;
}
}
});
console.log('[DEBUG] Options set, appending to container...');
// Add to container
const container = document.getElementById('chat-container');
container.appendChild(chatkit);
console.log('[DEBUG] ChatKit element appended to DOM');
statusEl.textContent = 'ChatKit ready!';
// Hide status after 2 seconds
setTimeout(() => {
statusEl.style.display = 'none';
}, 2000);
console.log('[DEBUG] Initialization complete!');
} catch (error) {
console.error('[ERROR] Error initializing ChatKit:', error);
console.error('[ERROR] Error stack:', error.stack);
statusEl.textContent = `Error: ${error.message}`;
statusEl.className = 'error';
}
}
// Wait for the script to load
window.addEventListener('load', () => {
console.log('[DEBUG] Window loaded, waiting 1000ms for CDN script...');
// Give the CDN script time to load
setTimeout(() => {
console.log('[DEBUG] Starting initChatKit...');
console.log('[DEBUG] window.ChatKit:', typeof window.ChatKit);
initChatKit();
}, 1000);
});
</script>
</body>
</html>
Front-end Server
'''
serve.py
Simple HTTP server to serve main.html
'''
import http.server
import socketserver
PORT = 8080
class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
# Add CORS headers
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', '*')
super().end_headers()
with socketserver.TCPServer(("", PORT), MyHTTPRequestHandler) as httpd:
print(f"Open http://localhost:{PORT}/main.html in your browser")
httpd.serve_forever()
Note that I used this for testing purposes only and did not use it for production. I was simply exploring.
If you have any suggestions or find an easier way to explore, please let me know.