Khai Python SDK
Stream chatbot turns to Khai for evaluation from any cloud — no access granted to Khai.
Install
pip install khai-sdk
Quickstart
Set your key in the environment rather than in source:
export KHAI_API_KEY="khai_..."
from khai import KhaiClient
khai = KhaiClient() # reads KHAI_API_KEY; base_url defaults to https://api.getkhai.ai
resp = khai.ingest_turn(
user_query="How do I pay my bill?",
agent_response="You can pay online at ...",
session_id="chat-123",
agent_id="YOUR_AGENT_ID",
)
print(resp.status, resp.result.trust_score if resp.evaluated else resp.reason)
Every turn is idempotent
You do not have to think about retries. When you omit them, the SDK fills in a
timestamp (UTC, ISO-8601) and a UUID response_id when the turn is created,
and keeps them for every retry. The backend deduplicates on response_id, so a
turn resent after a timeout, a 5xx, or a network outage is answered with
status: duplicate instead of being stored twice.
If your platform already has a per-reply id (Dialogflow responseId, Lex,
Copilot Studio), pass it as response_id and the same guarantee holds even
across restarts of your own process.
Fire-and-forget
ingest_turn_async queues the turn and returns immediately, so it never blocks
your chatbot's response path. Failed deliveries are buffered and retried. Both
the queue and the buffer are capped at max_queue_size (default 10,000 turns);
when full, the SDK drops a turn and reports it through on_error as
KhaiQueueFullError rather than growing memory during an outage. Open clients
are flushed once at interpreter exit.
with KhaiClient() as khai:
khai.ingest_turn_async(
user_query=user_msg,
agent_response=bot_reply,
session_id=session_id,
agent_id="YOUR_AGENT_ID",
)
# ... keep serving; turns flush in the background, and on close().
Batch
from khai import IngestTurn
khai.ingest_batch([
IngestTurn(user_query="...", agent_response="...", session_id="s1", agent_id="a1"),
IngestTurn(user_query="...", agent_response="...", session_id="s1", agent_id="a1"),
])
Redact PII before sending
def redact(payload: dict) -> dict:
payload["user_query"] = mask_emails(payload["user_query"])
return payload
khai.set_redactor(redact)
Errors
All errors derive from KhaiError:
| Error | Meaning |
|---|---|
KhaiAuthError |
API key missing/invalid (401/403) |
KhaiRateLimitError |
Per-key rate limit exceeded (429) |
KhaiAPIError |
Other non-success status |
KhaiConnectionError |
Network/timeout (already retried) |
KhaiQueueFullError |
Fire-and-forget queue/buffer full; a turn was dropped (via on_error) |
KhaiConfigError |
Bad client configuration (missing key, non-HTTPS base URL) |
Configuration
| Setting | Argument | Environment variable | Default |
|---|---|---|---|
| API key | api_key |
KHAI_API_KEY |
required |
| Base URL | base_url |
KHAI_BASE_URL |
https://api.getkhai.ai |
| Request timeout (s) | timeout |
— | 10.0 |
| Retries on 429/5xx/network | max_retries |
— | 3 |
| Queue / buffer cap | max_queue_size |
— | 10000 |
base_url must be https://; plain http:// is accepted only for localhost.
Releasing (maintainers)
Releases are cut from tags and published by CI through PyPI trusted publishing; no one uploads from a laptop and no API token is stored anywhere.
-
Bump
__version__insrc/khai/_version.pyand move theUnreleasedentries inCHANGELOG.mdunder the new version. Merge via pull request. -
Tag the merged commit and push the tag:
git tag v0.1.0 && git push origin v0.1.0
-
The
Releaseworkflow builds the sdist and wheel, publishes to TestPyPI, installs from TestPyPI and imports the package, then waits for a reviewer to approve thepypienvironment before publishing to PyPI and creating the GitHub Release. A tag whose version does not match__version__fails fast.
Release files for khai-sdk 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| khai_sdk-0.1.0.tar.gz | 29.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| khai_sdk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.4 kB
Release files / khai_sdk-0.1.0.tar.gz
| Download URL | khai_sdk-0.1.0.tar.gz |
|---|---|
| Size | 29.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7f3a9dad726052be4ccfb0a67e7796f097d64c4fe3d89728979fc6bc423d7994
|
|
BLAKE2b-256 checksum How to use checksums |
f5f12d0d066de691e8a1c3db1fc9ecc644393d59dc1b9090a6663b8325d478ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / khai_sdk-0.1.0-py3-none-any.whl
| Download URL | khai_sdk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3da48fc4dd12f30b3738d470bc29797be5a0e7ae441a977177905e314932e064
|
|
BLAKE2b-256 checksum How to use checksums |
b3600c5e4533835c8ab21dcd4bdcba62ab1d323995f620f8b7cfffb89b1615f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency log