Repository Public
1# ChatKit23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45ChatKit is the best way to build agentic chat experiences. Whether you’re building an internal knowledge base assistant, HR onboarding helper, research companion, shopping or scheduling assistant, troubleshooting bot, financial planning advisor, or support agent, ChatKit provides a customizable chat embed to handle all user experience details.67Use ChatKit's embeddable UI widgets, customizable prompts, tool‑invocation support, file attachments, and chain‑of‑thought visualizations to build agents without reinventing the chat UI.89## Overview1011Choose between two ChatKit paths:1213- **Custom server integration**. Run ChatKit on your own infrastructure. Use the ChatKit Python SDK and connect to any agentic service, including one built with the [Agents SDK](https://developers.openai.com/api/docs/guides/agents). Use widgets to build the frontend.14- **Existing Agent Builder-hosted integration**. If you already use ChatKit with an Agent Builder workflow, you can keep using that hosted workflow during the Agent Builder transition window.1516OpenAI is deprecating Agent Builder. Existing users can continue using it17 during the transition window, and the product is scheduled to shut down on18 November 30, 2026. ChatKit is still available. For new work or migration19 planning, use [advanced ChatKit integrations](https://developers.openai.com/api/docs/guides/custom-chatkit)20 with your own server-side agent implementation, and see [Migrate from Agent21 Builder](https://developers.openai.com/api/docs/guides/agent-builder/migrate-from-agent-builder) for Agent22 Builder transition guidance.2324## Get started with ChatKit2526- **[Custom server integration](https://developers.openai.com/api/docs/guides/custom-chatkit)**: Use any server and the ChatKit SDKs to build your own custom ChatKit user experience27- **[Existing hosted workflow](#embed-chatkit-in-your-frontend)**: Connect ChatKit to an existing Agent Builder workflow during the transition window2829## Embed ChatKit in your frontend3031Use this path only if you already have an Agent Builder workflow that backs your ChatKit implementation. For new ChatKit apps, or when migrating before Agent Builder shuts down, use the [advanced integration](https://developers.openai.com/api/docs/guides/custom-chatkit) to connect ChatKit to your own server-side agent implementation.3233At a high level, setting up ChatKit with an existing hosted workflow is a three-step process. Open your existing workflow while Agent Builder remains available. Then set up ChatKit and add features to build your chat experience.343536373940### 1. Use an existing hosted workflow4142Open your existing workflow in [Agent Builder](https://developers.openai.com/api/docs/guides/agent-builder). You'll get a workflow ID. For transition planning, see [Migrate from Agent Builder](https://developers.openai.com/api/docs/guides/agent-builder/migrate-from-agent-builder).4344The chat embedded in your frontend will point to the workflow you select.4546### 2. Set up ChatKit in your product4748To set up ChatKit, you'll create a ChatKit session and a server endpoint, pass in your workflow ID, exchange the client secret, and add a script to embed ChatKit on your site.4950**Important Security Note:** When creating a ChatKit session, you must pass in a `user` parameter, which should be unique for each individual end user. Your server must51authenticate your application's users and pass a unique identifier for them in this parameter.52531. On your server, generate a client token.5455 This example starts a service that creates a ChatKit session through the OpenAI API and returns the session's client secret:5657```python58# Replace the illustrative IDs and URLs below with your own resource values.59import hmac60import json61import os62from typing import Annotated6364import requests65from fastapi import Depends, FastAPI, HTTPException66from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer67from pydantic import BaseModel686970api_key = os.environ["OPENAI_API_KEY"]71workflow_id = "wf_123"72authenticated_users: dict[str, str] = json.loads(73 os.environ["CHATKIT_AUTHENTICATED_USERS"]74)75bearer_auth = HTTPBearer(auto_error=False)767778def get_authenticated_user_id(79 credentials: Annotated[80 HTTPAuthorizationCredentials | None,81 Depends(bearer_auth),82 ],83) -> str:84 if credentials is not None:85 for token, user_id in authenticated_users.items():86 if hmac.compare_digest(credentials.credentials, token):87 return user_id88 raise HTTPException(status_code=401, detail="Invalid authentication token")899091class ChatKitSession(BaseModel):92 client_secret: str939495app = FastAPI()969798@app.post("/api/chatkit/session")99def create_chatkit_session(100 user_id: Annotated[str, Depends(get_authenticated_user_id)],101):102 response = requests.post(103 "https://api.openai.com/v1/chatkit/sessions",104 headers={105 "Authorization": f"Bearer {api_key}",106 "Content-Type": "application/json",107 "OpenAI-Beta": "chatkit_beta=v1",108 },109 json={110 "workflow": {"id": workflow_id},111 "user": user_id,112 },113 timeout=30,114 )115 response.raise_for_status()116 session = ChatKitSession.model_validate(response.json())117 return {"client_secret": session.client_secret}118```119120```ruby121# Replace the illustrative IDs and URLs below with your own resource values.122require "json"123require "net/http"124require "openssl"125require "webrick"126127api_key = ENV.fetch("OPENAI_API_KEY")128workflow_id = "wf_123"129# Demo authentication mapping. Replace this with your application's session authentication.130authenticated_users = JSON.parse(ENV.fetch("CHATKIT_AUTHENTICATED_USERS"))131server = WEBrick::HTTPServer.new(132 BindAddress: "127.0.0.1", Port: Integer(ENV.fetch("PORT", "8000")),133 AccessLog: [], Logger: WEBrick::Log.new($stderr, WEBrick::BasicLog::WARN)134)135server.mount_proc("/api/chatkit/session") do |request, response|136 response["Content-Type"] = "application/json"137 response["Cache-Control"] = "no-store"138 unless request.path == "/api/chatkit/session" && request.request_method == "POST"139 response.status = 405140 response.body = JSON.generate(error: "Use POST /api/chatkit/session")141 next142 end143 token = request["Authorization"].to_s.delete_prefix("Bearer ")144 user = authenticated_users.find do |credential, _id|145 request["Authorization"].to_s.start_with?("Bearer ") &&146 OpenSSL.secure_compare(credential, token)147 end148 unless user149 response.status = 401150 response.body = JSON.generate(error: "Invalid authentication token")151 next152 end153 uri = URI("https://api.openai.com/v1/chatkit/sessions")154 upstream = Net::HTTP::Post.new(uri)155 upstream["Authorization"] = "Bearer #{api_key}"156 upstream["Content-Type"] = "application/json"157 upstream["OpenAI-Beta"] = "chatkit_beta=v1"158 upstream.body = JSON.generate(workflow: { id: workflow_id }, user: user.fetch(1))159 begin160 result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, open_timeout: 10, read_timeout: 30) do |http|161 http.request(upstream)162 end163 result.value164 secret = JSON.parse(result.body).fetch("client_secret")165 raise "Missing session secret" unless secret.is_a?(String) && !secret.empty?166167 response.body = JSON.generate(client_secret: secret)168 rescue169 response.status = 502170 response.body = JSON.generate(error: "Unable to create a ChatKit session")171 end172end173trap("INT") { server.shutdown }174trap("TERM") { server.shutdown }175puts("http://127.0.0.1:#{server.config[:Port]}/api/chatkit/session")176$stdout.flush177server.start178```179180181 For Ruby, install WEBrick with `gem install webrick`.182183 Before starting the service, replace `wf_123` with your workflow ID and set `OPENAI_API_KEY` and `CHATKIT_AUTHENTICATED_USERS`. The latter value is a JSON map from your application's bearer tokens to stable user IDs. In production, replace this environment-backed map with your application's authentication or session lookup.1841852. In your server-side code, pass in your workflow ID and secret key to the session endpoint.186187 The client secret is the credential that your ChatKit frontend uses to open or refresh the chat session. You don't store it; you immediately hand it off to the ChatKit client library.188189 See the [chatkit-js repo](https://github.com/openai/chatkit-js) on GitHub.190191 chatkit.js192193```javascript194export default async function getChatKitSessionToken(deviceId) {195 const apiKey = process.env.OPENAI_API_KEY;196 if (!apiKey) {197 throw new Error("OPENAI_API_KEY is required");198 }199200 const response = await fetch("https://api.openai.com/v1/chatkit/sessions", {201 method: "POST",202 headers: {203 "Content-Type": "application/json",204 "OpenAI-Beta": "chatkit_beta=v1",205 Authorization: `Bearer ${apiKey}`,206 },207 body: JSON.stringify({208 workflow: { id: "wf_68df4b13b3588190a09d19288d4610ec0df388c3983f58d1" },209 user: deviceId,210 }),211 });212213 if (!response.ok) {214 throw new Error(215 `Failed to create a ChatKit session: ${response.status} ${await response.text()}`216 );217 }218219 const { client_secret } = await response.json();220221 if (!client_secret) {222 throw new Error("ChatKit session response did not include client_secret");223 }224225 return client_secret;226}227```2282292303. In your project directory, install the ChatKit React bindings:231232```bash233 npm install @openai/chatkit-react234```2352364. Add the ChatKit JS script to your page. Drop this snippet into your page’s `<head>` or wherever you load scripts, and the browser will fetch and run ChatKit for you.237238 index.html239240```html241<script242src="https://cdn.platform.openai.com/deployments/chatkit/chatkit.js"243async244></script>245```2462472485. Render ChatKit in your UI. Pass the React `MyChat` component a `getAppAuthToken` function that returns the current user's bearer token. If you use the JavaScript tab, make the same function available in the snippet's scope. This code sends that credential to your server, fetches the client secret, and mounts a live chat widget connected to your workflow.249250 Your frontend code251252```javascript253const chatkit = document.getElementById("my-chat");254if (255 !chatkit ||256 !("setOptions" in chatkit) ||257 typeof chatkit.setOptions !== "function"258) {259 throw new Error("ChatKit element not found.");260}261262chatkit.setOptions({263 api: {264 async getClientSecret() {265 const appAuthToken = await getAppAuthToken();266 const res = await fetch("/api/chatkit/session", {267 method: "POST",268 headers: {269 Authorization: `Bearer ${appAuthToken}`,270 "Content-Type": "application/json",271 },272 });273 if (!res.ok) {274 throw new Error(`ChatKit session request failed: ${res.status}`);275 }276 const { client_secret } = await res.json();277 return client_secret;278 },279 },280});281```282283```tsx284import { ChatKit, useChatKit } from '@openai/chatkit-react';285286 export function MyChat({ getAppAuthToken }) {287 const { control } = useChatKit({288 api: {289 async getClientSecret(existing) {290 if (existing) {291 // implement session refresh292 }293294 const appAuthToken = await getAppAuthToken();295 const res = await fetch('/api/chatkit/session', {296 method: 'POST',297 headers: {298 'Authorization': 'Bearer ' + appAuthToken,299 'Content-Type': 'application/json',300 },301 });302 const { client_secret } = await res.json();303 return client_secret;304 },305 },306 });307308 return ;309 }310```311312313### 3. Build and iterate314315See the [custom theming](https://developers.openai.com/api/docs/guides/chatkit-themes), [widgets](https://developers.openai.com/api/docs/guides/chatkit-widgets), and [actions](https://developers.openai.com/api/docs/guides/chatkit-actions) docs to learn more about how ChatKit works. Or explore the following resources to test your chat, iterate on prompts, and add widgets and tools.316317#### Build your implementation318319[ChatKit docs on GitHub320321322323 Learn to handle authentication, add theming and customization, and more.](https://openai.github.io/chatkit-python)324[ChatKit Python SDK325326327328 Add server-side storage, access control, tools, and other backend329 functionality.](https://github.com/openai/chatkit-python)330331[ChatKit JS SDK332333334335 Check out the ChatKit JS repo.](https://github.com/openai/chatkit-js)336337#### Explore ChatKit UI338339[chatkit.world340341342343 Play with an interactive demo of ChatKit.](https://chatkit.world)344345[Widget builder346347348349 Browse available widgets.](https://widgets.chatkit.studio)350351[ChatKit playground352353354355 Play with an interactive demo to learn by doing.](https://chatkit.studio/playground)356357#### See working examples358359[Samples on GitHub360361362363 See working examples of ChatKit and get inspired.](https://github.com/openai/openai-chatkit-advanced-samples)364365[Starter app repo366367368369 Clone a repo to start with a fully working template.](https://github.com/openai/openai-chatkit-starter-app)370371## Next steps372373When you're happy with your ChatKit implementation, learn how to optimize it with [evals](https://developers.openai.com/api/docs/guides/agent-evals). For new ChatKit apps, or to move an existing ChatKit app off an Agent Builder-hosted workflow, see the [advanced integration docs](https://developers.openai.com/api/docs/guides/custom-chatkit).