맞춤형 인증, 데이터 레지던시, 온프레미스 배포, 맞춤형 에이전트 오케스트레이션 등 운영 환경을 직접 제어해야 한다면 자체 인프라에서 ChatKit을 실행할 수 있습니다. OpenAI의 고급 자체 호스팅 옵션을 사용하면 자체 서버에서 제품에 맞게 구성한 ChatKit을 운영할 수 있습니다.
Agent Builder에서 호스팅하는 ChatKit 워크플로우는 현재 전환 기간에 있습니다. 새 ChatKit 앱을 만들 때는 ChatKit SDK와 Agents SDK로 서버 측 에이전트를 직접 구현하고 이를 기반으로 앱을 구축하세요. ChatKit 전환 가이드 보기 →
자체 인프라에서 ChatKit 실행하기
ChatKit 고급 통합은 자체 ChatKit 서버를 구축하고 채팅 화면에 위젯을 추가하는 과정입니다. OpenAI API와 자체 ChatKit 서버를 사용해 OpenAI 모델을 기반으로 제품에 맞는 채팅 기능을 구현합니다.

ChatKit 서버 설정하기
GitHub의 서버 가이드에서 수신 요청을 처리하고 도구를 실행한 뒤 결과를 클라이언트로 스트리밍하는 방법을 확인하세요. 아래 코드 예제에서는 주요 구성 요소를 살펴봅니다.
1. 서버 패키지 설치하기
pip install openai-chatkit
2. 서버 클래스 구현하기
ChatKitServer는 대화를 관리합니다. 사용자 메시지나 클라이언트 도구의 출력이 도착할 때마다 이벤트를 스트리밍하도록 respond를 재정의하세요. stream_agent_response 같은 헬퍼 함수로 서버를 Agents SDK에 연결할 수 있습니다.
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. 엔드포인트 제공하기
원하는 프레임워크를 사용해 HTTP 요청을 서버 인스턴스로 전달하세요. 다음은 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. 데이터 저장소 인터페이스 구현하기
원하는 데이터베이스에 스레드, 메시지, 파일을 저장하도록 chatkit.store.Store를 구현하세요. 로컬 개발 환경에서는 인메모리 Store 구현을 사용할 수 있습니다. 프로덕션 환경에서는 영구 저장소를 사용하세요. 라이브러리 업데이트로 스키마가 변경되어도 마이그레이션이 필요 없도록 모델을 JSON 블롭으로 저장하는 방법을 고려하세요.
5. 파일 저장소 인터페이스 구현하기
파일 업로드를 지원하려면 FileStore를 구현하세요. ChatKit은 클라이언트가 자체 서버의 엔드포인트에 POST 요청으로 파일을 보내는 직접 업로드와 클라이언트가 서명된 URL을 요청한 뒤 클라우드 스토리지에 파일을 업로드하는 2단계 업로드를 지원합니다. 채팅에 인라인 썸네일을 표시할 수 있도록 미리보기를 제공하고, 스레드를 삭제할 때는 파일 삭제도 처리하세요.
6. 서버에서 클라이언트 도구 호출하기
클라이언트 도구는 클라이언트 옵션과 에이전트 양쪽에 모두 등록해야 합니다. Agents SDK 도구에서 ctx.context.client_tool_call을 사용해 클라이언트 도구 호출을 대기열에 추가하세요.
@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. 스레드 메타데이터와 상태 사용하기
이전 Responses API 실행 ID나 사용자 지정 레이블 같은 서버 측 상태는 thread.metadata에 저장하세요. 메타데이터는 클라이언트에 공개되지 않으며 respond를 호출할 때마다 사용할 수 있습니다.
8. 도구 상태 업데이트 받기
실행 시간이 긴 도구는 ProgressUpdateEvent로 진행 상황을 UI에 스트리밍할 수 있습니다. ChatKit은 다음 어시스턴트 메시지나 위젯 출력이 도착하면 진행 상황 이벤트를 해당 메시지나 출력으로 대체합니다.
9. 서버 컨텍스트 사용하기
사용자 지정 컨텍스트 객체를 server.process(body, context)에 전달하면 권한을 적용하거나 데이터 저장소와 파일 저장소 구현에 사용자 식별 정보를 전달할 수 있습니다.
인라인 대화형 위젯 추가하기
에이전트는 위젯을 사용해 채팅 화면에 카드, 폼, 텍스트 블록, 목록 등 다양한 레이아웃의 UI를 표시할 수 있습니다. stream_widget 헬퍼 함수는 위젯을 즉시 렌더링하거나 업데이트가 도착할 때마다 스트리밍할 수 있습니다.
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은 카드, 목록, 폼, 텍스트, 버튼 등 다양한 위젯 노드를 제공합니다. 전체 컴포넌트와 속성, 스트리밍 방법은 GitHub의 위젯 가이드에서 확인하세요.
Widget Builder에서 대화형 UI로 위젯을 살펴보고 직접 만들어 보세요.
액션 사용하기
액션을 사용하면 사용자 메시지를 보내지 않고도 ChatKit UI에서 작업을 시작할 수 있습니다. ActionConfig를 지원하는 위젯 노드에 이 설정을 추가하세요. 버튼, 선택 메뉴 등의 컨트롤로 새 스레드 항목을 스트리밍하거나 기존 위젯을 제자리에서 업데이트할 수 있습니다. 위젯이 Form 안에 있으면 ChatKit은 폼에서 수집한 값을 액션 페이로드에 포함합니다.
서버에서는 action 메서드를 ChatKitServer에 구현해 페이로드를 처리하고 필요에 따라 추가 이벤트를 스트리밍하세요. handler="client"로 설정하면 클라이언트에서도 액션을 처리할 수 있습니다. JavaScript에서 액션에 응답한 뒤 후속 작업을 서버로 전달하세요.
액션을 연이어 실행하거나, 엄격한 타입을 적용한 페이로드를 만들거나, 클라이언트와 서버의 핸들러를 연동하는 방법은 GitHub의 액션 가이드에서 확인하세요.
참고 자료
다음 자료와 레퍼런스를 활용해 통합을 마무리하세요.
디자인 자료
- OpenAI Sans Variable을 다운로드하세요.
- 파일을 복제하고 제품에 맞게 컴포넌트를 수정하세요.
이벤트 레퍼런스
ChatKit의 Web 컴포넌트는 CustomEvent 인스턴스를 발생시킵니다. 수명 주기 이벤트를 수신하고 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);
});옵션 레퍼런스
| 옵션 | 타입 | 설명 | 기본값 |
|---|---|---|---|
apiURL |
string |
ChatKit 서버 프로토콜을 구현하는 엔드포인트입니다. | 필수 |
fetch |
typeof fetch |
사용자 지정 헤더나 인증을 적용하도록 fetch 호출을 재정의합니다. | window.fetch |
theme |
"light" | "dark" |
UI 테마입니다. | "light" |
initialThread |
string | null |
마운트 시 열 스레드입니다. null이면 새 스레드 화면을 표시합니다. |
null |
clientTools |
Record<string, Function> |
모델에 제공하며 클라이언트에서 실행하는 도구입니다. | |
header |
object | boolean |
헤더를 구성합니다. false로 설정하면 헤더를 숨깁니다. |
true |
newThreadView |
object |
인사말과 대화 시작 프롬프트를 설정합니다. | |
messages |
object |
피드백, 주석 등 메시지 기능을 설정합니다. | |
composer |
object |
첨부 파일, 엔터티 태그, 자리표시자 텍스트를 설정합니다. | |
entities |
object |
엔터티 조회, 클릭 처리, 미리보기에 사용하는 콜백입니다. |