CopilotKit

CopilotKit (CopilotKit)

CopilotKit완전한 React 채팅 런타임을 제공하고, 에이전트가 일반 텍스트 대신 구조화된 UI 페이로드를 반환하기를 원할 때 LangGraph와 특히 잘 어울려요. 이 패턴에서는 LangGraph 배포가 그래프 API와 커스텀 CopilotKit 엔드포인트 둘 다 서빙하고, 프론트엔드는 어시스턴트 메시지를 동적 React 컴포넌트로 파싱합니다.

서버 측에서는 copilotkit 패키지가 CopilotKitMiddleware를 제공해서, LangGraph 그래프·LangChain 에이전트·Deep AgentAgent UI (AG-UI) 와이어 프로토콜로 통신하고, 도구·메시지 이벤트를 채팅 UI로 스트림하며, 공유 CopilotKit 상태 슬라이스를 읽고 쓸 수 있게 해줘요. 그래프 앞에 CopilotKit 호환 HTTP 엔드포인트를 마운트하는 헬퍼도 있습니다. 이 방식은 이런 때 유용하죠.

  • 직접 stream.messages를 연결하는 대신 준비된 채팅 런타임을 쓰고 싶을 때
  • 배포된 그래프 옆에 제공자별 동작을 추가할 수 있는 커스텀 서버 엔드포인트가 필요할 때
  • 제약된 컴포넌트 레지스트리에서 렌더링되는 구조화된 생성 UI를 원할 때

LangGraph용 CopilotKit은 같은 미들웨어와 클라이언트 위에 생성 UI, 인간 개입 (HITL), 공유 상태도 다루고 있어요.

출처: LangChain 공식 문서 — copilotkit

동작 방식 (How it works)

높은 수준에서 보면 CopilotKit은 React 앱과 LangGraph 배포 사이에 위치해요. 프론트엔드는 대화 상태를 그래프 API 옆에 마운트된 커스텀 /api/copilotkit 라우트로 보내고, 그 라우트가 요청을 LangGraph로 전달하며, 응답에는 어시스턴트 메시지와 컴포넌트 레지스트리가 렌더링할 수 있는 구조화된 UI 페이로드가 함께 돌아옵니다.

  1. 그래프를 평소처럼 배포 — LangSmith 또는 LangGraph 개발 서버를 사용해요.
  2. HTTP 앱으로 배포 확장 — 그래프 API 옆에 CopilotKit 라우트를 마운트하죠.
  3. 프론트엔드를 CopilotKit으로 감싸기 — 커스텀 런타임 URL을 가리켜요.
  4. 동적 UI 컴포넌트 등록 — 렌더링 시 어시스턴트 응답을 그 컴포넌트들로 파싱합니다.

Python 서버에서 얻는 것 (What you get on the Python server)

copilotkit 및 관련 패키지는 LangGraph 배포와 CopilotKit 클라이언트를 잇습니다.

CopilotKitMiddlewarecreate_deep_agent와, middleware 목록에 추가한 create_agent로 만든 그래프 양쪽에 같은 미들웨어예요. CopilotKitState와 FastAPI 브리지를 쓰는 create_agent 그래프라면 아래 Python main.py 예제를 따르세요. 구조화된 생성 UI(예: useAgentContext와 클라이언트의 output_schema)는 Copilot 상태를 구조화된 출력 전략에 매핑하는 추가 미들웨어가 필요해요. 같은 섹션의 펼쳐지는 src/middleware.py 예제처럼 말이죠. applanggraph.jsonhttp 키에 마운트하는 것은 평소의 LangGraph 또는 LangSmith 배포를 따르므로, 하나의 프로세스가 그래프와 같은 FastAPI 앱을 CopilotKit 클라이언트에 동시에 서빙해요.

설치 (Installation)

백엔드 엔드포인트용으로, 미들웨어 패키지는 Deep Agents 스택 옆에 놓여요. 채팅 모델 패키지(예제는 OpenAI 사용)와 함께 설치하세요. 프론트엔드 앱용 설치는 별도로 진행합니다.

Deep Agent와 함께 CopilotKit 사용하기 (Use CopilotKit with a Deep Agent)

CopilotKitMiddlewarecreate_deep_agent에 넘기는 middleware 목록에 추가하세요. 미들웨어가 CopilotKit이 프론트엔드 도구 호출을 라우팅하고 채팅 상태를 그래프와 정렬하게 해줘요. 구성하는 다른 미들웨어도 같은 목록에 유지하세요. 컴파일된 그래프는 CopilotKit 또는 AG-UI 인식 프로세스(아래 FastAPI 패턴 같은)나 CopilotKit 문서의 Deep Agents and CopilotKit 가이드에 꽂을 준비가 끝납니다.

LangGraph 배포를 커스텀 엔드포인트로 확장하기 (Extend the LangGraph deployment with a custom endpoint)

핵심 아이디어는 LangGraph 배포가 그래프만 서빙하지 않는다는 거예요. HTTP 앱을 로드할 수도 있어서, 배포 자체 옆에 추가 라우트를 마운트할 수 있죠. langgraph.json에서 http.app을 여러분의 커스텀 앱 엔트리포인트로 지정하면 됩니다.

Python에서는 FastAPI 앱을 만들어 LangGraph 에이전트를 CopilotKit의 AG-UI 브리지로 노출해요.

# main.py
# FastAPI 앱을 만들고 CopilotKit의 AG-UI 브리지로 LangGraph 에이전트를 노출한다.

이 커스텀 앱이 중요한 확장 지점이에요. 기본 LangGraph 배포를 대체하지 않고 CopilotKit 인식 런타임을 마운트하니까요. Python에서 같은 작업은 미들웨어에서 일어나요 — CopilotKit 컨텍스트를 정규화하고 useAgentContext(...)output_schema를 모델의 구조화된 출력 설정으로 전달하죠.

결과적으로 책임이 깔끔하게 분리됩니다.

  • LangGraph — 그래프 실행과 영속성 담당
  • CopilotKit — 채팅 지향 런타임 계약 담당
  • 커스텀 엔드포인트 — 하나의 배포 안에서 둘을 이어주는 접착제

CopilotKit 런타임 어댑터를 쓸 때는 runtimeUrl이 원시 그래프 REST 서페이스가 아니라 FastAPI(또는 다른) 앱이 노출하는 라우트를 가리키게 하세요. Node CopilotRuntimeLangGraphHttpAgentLangGraphAgent는 CopilotKit 문서를 따르고, Python 그래프와 미들웨어가 여전히 도구 동작과 에이전트 로직을 정의해요.

프론트엔드 앱 구성하기 (Structure the frontend app)

프론트엔드에서는 앱을 CopilotKit으로 감싸고 커스텀 런타임 URL을 가리켜요. 여기 두 가지 중요한 부분이 있습니다.

  • runtimeUrl="/api/copilotkit" — 채팅을 원시 LangGraph API 대신 커스텀 백엔드 라우트로 보내요.
  • useAgentContext(...) — UI 스키마를 에이전트에 보내서 모델이 어떤 구조화된 출력 형식을 만들어야 하는지 알게 해요.

동적 컴포넌트 등록하기 (Register the dynamic components)

컴포넌트 레지스트리는 useChatKit() 안에 있어요. 에이전트가 내보낼 수 있는 컴포넌트 집합 — 카드, 행, 열, 차트, 코드 블록, 버튼 — 을 여기서 정의하죠. 이 레지스트리가 에이전트와 UI 사이의 계약(contract) 이 됩니다. 모델은 임의의 JSX를 생성하는 게 아니라, 여러분이 노출한 컴포넌트와 props에 대해 검증되어야 하는 구조화된 데이터를 생성해요. 어시스턴트 응답이 도착하면 커스텀 메시지 렌더러가 표시 방식을 결정합니다. 이 예제에서는:

  • 어시스턴트 메시지를 UI 키트 스키마에 대해 구조화된 JSON으로 파싱하고
  • 유효한 구조화된 출력을 실제 React 컴포넌트로 렌더링하며
  • 사용자 메시지는 평범한 채팅 거품으로 렌더링해요.

이 렌더러 패턴 덕분에 통합이 네이티브하게 느껴집니다.

  • CopilotKit — 채팅 상태와 전송 담당
  • 커스텀 렌더러 — 어시스턴트 페이로드가 어떻게 UI가 되는지 결정
  • Hashbrown — 검증된 구조화된 데이터를 구체적인 React 요소로 변환

모범 사례 (Best practices)

  • 커스텀 엔드포인트는 얇게 유지 — 그래프 배포에 CopilotKit을 적응시키는 데 쓰고, 그래프 안에 이미 있는 비즈니스 로직을 복제하지 마세요.
  • 스키마를 명시적으로 전송useAgentContext가 페이지가 마운트될 때마다 UI 계약을 기술하게 하세요.
  • 제약된 컴포넌트 집합 등록 — 모델이 실제로 쓰길 원하는 컴포넌트와 props만 노출해요.
  • 렌더링을 파싱 단계로 취급 — 렌더링 전에 어시스턴트 콘텐츠를 스키마에 대해 파싱하세요.
  • 사용자 메시지는 평범하게 유지 — 구조화된 렌더러가 필요한 건 어시스턴트 메시지뿐이고, 사용자 메시지는 일반 채팅 거품으로 남겨두면 돼요.

리소스 (Resources)

더 알아보기 (Learn more)