Si vous avez besoin d’un contrôle total pour personnaliser l’authentification, respecter vos exigences de résidence des données, déployer votre application sur site ou orchestrer vos agents sur mesure, vous pouvez exécuter ChatKit sur votre propre infrastructure. L’option d’auto-hébergement avancée d’OpenAI vous permet d’utiliser votre propre serveur et de personnaliser ChatKit.
Les workflows ChatKit hébergés par Agent Builder sont en phase de transition. Pour toute nouvelle application ChatKit, implémentez vos agents sur votre serveur à l’aide des SDK ChatKit et du SDK Agents. Consultez les recommandations pour la transition de ChatKit →
Exécutez ChatKit sur votre propre infrastructure
Pour mettre en place une intégration avancée, créez votre propre serveur ChatKit et ajoutez des widgets à votre interface de discussion. Les API d’OpenAI et votre serveur ChatKit vous permettent de créer une interface de discussion personnalisée qui s’appuie sur les modèles d’OpenAI.

Configurez votre serveur ChatKit
Suivez le guide du serveur sur GitHub pour apprendre à traiter les requêtes entrantes, à exécuter des outils et à transmettre les résultats au client au fur et à mesure. Les extraits de code ci-dessous illustrent les principaux composants.
1. Installez le paquet serveur
pip install openai-chatkit
2. Implémentez une classe serveur
ChatKitServer gère la conversation. Redéfinissez respond pour transmettre des événements en continu à chaque réception d’un message utilisateur ou du résultat d’un outil côté client. Des fonctions utilitaires comme stream_agent_response relient le serveur au SDK Agents.
class MyChatKitServer(ChatKitServer[RequestContext]):
async def respond(
self,
thread: ThreadMetadata,
input: UserMessageItem | ClientToolCallOutputItem | None,
context: RequestContext,
) -> AsyncIterator[Event]:
items_page = await self.store.load_thread_items(
thread.id,
after=None,
limit=20,
order="desc",
context=context,
)
input_items = await simple_to_agent_input(list(reversed(items_page.data)))
agent_context = AgentContext(
thread=thread,
store=self.store,
request_context=context,
)
result = Runner.run_streamed(
assistant_agent,
input_items,
context=agent_context,
)
async for event in stream_agent_response(agent_context, result):
yield event3. Exposez le point de terminaison
Utilisez le framework de votre choix pour transmettre les requêtes HTTP à l’instance du serveur. Voici un exemple avec FastAPI :
from fastapi import FastAPI, Request, Response
from fastapi.responses import StreamingResponse
app = FastAPI()
data_store = MemoryStore()
server = MyChatKitServer(data_store)
@app.post("/chatkit")
async def chatkit_endpoint(request: Request):
result = await server.process(await request.body(), {})
if isinstance(result, StreamingResult):
return StreamingResponse(result, media_type="text/event-stream")
return Response(content=result.json, media_type="application/json")4. Implémentez l’interface de stockage des données
Implémentez chatkit.store.Store pour enregistrer les fils de discussion, les messages et les fichiers dans la base de données de votre choix. Pour le développement local, vous pouvez utiliser une implémentation en mémoire de Store. En production, utilisez un stockage persistant et envisagez d’enregistrer les modèles sous forme de blobs JSON pour que les mises à jour de la bibliothèque puissent faire évoluer le schéma sans migration.
5. Implémentez l’interface de stockage des fichiers
Si vous prenez en charge l’envoi de fichiers, fournissez une implémentation de FileStore. ChatKit accepte les envois directs (le client envoie le fichier à votre point de terminaison par requête POST) et les envois en deux étapes (le client demande une URL signée, puis envoie le fichier vers un espace de stockage cloud). Fournissez des aperçus pour afficher les miniatures dans la discussion et gérez la suppression des fichiers lorsque les fils de discussion sont supprimés.
6. Déclenchez les outils côté client depuis le serveur
Enregistrez les outils côté client à la fois dans les options du client et auprès de votre agent. Utilisez ctx.context.client_tool_call pour mettre un appel en file d’attente depuis un outil du SDK Agents.
@function_tool(description_override="Add an item to the user's todo list.")
async def add_to_todo_list(ctx: RunContextWrapper[AgentContext], item: str) -> None:
ctx.context.client_tool_call = ClientToolCall(
name="add_to_todo_list",
arguments={"item": item},
)
assistant_agent = Agent[AgentContext](
model="gpt-6-astra",
name="Assistant",
instructions="You are a helpful assistant",
tools=[add_to_todo_list],
tool_use_behavior=StopAtTools(stop_at_tool_names=[add_to_todo_list.name]),
)7. Utilisez les métadonnées et l’état du fil de discussion
Utilisez thread.metadata pour stocker l’état côté serveur, par exemple l’identifiant de l’exécution précédente de l’API Responses ou des libellés personnalisés. Le client n’a pas accès aux métadonnées, mais elles sont disponibles à chaque appel à respond.
8. Suivez la progression des outils
Les outils qui exécutent des tâches de longue durée peuvent transmettre leur progression à l’interface avec ProgressUpdateEvent. ChatKit remplace l’événement de progression par le prochain message de l’assistant ou le prochain résultat d’un widget.
9. Utilisez le contexte du serveur
Passez un objet de contexte personnalisé à server.process(body, context) pour appliquer les règles d’autorisation ou transmettre l’identité de l’utilisateur à vos implémentations de stockage des données et des fichiers.
Ajoutez des widgets interactifs dans la discussion
Les widgets permettent aux agents d’afficher des éléments d’interface riches directement dans la discussion. Utilisez-les pour présenter des cartes, des formulaires, des blocs de texte, des listes ou d’autres mises en page. La fonction utilitaire stream_widget peut afficher un widget immédiatement ou transmettre ses mises à jour à mesure qu’elles arrivent.
async def respond(
self,
thread: ThreadMetadata,
input: UserMessageItem | ClientToolCallOutputItem | None,
context: RequestContext,
) -> AsyncIterator[Event]:
widget = Card(
children=[
Text(
id="description",
value="Generated summary",
)
]
)
async for event in stream_widget(
thread,
widget,
generate_id=lambda item_type: self.store.generate_item_id(
item_type, thread, context
),
):
yield eventChatKit propose de nombreux nœuds de widgets, notamment des cartes, des listes, des formulaires, du texte et des boutons. Consultez le guide des widgets sur GitHub pour découvrir tous les composants et leurs propriétés, ainsi que les recommandations pour la diffusion en continu.
Utilisez le Widget Builder pour explorer et créer des widgets dans une interface interactive.
Utilisez les actions
Les actions permettent de déclencher un traitement depuis l’interface ChatKit sans envoyer de message utilisateur. Associez un ActionConfig à tout nœud de widget qui le prend en charge. Les boutons, les listes de sélection et d’autres contrôles peuvent transmettre de nouveaux éléments du fil de discussion en continu ou mettre à jour les widgets sur place. Lorsqu’un widget se trouve dans un Form, ChatKit inclut les valeurs du formulaire dans la charge utile de l’action.
Côté serveur, implémentez la méthode action de ChatKitServer pour traiter la charge utile et, si nécessaire, transmettre d’autres événements en continu. Vous pouvez aussi traiter les actions côté client en définissant handler="client" et en répondant en JavaScript avant de confier la suite du traitement au serveur.
Consultez le guide des actions sur GitHub pour savoir comment enchaîner des actions, créer des charges utiles fortement typées et coordonner les gestionnaires côté client et côté serveur.
Ressources
Appuyez-vous sur les ressources et la documentation de référence ci-dessous pour finaliser votre intégration.
Ressources de conception
- Téléchargez OpenAI Sans Variable.
- Dupliquez le fichier et adaptez les composants à votre produit.
Référence des événements
Le composant Web de ChatKit émet des instances de CustomEvent. Écoutez les événements du cycle de vie et lisez les données de leur charge utile dans event.detail :
chatkit.addEventListener("chatkit.error", (event) => {
console.error(event.detail.error);
});
chatkit.addEventListener("chatkit.response.start", () => {
console.log("Response started");
});
chatkit.addEventListener("chatkit.response.end", () => {
console.log("Response ended");
});
chatkit.addEventListener("chatkit.thread.change", (event) => {
console.log("Active thread:", event.detail.threadId);
});
chatkit.addEventListener("chatkit.log", (event) => {
console.log(event.detail.name, event.detail.data);
});Référence des options
| Option | Type | Description | Valeur par défaut |
|---|---|---|---|
apiURL |
string |
Point de terminaison qui implémente le protocole du serveur ChatKit. | obligatoire |
fetch |
typeof fetch |
Redéfinissez les appels à fetch pour personnaliser les en-têtes ou l’authentification. | window.fetch |
theme |
"light" | "dark" |
Thème de l’interface. | "light" |
initialThread |
string | null |
Fil de discussion à ouvrir au montage du composant. Avec null, la vue de création d’un fil s’affiche. |
null |
clientTools |
Record<string, Function> |
Outils mis à la disposition du modèle et exécutés côté client. | |
header |
object | boolean |
Configuration de l’en-tête. Utilisez false pour le masquer. |
true |
newThreadView |
object |
Personnalisez le message d’accueil et les prompts proposés pour lancer la discussion. | |
messages |
object |
Configurez les fonctionnalités des messages (retours des utilisateurs, annotations, etc.). | |
composer |
object |
Gérez les pièces jointes, les étiquettes d’entités et le texte indicatif de la zone de saisie. | |
entities |
object |
Fonctions de rappel pour rechercher des entités, traiter les clics et afficher les aperçus. |