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

SSE wire contract

AI chat endpoint は Server-Sent Eventstext/event-stream)を stream します。 このページでは POST /chat/control/stream が使用する control-stream contract を 説明します。source of truth は @kaleidr/inference-ui 内の parser + types (packages/inference-ui/src/control/sse.tstypes.ts)です。 kaleidr.js を使用する場合、chat bundle が解析するため、このページが必要なのは custom client を構築するときだけです。

/chat/summary/stream/chat/button/stream は異なる SSE contract を使用します。ここでは扱いません。これらの endpoint で control-stream parser を再利用しないでください。

互換性ルール

Client は 未知の event name を無視する必要があります。stable contract には version bump なしで新しい event が追加される場合があります。下の "diagnostic / experimental" table にある downstream event は contract ではありません — official client は無視し、将来消える可能性があります。

Stable event

Payload は control parser が想定する形式です。startphase field はありません (phase event にのみ存在します)。

event:PayloadMeaning
(unnamed){ text }増分 prose token。[[Place]] marker を含む場合があります。
phase{ type: "phase", phase, session_id }stream 前の lifecycle。
start{ type: "start", session_id, purpose? }Stream 開始。
place{ name, coordinates: { lat, lng }, address?, category?, source?, id? }解決された place(merge-by-name → map pin)。source: "vendor" は org が upload した data 由来の place を示します。
place_linkedplace fields + is_update?すでに emit された place を enrich。
early_actions{ type: "early_actions", actions: [ { type, payload } ], places_count?, is_partial? }完全な reply より前に送る map action(fitBounds / route / highlight)。
prompt_options{ type: "prompt_options", schema_version, kind, question, allow_free_text, options: [ { label, send_text } ] }曖昧さ解消 chip — tappable option として表示し、その option の send_text を次の user message として送信します。
route_clear{}新しい route が到着する前にすべての overlay を clear。Stable.
route{ type: "route", schema_version, id?, profile, origin, destination, primary, alternatives[], comparison[], stops?, connectors?, color?, label? }journey 表現の turn — engine-computed route。prose より先に emit され、回答 streaming 中に map が描画できます。
quota{ type: "quota", product, meter, tier, used, limit, reset_at, period }stream 中 meter — remaining budget を表示。
end{ type: "end", full_text, places[], actions[], question_type, response_time, total_tokens? }Terminal envelope — 完全な結果。
error{ type: "error", message, code?, partial_text? }Terminal error。
: keep-alivecomment lineProxy keep-alive(~10s)。無視。

削除済み:grounding(2026-09-05)。Grounding は引き続き回答に影響しますが、 wire 上に frame を置きません。

Diagnostic / experimental(non-contract)

これらは emit される implementation detail です。official client は 無視します。依存しないでください。

event:PayloadNotes
debug{ scope, … }内部 diagnostic。変更または削除される可能性があります。
place_name_found{ name, is_early? }Non-contract。official client は無視。

Token と structured data

Unnamed event は plain prose を stream します。place が参照される箇所に inline [[Place]] marker を含む場合があります(例:…cafes near [[Louvre]]…) — clean display では削除するか、prose を完全に無視して structured event から UI を駆動してください。

Structured data は event として到着し、prose 内には入りません。 Resolved place は geocode されるにつれて place(late metadata は place_linked)で stream されます。 map action は early_actions、route は route_clear の後に route で届き、 authoritative final payload は end event です。 一般的な client は place event の到着に合わせて pin を render し、 end を source of truth として扱います。

Minimal client

const res = await fetch(`${API}/inference-api/b2b/v1/chat/control/stream`, {
method: 'POST',
headers: { 'X-Api-Key': key, 'Content-Type': 'application/json', Accept: 'text/event-stream' },
body: JSON.stringify({ messages: [{ role: 'user', content: 'cafes near the Louvre' }] }),
});
const reader = res.body.getReader();
// …decode chunks, split on \n\n, parse `event:` + `data:` lines
// IMPORTANT: ignore any unknown event name (forward-compat rule above).

request body は Endpoints、failure handling は Errors を参照してください。