채팅 에이전트의 답변에 표나 차트, 버튼을 담으려면 생성한 내용을 채팅 서비스가 받아들이는 메시지 형식으로 옮겨야 한다. Vercel은 2026년 11월 6일 Chat SDK 에이전트에서 json-render로 생성형 UI를 스트리밍하는 기능을 발표했다. 에이전트가 카드의 구성을 JSON으로 작성하면, 이를 Slack이나 Teams의 기본 카드 형식으로 보내는 연결이다.

핵심은 카드가 완성되기 전부터 내용을 보여 줄 수 있다는 점이다. 생성 중인 요소가 도착할 때마다 이미 게시한 메시지를 갱신하고, 마지막에 검증된 카드로 마무리한다.

에이전트가 구성을 쓰고, 어댑터가 표현한다

출발점은 표·차트·버튼처럼 사용할 수 있는 컴포넌트와 그 속성의 타입을 정한 카탈로그다. 에이전트는 이 목록을 바탕으로 어떤 요소를 어떻게 배치할지 JSON 명세를 작성한다. json-render는 명세를 Chat SDK 카드로 바꾸고, 각 플랫폼의 어댑터가 카드를 해당 서비스의 기본 형식으로 게시한다.

하나의 카드 명세가 플랫폼별 메시지가 되는 경로

공통 카드에서 각 플랫폼의 어댑터를 거쳐 서로 다른 기본 형식으로 게시된다.

  1. 컴포넌트 카탈로그사용할 요소와 속성의 타입을 정한다.
  2. 에이전트의 JSON 명세카탈로그를 바탕으로 카드의 구성을 작성한다.
  3. json-renderJSON 명세를 Chat SDK 카드로 변환한다.

Slack

  1. Slack 어댑터카드를 Block Kit 형식으로 게시한다.

Teams

  1. Teams 어댑터카드를 Adaptive Cards 형식으로 게시한다.

생성할 내용의 구성과 플랫폼에서 표현하는 방식이 이 경계에서 나뉜다.

먼저 보이는 카드와 최종 카드의 차이

Vercel의 설명에 따르면 streamCard는 카드의 루트 요소에 내용이 생기면 메시지를 게시한다. 이후 새 요소가 들어올 때 같은 메시지를 수정하고, 스트림이 끝나면 검증을 마친 최종 카드를 표시한다. 기본 설정에서 수정은 최대 500ms에 한 번씩 이뤄진다.

화면에 일부 내용이 나타났다고 해서 최종 명세의 유효성이 확인된 것은 아니다. API 문서는 최종 명세가 유효하지 않으면 부분 메시지가 이미 보이는 상태에서 CardSpecError가 발생한다고 설명한다. 이 경우 개발자는 재시도하거나 메시지를 수정하도록 처리할 수 있다. 스트리밍은 생성 도중의 내용을 먼저 보여 주는 과정이고, 최종 검증은 그 결과를 확정하는 별도 단계인 셈이다.

명세를 완성된 카드로 바꾸는 toCard는 각 요소의 속성과 명세 구조를 검사한다. 문제가 있으면 CardSpecError 예외를 던지며, 예외의 issues 배열에 문제별 설명을 담는다. 개발자는 이 목록을 모델에 전달해 수정된 명세를 요청할 수 있다.

여기에 플랫폼이 한 메시지에 담을 수 있는 양이라는 조건도 붙는다. 유효한 명세라도 플랫폼의 수용 한도를 넘으면 어댑터가 표현을 바꿀 수 있다. Vercel이 든 예로, Slack 어댑터는 두 번째 표를 코드 블록으로 바꾼다. 같은 카드 명세를 사용해도 모든 요소가 원래 형태대로 유지되는 것은 아니다.

표현을 바꾸어 게시하는 대신 해당 명세를 거부하려면 limits를 전달해 한도를 적용할 수 있다. 명세가 올바르게 구성됐는지 검사하는 일에 더해, 보낼 플랫폼에서 원하는 형태를 유지할 수 있는지도 조건으로 삼는 방식이다.

관련 자료