Model features
Streaming responses
Display partial text, distinguish stream formats, and recover interrupted requests.
Choose the right parser
| Endpoint | Format | Completion |
|---|---|---|
| /v1/chat/completions | Text in choices[].delta.content | Inspect finish_reason; raw SSE ends with [DONE]. |
| /v1/responses | Responses events such as response.output_text.delta | Wait for response.completed; handle error, failed, and incomplete events. |
| /api/v1/llm/responses | Kendr start, status, delta, done, error events | The done payload contains the final result. |
| /api/v1/images/generations | Image progress with optional partial frames | Use 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.