Model features

Streaming responses

Display partial text, distinguish stream formats, and recover interrupted requests.

Choose the right parser

EndpointFormatCompletion
/v1/chat/completionsText in choices[].delta.contentInspect finish_reason; raw SSE ends with [DONE].
/v1/responsesResponses events such as response.output_text.deltaWait for response.completed; handle error, failed, and incomplete events.
/api/v1/llm/responsesKendr start, status, delta, done, error eventsThe done payload contains the final result.
/api/v1/images/generationsImage progress with optional partial framesUse final done; see image progress.

Check the content type before choosing a parser. Buffered requests or replays may return JSON. Custom MCP and some tool combinations return a complete answer; X-Kendr-Stream-Mode: buffered and X-Kendr-Buffered-Reason explain supported buffering cases.

Stream Chat Completions in Python

Use the client from the Python guide. Persist the request ID before sending.

request_id = str(uuid4())
finished = False
with client.chat.completions.create(
    model="kendr-intelligent",
    messages=[{"role": "user", "content": "Explain a safe release process."}],
    stream=True,
    extra_headers={"Idempotency-Key": request_id},
) as stream:
    for chunk in stream:
        if not chunk.choices:
            continue
        choice = chunk.choices[0]
        print(choice.delta.content or "", end="", flush=True)
        if choice.finish_reason == "stop":
            finished = True
if not finished:
    raise RuntimeError("Incomplete stream; recover with " + request_id)
print()

Stream Responses in JavaScript

Use the client and randomUUID import from the JavaScript guide.

const requestId = randomUUID();
const stream = await client.responses.create({
  model: "kendr-intelligent", input: "Explain a safe release process.", stream: true,
}, { headers: { "Idempotency-Key": requestId } });
let completed = false;
for await (const event of stream) {
  if (event.type === "response.output_text.delta") process.stdout.write(event.delta);
  if (event.type === "response.completed") completed = true;
  if (["error", "response.failed", "response.incomplete"].includes(event.type)) {
    throw new Error(`Stream did not complete: ${requestId}`);
  }
}
if (!completed) throw new Error(`Interrupted stream: ${requestId}`);

Handle streaming correctly

  • Send stream: true and keep the HTTP connection open for server-sent events.
  • Parse complete SSE events rather than treating arbitrary network chunks as complete JSON messages.
  • Handle start, status, delta, done, and error events where present.
  • Accumulate text deltas for display, but treat the terminal event as the authoritative completion and usage record.
  • If the connection fails before completion, call the empty-body POST /api/v1/llm/responses/replay with the original idempotency key. That lookup can never start another generation.
  • Do not assume every model emits identical timing or intermediate events; depend only on the compatible event fields you use.

Recover after a disconnect

curl -X POST https://api.kendr.org/api/v1/llm/responses/replay \
  -H "Authorization: Bearer $KENDR_API_KEY" \
  -H "Idempotency-Key: YOUR_ORIGINAL_REQUEST_ID"

This lookup has no JSON body and cannot start another generation. A missing or still-running result is not successful completion. See replay rules. Do not present partial output as final.