メインコンテンツまでスキップ

SSE ワイヤープロトコル仕様

POST /chat/control/stream は Server-Sent Events(text/event-stream)で応答します。長時間維持される接続を通じて、生成中の回答テキストと、場所・地図操作・ルートに関する構造化イベントが順次送信されます。

このページではストリームの仕様を定義します。kaleidr.js を使用する場合はチャットパネルがストリームを読み取るため、このページを読む必要はありません。独自クライアントを開発する場合に参照してください。Node と Python の動作する実装例はストリームの読み取り、リクエスト本文はエンドポイントを参照してください。

/chat/summary/stream と /chat/button/stream も同じフレーム形式を使用しますが、イベントの種類は少なくなります。このページの末尾で説明します。

ストリーム開始前​

拒否されたリクエストはストリームにはなりません。認証、スコープ、クォータ、レート制限、検証、サイズの問題は、JSON 本文と 4xx ステータスを持つ通常の HTTP 応答で返されます(エラー)。先にステータスを確認し、200 の場合に限って本文を SSE として解析してください。

リクエストのサイズ上限は、メッセージ 400 件、各メッセージ 64,000 文字、全メッセージ合計 200,000 文字です。超過すると conversation_too_long などのコードとともに 422 が返り、本文が 2 MiB を超えると 413 が返ります。詳細はエンドポイントを参照してください。

成功した応答には次のヘッダーがあります。

HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache, no-transform

フレーム形式​

1 フレームは 1~2 行と、それに続く空行で構成されます。各行は \n で終わります。

event: place
data: {"name": "Louvre Museum", "coordinates": {"lat": 48.8606, "lng": 2.3376}}

data: {"text": "The Louvre sits on the right bank"}

: keep-alive

  • 名前付きフレームには event: 行と、それに続く data: 行があります。
  • テキストフレームには data: 行だけがあり、event: 行はありません。
  • コメントはコロンで始まります。Kaleidr はハートビートとして : keep-alive を送信します。データは含みません。
  • data: は必ず 1 行に完全な JSON オブジェクト 1 つを格納します。 文字コードは UTF-8 です。

ネットワークチャンクの区切りはフレームの区切りと一致しません。1 回の読み取りで半分のフレームだけ、または複数フレームを受信することがあります。受信データをバッファーに蓄積し、改行で区切り、空行に達した時点で初めてそのフレームを処理してください。

互換性のルール​

認識できないイベント名と使用しないフィールドは無視してください。 バージョンを変更せずに新しいイベントやフィールドが追加されることがあります。未知のイベントでエラーになるクライアントは動作しなくなります。

安定したイベント​

event:ペイロード意味
(名前なし){ text }回答本文の次の部分。既存の本文に追加します。地名の周りに [[Name]] マーカーが含まれる場合があります。
phase{ type: "phase", phase: "thinking", session_id }リクエストが受理され処理が始まりました。phase は常に "thinking" です。
start{ type: "start", session_id, purpose: "control" }本文のストリーミングがまもなく始まります。
place{ name, coordinates?: { lat, lng }, address?, category?, icon?, source?, id?, unverified? }回答中の場所。name で統合します。同じ名前で最初に受け取った座標が最終値です。source: "vendor" は組織データの場所、source: "map" は表示中の公開済み地図にすでにある場所を表します。
place_linked場所のフィールドと is_update?送信済みの場所に関する追加情報。同じ name の場所に統合し、その場所が未受信なら無視します。
early_actions{ type: "early_actions", actions: [ { type, payload } ], places_count, is_partial: true }回答の完了前に適用できる地図操作。2 か所以上に座標が付いた時点で送信されます。
prompt_options{ type: "prompt_options", schema_version, kind, question, allow_free_text, options: [ { label, send_text } ] }質問が曖昧な場合の選択肢。選択肢を提示し、選ばれた send_text を次のユーザーメッセージとして送信してください。
route_clear{}描画済みルートを消去します。新しいルートが続きます。
route{ type: "route", schema_version, id?, profile, origin, destination, primary, alternatives[], comparison[], stops?, color?, label?, transit?, attribution? }算出されたルート。道順の質問では本文より前に届くため、本文送信中に地図を描画できます。
end{ type: "end", full_text, places[], actions[], question_type, response_time, total_tokens?, dropped_places? }回答が完了しました。これが確定した結果です。
error{ type: "error", message, code?, partial_text }回答が失敗しました。end の代わりに送信されます。
quotaサーバーキーの場合は { type: "quota", product, meter, tier, used, limit, reset_at, period }、セッショントークンの場合は { type: "quota", meter, reset_at }呼び出しの課金後における組織の AI クレジット使用量。end または error の後に届く最後のイベントです。quotaを参照してください。
: keep-aliveコメント行無通信が 10 秒続いた際のハートビート。内容は無視し、活動として計上してください。

削除済み:grounding(2026-09-05)。現在は送信されません。

リアルタイムデータのカードとレイヤー​

リアルタイム情報や観測値に関する質問では、以下のイベントが追加されることがあります。カードは本文より前に届き、レイヤーは本文の途中または後に届く場合があります。これらは追加要素です。対応しているものを描画し、それ以外は無視してください。ここに示すフィールドは今後追加される可能性があります。

event:ペイロード用途
weather_cardlat、lng、name、気温(temp_c、temp_f)、conditions、任意の forecast[] を持つオブジェクト場所の現在の天気。
weather_layerlayer、tile_path_template、tile_size、max_zoom、scope、attribution を持つオブジェクト地域の気温オーバーレイ。
satellite_cardname、norad_id、lat、lng、altitude_km、velocity_kms、observed_at を持つオブジェクト指定された人工衛星の位置。
constellation_layergroup、{ name, norad_id, lat, lng } の features[]、任意の track を持つオブジェクトカードに示された衛星の周辺にある衛星。
building_cardlat、lng、任意の name、height_m、num_floors を持つオブジェクト建物の情報。
trees_cardlat、lng、count、radius_m を持つオブジェクトある地点付近で調査された樹木。
heritage_cardlat、lng、count、sites[] を持つオブジェクトある地点付近の文化遺産。
rail_cardlat、lng、lines[]、任意の nearest_station を持つオブジェクトある地点付近の鉄道路線。
arrivals_cardlat、lng、stop、departures[]、alerts[]、attribution を持つオブジェクト停留所の公共交通機関の発車時刻。
vehicles_layeroperator、vehicles[]、shapes[]、attribution を持つオブジェクトカードの停留所や路線に関する交通車両の位置。
streetview_cardlat、lng、image_id、image_lat、image_lng を持つオブジェクト場所の付近のストリートレベル画像。

これらが送信された場合、end は同じ名前で次の 5 種類を再掲します。イベントを取り逃したクライアントでも読み取れるようにするためです:weather_card、satellite_card、constellation_layer、weather_layer、vehicles_layer(例:end.weather_card)。他のカードは end に再掲されません。ライブイベントの一覧はプラットフォーム API では提供されません。データライセンスを参照してください。

診断用・実験用(仕様対象外)​

これらはストリームに現れる場合がありますが、正式な仕様には含まれません。依存しないでください。

event:ペイロード備考
debug{ scope, … }内部診断情報。通常のリクエストでは送信されません。
place_name_found{ name, is_early }地名に言及したことを早期に通知します。後続の place イベントを使用してください。

イベントの順序​

ストリームは次の段階を経ます。任意と示された段階は必ずしも現れません。

  1. 任意。 source: "vendor" を持つ place イベント。キーに vendor スコープがある場合、組織独自のデータから最大 3 件の場所を先に送信します。これにより地図ですぐに描画できます。
  2. phase。回答自体が送る最初のイベントです。
  3. 任意。 回答の準備中は : keep-alive コメントが送信されます。
  4. 任意。 本文に先立つイベント:prompt_options、または route_clear とそれに続く route、およびカード。
  5. start。
  6. テキストフレーム。place、place_linked、early_actions が混在し、場合によっては route_clear、route、レイヤーのイベントも含まれます。無通信時にはキープアライブが送られます。
  7. 任意。 本文終了後に届く place、place_linked、レイヤー、ルートの各イベント。
  8. end または error。
  9. 任意。 quota。
  10. サーバーが接続を閉じます。

クライアントでは次の 2 点に注意してください。

  • end は最後のイベントではありません。 本文の接続が閉じるまで読み続けてください。途中で止めると quota を受け取れません。
  • end と error のどちらもなく接続が閉じる場合があります。 例えばネットワーク切断時です。終端イベントなしで閉じたストリームは失敗として扱ってください。

ペイロードの詳細​

本文とマーカー​

テキストフレームにはテキストしか含まれず、構造化データが本文中に入ることはありません。本文には、near [[Louvre Museum]] のように地名を二重角括弧で囲んだマーカーが含まれることがあります。チャットパネルはこれを地図ピンへのリンクに変換します。プレーンテキストとして表示する場合は、括弧を削除して名前を残してください。

place​

フィールド型備考
namestring統合のキーとなる名称。
coordinatesobject { lat, lng }度数の十進表記。ない場合もあります。 回答が挙げた場所の位置を確認できないと、座標なしで unverified: true が送られます。ピンを置かないでください。
addressstring任意。
categorystring任意。
iconstring任意。場所を示す絵文字。
sourcestring任意。"vendor" は組織独自のデータからの場所です。"map" は閲覧中の公開地図にすでに表示されている場所です。地図側が描画するため、チャットパネルは独自のピンを追加しません。
idstring任意。独自データからの場所に含まれます。
unverifiedboolean任意。位置が確認されていない場合は true です。

場所には別のフィールドが含まれる場合があります。使用しないものは無視してください。

同じ名前が複数回届く場合があります。最初は座標付きで、後から詳細が補われます。名前ごとに 1 件を保持し、一度座標を得たピンは移動させず、後続イベントで他のフィールドを補完してください。

アクション​

early_actions.actions と end.actions は { type, payload } のリストです。

アクション種別ペイロード処理
map.fitBounds{ coordinates: [[lng, lat], …], padding, maxZoom, duration }座標に合わせてカメラの表示範囲を調整します。
places.highlight{ places: [ { name, lat, lng } ], options }これらの場所を強調表示します。
map.showRoute{ id, label, profile, coordinates: [[lng, lat], …], distance_m, duration_s, turn_by_turn[], transit?, attribution? }線を描画し、attribution を表示します。
route.clear{ id? }その id のルートを削除します。id がなければすべて削除します。

ほかのアクション種別が届く場合もあります。処理できないものはスキップしてください。座標の形式が 2 種類ある点に注意してください。場所は coordinates: { lat, lng }、線は [lng, lat] のペアのリストです。

route​

primary は描画する線を保持します:{ coordinates: [[lng, lat], …], distance_m, duration_s, turn_by_turn[] }。turn_by_turn の各ステップには text があり、direction_type、distance_m、duration_s、lat、lng が含まれることもあります。origin と destination はそれぞれ label を持ちます。alternatives[] は route_id を持つ別の線で、comparison[] は主ルートに対する各候補の delta_duration_s を示します。stops[] があれば、複数立ち寄り地点の { lat, lng, name } を順序どおりに格納します。

道路ルートには attribution: { text, url, license } があります。描画する際には、url へのリンクを付けた text を表示してください。公共交通機関のルートでは事業者のクレジットが transit 内にあります。

各 route イベントは id を持ちます。同じ id のルートを描画すると既存のルートが置き換わります。

end​

フィールド型備考
full_textstring回答全体。連結したテキストフレームよりこちらを優先してください。
placesarray順番に並んだ最終場所一覧。収集済みの場所と名前で統合します。
actionsarray最終的な地図操作。early_actions よりこちらを優先して適用します。
dropped_placesarray of strings任意。以前送信されたが最終回答に含まれない場所名。そのピンを削除します。
question_typestring質問種別を示す参考ラベル。
response_timenumber回答に要した秒数。
total_tokensnumber任意。回答で使用したトークン数であり、課金対象となる量です。

error​

event: error
data: {"type": "error", "code": "upstream_stall", "message": "The AI service stopped responding. Please try again.", "partial_text": "The Louvre sits"}

message はそのままユーザーに表示できます。partial_text は失敗する前に生成された本文です。code があるのは次の場合だけです。

場合code対処
回答の進行が止まった、またはストリームが最大長に達した"upstream_stall"再試行を案内してください。
回答中のその他の失敗なしmessage を表示してください。再試行で成功する場合があります。

error の後には end は送信されません。ただし quota が続く場合はあります。

quota​

フィールドは、ストリームを開始した認証情報によって変わります。

フィールド型サーバーキーまたは旧形式のキーセッショントークン
type文字列, "quota"はいはい
meter文字列はいはい
reset_at文字列、タイムゾーンオフセット付き ISO 8601はいはい
product文字列はいいいえ
period文字列はいいいえ
tier文字列はいいいえ
used数値はいいいえ
limit数値はいいいえ

セッショントークンは Web ページの訪問者が使用するもので、公開キーから交換して得たもの、または公開済み地図の訪問者セッションで発行されたものです。その quota イベントは期間のリセット時刻のみを示し、組織のプラン、使用量、上限は明かしません。ブラウザクライアントは used や limit を受信する前提にしないでください。429 quota_exceeded の本文にも同じルールが適用されます。クォータとレート制限を参照してください。

キープアライブとタイムアウト​

動作値クライアントの対応
チャットストリームのハートビート他の出力が 10 秒間ない場合に届く : keep-alive コメントコメントも含め、何か 1 バイトでも受信したらアイドルタイマーをリセットします。
アイドル接続約 1 分間沈黙した接続は通信経路で閉じられることがあります読み取り時のアイドルタイムアウトを 30~60 秒に設定します。全体のタイムアウトを短くしないでください。
最初の本文までの時間難しい質問では数十秒かかることがありますphase の時点から進捗を表示し、待ち時間を失敗とみなさないでください。
ストリームの最大時間約 10 分後、サーバーが upstream_stall を伴う error を送信します念のため、全体のタイムアウトを 10 分より少し長く設定します。

ストリームの中断と課金​

中断するには接続を閉じます。サーバーは約 10 秒以内にそれを検知し、回答の生成を停止します。

  • 正常に完了したストリームは、end.total_tokens に報告された使用トークン数で課金されます。
  • 完了前に中断または失敗したストリームは推定値で課金されます。少なくともリクエストで送った会話のサイズに相当し、それ以外の場合は送信済みのテキスト量から推定されます。そのため、事前に確保した量を上回る場合があります。最初のフレームで接続を閉じても長い会話が無料になるわけではありません。
  • 独自データに由来する場所(source: "vendor")は課金量に含まれません。

再試行は新しいリクエストとして再度課金されます。クォータとレート制限を参照してください。

要約とボタンのストリーム​

これら 2 つのエンドポイントは、Kaleidr Chat の場所カードに使われます。同じフレーム形式、名前のないテキストフレーム、最後の quota イベントを使用します。通常のチャットストリームとは 3 点異なります。phase イベントがないこと、場所やアクションのイベントがないこと、そしてキープアライブがないことです。アイドルタイムアウトは 60 秒にしてください。

どちらもストリーム開始前に長すぎるフィールドを 422 field_too_long で拒否し、記載されていないフィールドは無視します。エンドポイントを参照してください。これらのストリームが中断・失敗した場合の課金は送信済みテキスト量に基づく推定であり、事前確保量を超えません。

POST /chat/summary/stream、場所の場合:

  1. 任意。 { type: "address", address, source } をペイロードとする address
  2. { type: "start", poi_type } をペイロードとする start
  3. 任意、複数回届く場合あり。 { type: "url", website, source } をペイロードとする url
  4. { text } をペイロードとするテキストフレーム
  5. { type: "end", full_text, summary, poi_type, category, city, country, sources[], website?, total_tokens? } をペイロードとする end、または { type: "error", message, partial_text } をペイロードとする error
  6. 任意。 quota

POST /chat/summary/stream、建物の場合(type: "building"):

  1. { type: "start", address } をペイロードとする start
  2. テキストフレーム
  3. { type: "end", full_text, parsed, total_tokens? } をペイロードとする end、または error
  4. 任意。 quota

POST /chat/button/stream:

  1. { type: "start", query_type } をペイロードとする start
  2. テキストフレーム
  3. { type: "end", full_text, reply, query_type, first_token_ms, total_ms, total_tokens? } をペイロードとする end
  4. 任意。 quota

ボタンのストリームには error イベントはありません。開始後に失敗すると end なしで接続が閉じます。開始前に失敗した場合は HTTP 500 と {"detail": "Button chat stream error"} が返されます。

POST /spot/overview/stream は上記の場所要約と同じフレームを送信します。その前に、ペイロード { type: "place", name } を持つ place フレームが届きます。name は説明対象の場所または地域の正式な名前(例:"Springfield, Ohio, United States of America")で、ラベル表示やコピーに使えます。このフレームは他のすべてのフレームより先に届き、省略されることもあります。チャットストリームの place イベントとは別物で、座標は含みません。説明できない ref に対しては、要約の代わりに { type: "error", message, ref } を含む error フレーム 1 つが返されます。エンドポイントを参照してください。

関連ページ​