가이드
모바일 앱에서 사용하기
가능합니다. 위젯은 plain HTTP API 위의 얇은 클라이언트이고, 그 API에서 브라우저가 전제인 것은 아무것도 없습니다 — 쿠키도, 리디렉션도 없고, JSON이 들어가면 JSON이 나옵니다. iOS나 Android 앱이 같은 플랜, 같은 할당량으로 같은 에이전트와 대화합니다. 따로 사야 할 모바일 제품도, 설치할 SDK도 없습니다.
바뀌는 것은, 앱이 자신을 증명하는 방식입니다. 누군가 열 수 있는 바이너리를 ship하기 전에, 이것을 제대로 해 둘 가치가 있습니다.
들어가는 방식은 두 가지 — 어느 쪽이 맞는가
앱에 이미 백엔드가 있다면, 그것으로 하세요. 서버가 사이트의 비밀을 갖고, 짧은 유효기의 서명 토큰을 발행합니다. 앱은 서버에 토큰을 요청해, 그것을 우리에게 보냅니다. 비밀은 앱 안에 절대 ship되지 않고, 토큰은 몇 분 안에 만료되며, 당신의 사용자 중 누구에게 대화가 주어질지 정하는 것은 당신입니다. 선택지가 있다면, 이 길이 맞습니다.
앱에 백엔드가 없다면, 대신 공개 사이트 키를 가질 수 있습니다 — 웹사이트 위젯이 쓰는 키와 같은 것입니다. 그것이 무슨 뜻인지 이해하세요: 키는 어떤 앱 바이너리에서도 추출할 수 있고, 웹사이트와 달리 대조할 도메인이 없습니다. 포털에서, 사이트의 Setup 탭 Also used from a mobile app 항목에서 의도적으로 켜야 합니다. 켜기 전까지, 브라우저 origin이 없는 요청은 거절됩니다.
그 경우, 바로 아래 Require each app install to register도 체크하세요. 그러면 앱은 첫 실행 때 /v1/install을 한 번 호출하고, 받은 id를 보관한 뒤, 그 다음 모든 요청에 함께 보냅니다. 요청은 등록된 install마다 속도 제한되므로, 추출된 키로 한 호출자가 봇의 공유 할당량에 무제한으로 닿는 길이 되지는 않습니다. 설치마다 호출 하나가 추가되는 비용입니다.
요청 순서
Base URL은 https://kavilo.cloud. 모든 요청에서 자격 증명을 헤더로 보냅니다 — Authorization: Bearer <token> 또는 X-Kavilo-Key: kw_pub_….
POST /v1/install— 위의 설정을 체크했다면, 첫 실행 때 한 번. 반환되는installId를 보관하고, 그 다음부터X-Kavilo-Install으로 보냅니다.POST /v1/session— 열기 또는 재개.{"conversationId": "…"}를 보냅니다 — 처음에는 비워 두세요. 보관할 id, greeting, cursor, 그리고 지금까지의 history가 돌아옵니다.POST /v1/message— 한 턴 보내기. 즉시202로 답하고, 응답은 당신이 읽고 있는 전송 방식으로 옵니다.POST /v1/poll— 응답을 받는 두 가지 방식 중 하나. cursor를 보내고, 새로 생긴 것을 가져옵니다. 빈 응답으로 답하기 전까지 25초까지 기다리므로, 이것의 반복은 long-poll이지 busy wait이 아닙니다.GET /v1/stream— 폴링의 대안: 같은 프레임을 server-sent events로 받습니다.POST /v1/end— 방문자가 끝났다는 뜻. 전사본을 보내고, 대화를 닫습니다.
poll과 stream은 같은 cursor로 같은 버퍼를 읽으므로, 대화 도중에도 서로 갈아타고 아무것도 잃지 않습니다. 모바일에서는 보통 poll이 둘 중 더 쉽습니다: 특별한 처리 없이 네트워크 변경을 버티고, 사용자가 읽는 동안 소켓을 열어 두지 않으니까요.
응답 읽기
프레임마다 seq, kind, 보통 text가 있습니다. token 프레임은 올 때마다 붙여 넣으세요. 턴은 final로 끝납니다. 여기에는 완성된 답이 담겨 있으니, 이것을 기준으로 삼아 그동안 누적한 것으로 교체하세요 — 다시 연결했을 때, 답변이 두 번 표시되게 하지 않기 위해서. 턴은 error로 끝나기도 합니다. 끝은 이 두 가지뿐입니다 — 기다려야 할 별도 "done" 프레임은 없습니다.
메시지 하나가 항상 응답 하나를 뜻하지는 않습니다. 에이전트가 답하는 도중, 방문자가 두 번째 메시지를 보내면, 같은 턴에 합쳐집니다. 메시지당 응답 하나를 세기 전까지 멈추는 앱은 결국 멈춰 버립니다; 대신 final까지 읽으세요.
앱이 배경으로 갈 때
15분간 조용해지면, 대화가 닫히고 전사본이 발송됩니다 — 웹에서도 같은 규칙입니다. 탭을 닫는 방문자는 차를 내리는 방문자와 정확히 구별이 안 되니까요. 잠드는 모바일은 그 선을 쉽게 넘습니다.
그러므로 포그라운드로 돌아올 때, 저장해 둔 id로 /v1/session을 다시 호출하세요. 대화가 열려 있으면 그대로 이어 가고, 닫혀 있었다면 새 대화가 주어집니다 — 어느 쪽이든, 응답이 다시 그릴 history를 건네 줍니다. 그 호출을 에러 처리가 아니라, 화면이 로딩되는 방식으로 다루세요.
아직 없는 것
첨부 파일입니다. 채팅 API에는 업로드 엔드포인트가 없습니다 — 앱에도, 웹에도 — 그래서 방문자가 고장 난 부품의 사진을 보내 주지 못합니다. 그것이 당신의 앱의 목적인데, 알려 주세요 — 누군가 실제로 필요로 하면, 목록에서 올라옵니다.
여기서 시작하세요
reference client를 요청해 주시면, Swift와 Kotlin으로 전체 순서를 보내 드리겠습니다 — 각각 100줄 안팎, 믿는 것보다 읽을 수 있을 만큼 짧습니다. hello@kavilo.cloud로, 어떤 플랫폼을 쓰는지 알려 주세요.