A zero-dependency Web client and a standard-library-only Python client. No package to install, no build step, no vendor lock-in — just HTTP.
Both clients do the same three things: open a session, send turns, complete the session to build the model. The engine keeps the session server-side, so a turn is one small JSON POST.
# pip install nothing from kkos_client import KKOS kk = KKOS(api_key="kk_live_...", token="<user token>") model = kk.run_text_session([ "I usually decide fast and say what I think.", "When someone hesitates, I push them to decide.", "I would rather hear a direct answer.", ]) for t in model["traits"]: print(t["name"], t["score"], t["confidence"])
<script src="/sdk/kkos.js"></script> <script> const kk = new KKOS({ token: userToken }); const model = await kk.runTextSession([ "I usually decide fast and say what I think.", "When someone hesitates, I push them to decide.", "I would rather hear a direct answer.", ]); kk.traits(model).forEach(t => console.log(t.name, t.score, t.confidence)); </script>
/mirror/complete returns
{session_id, model_id, redirect, model} — the model sits under model.
Call completeModel() to get it unwrapped, or traits(resp) to normalise the
dimension list out of either shape.
/mirror/start, /mirror/message and
/mirror/complete are login-gated and need Authorization: Bearer <uid.ts.sig>.
A platform API key on its own is enough for /health, /plans and
/mirror/voices, but a session attempt with only a key returns
401 login_required. This is deliberate: a model is personal data, so it is never built for an
anonymous caller.
urllib only — drops into any Python 3.8+ project without touching requirements.python example.pyexample.py; if you are wiring it into a product UI, start from example-web.html.All paths are relative to the base URL. The full OpenAPI schema is served at /openapi.json and rendered at /docs.html.
| Method | Path | Client method | Credential |
|---|---|---|---|
| GET | /health | health() | public |
| GET | /api/v1/plans | plans() | public |
| GET | /api/v1/mirror/voices | voices() | API key |
| POST | /api/v1/mirror/start | start() | user token |
| POST | /api/v1/mirror/message | message() | user token |
| POST | /api/v1/mirror/complete | complete() · completeModel() | user token |
| GET | /api/v1/mirror/model/{id} | get_model() | API key |
| DELETE | /api/v1/mirror/model/{id} | delete_model() | API key |
| POST | /api/v1/mirror/model/{id}/regenerate | regenerate_model() | API key |
| POST | /api/v1/mirror/compare | compare() | API key |
| POST | /api/v1/mirror/tts | tts() · tts_to_file() · speak() | API key |
| POST | /api/v1/mirror/stt | stt() | API key |
| POST | /api/v1/life-stage | — | API key |
| GET | /api/v1/auth/me | me() | user token |
KKOSError with status, payload, url and method, so you can branch on 401 (re-authenticate) versus 429 (back off) versus 5xx (retry) instead of parsing strings.The block below is not illustrative — it is the response from an actual run on 2026-09-12, with three user turns taken verbatim from example.py. Desensitised: no session identifier, no user identifier.
Session: 3 user turns, text mode · overall_confidence 0.60 · model_version hm-v1 · 11/11 dimensions returned
| Dimension | Score | Confidence | Evidence returned by the engine |
|---|---|---|---|
| directness | 95 | 0.95 | “I usually decide fast and say what I think, even if it is blunt.” |
| communication_style | 90 | 0.90 | “I usually decide fast and say what I think, even if it is blunt.” |
| decision_style | 90 | 0.90 | “I usually decide fast” |
| uncertainty_response | 85 | 0.80 | “When someone around me hesitates, I tend to push them toward a decision.” |
| ai_interaction_style | 80 | 0.70 | Repeated direct-answer preference when interacting with AI. |
| conflict_style | 70 | 0.60 | “say what I think, even if it is blunt.” |
| engagement | 70 | 0.50 | Responded consistently to questions from the assistant. |
| trust_disclosure_pattern | 60 | 0.50 | Shared personal preferences quickly in conversation. |
| openness | 50 | 0.40 | They openly stated their preference for bluntness. |
| emotional_expression | 45 | 0.50 | The word “honestly” conveys sincerity but not emotion. |
| reflection_style | 25 | 0.50 | Statements are brief and conclusive rather than exploratory. |
Summary returned: “The user strongly values directness and quick decisions, prefers blunt honesty over politeness, and tends to push others toward closure. Their communication is terse and conclusive…”
Cost of that run: 2 182 input tokens / 3 818 output tokens over 4 LLM calls, estimated $0.00262.
Read off the same run the table above reports — an unedited transcript, not an illustration. The silhouette is what the engine returned; the numbers are in the table.
Source: the verified run above — three turns, text mode, 2026-09-12, model_version hm-v1. Left radar: the eleven scores. Right bars: the confidence the engine attached to each of them. One run is a sample, not a verdict — the repeatability measurement is in the Effect Reports.
/api/v1/mirror/evi. Both SDKs leave it to you rather than shipping a socket abstraction — see the docs page for the session-settings handshake.localStorage only because it is a demo — do not ship that pattern in production.