The foundation layer

KAILib — the foundation every system stands on.

One small, dependency-free library that unifies AI, data, and networking behind a single resilient surface. Local-first when it matters, connected when it helps — the spine beneath the portfolio and the base for ObserverWare_AI, mobile backends and embedded systems alike.

Dependency-free base Local or connected Resilient by design One surface
01 — WHY IT EXISTS

Build the foundation once. Stand on it forever.

Every serious system needs the same plumbing: talk to a model, keep data safe, reach the services it depends on — and stay standing when any of those wobble. Rebuilding that per project is wasted effort and four different ways to fail. KAILib is that plumbing, solved once, so a new system — an offline appliance, a connected mobile backend, or an embedded sensor pipeline — starts from a hardened base and spends its effort on what makes it different.

01

Local or connected — your call

Run entirely on hardware you control, reach cloud and network services, or both. Sovereignty is a capability you can switch on, not a limit you're stuck with.

02

Dependency-free base

The core installs with zero third-party packages — just the standard library. Small enough to trust, easy to audit, quick to embed.

03

Resilient everywhere

Every call — model, database, or network — runs through one reliability layer: retry with backoff, a circuit breaker, a concurrency limit.

04

Composable, not monolithic

Three independent subsystems behind clear seams. Adopt one piece or the whole thing; swap a backend without touching your code.

from kai_lib import KAIApp

app = KAIApp()              # local model + local store by default — or point it anywhere

# 1 · AI — local model or a networked service; cached, retried, circuit-broken
answer = app.llm.ask("Summarize today's session.")

# 2 · data + memory — one API over SQLite / Postgres
app.store.append_event("audit", "answered", {"a": answer})

# 3 · the network — guarded fetch, cloud services, search
page = app.web.fetch("https://example.org")

The whole foundation in one screen. Swap the backends — the code stays the same.

02 — THE ARCHITECTURE

Three subsystems. One resilient core.

Independent by design — use one without the others. Local-first when it matters, connected when it helps.

AI

AI — local or connected

Local models (Ollama), networked services, or — when the model lives on another box — a hardened hop through KQAI: point an AIBBProvider at it and the call is authenticated, encrypted and audited. All behind one provider-agnostic surface, with real token streaming and an answer cache.

  • Streaming
  • Cached
  • Swappable
  • Guarded hop
STORE

Data & Memory

One interface over SQLite (default) and Postgres: a JSON key/value store, an append-only event log, and parameterized SQL. Never an ORM.

  • SQLite
  • Postgres
  • Event log
NET

Connected

The network as a first-class citizen: guarded fetch, cloud services and search — with an SSRF guard and size/time caps so reaching out never becomes a liability.

  • Fetch
  • Cloud & search
  • Guarded

The resilience core — shared by all three

Every call — model, database, or network — runs through the same reliability layer: retry with jittered backoff, a circuit breaker that fails fast, and a concurrency limiter that waits for a slot (and sheds cleanly if the wait runs past its timeout, rather than piling work onto a struggling backend). One behavior, one failure vocabulary, everywhere.

  • Retry + jitter
  • Circuit breaker
  • Concurrency limit
  • Typed errors
03 — THE PUBLIC SURFACE

Small enough to hold in your head.

Everything an application calls, grouped by subsystem. Signatures show intent, not implementation — internals stay proprietary. As of v0.4 the records you read back — health, events, completions — are typed and frozen, so you branch on named fields and never guess a dictionary key.

Entry point

kai_lib · KAIApp
KAIApp(*, llm?, store?, web?, …configs) · KAIApp.from_env()
Build directly, or entirely from environment variables. Subsystems are created lazily — you only initialize (and only need the dependencies of) what you touch.
app.llm app.store app.web
llm and store are sovereign by default; web leaves the machine and is opt-in — it is never constructed for you.
app.health() → SystemHealth · app.close()
Typed health for whichever subsystems have been built; clean shutdown. Also a context manager (with KAIApp() as app:).

AI — local or connected

app.llm · LLMClient
llm.ask(prompt, *, system?, options?, use_cache=True) → str
The everyday call: returns the model's text answer, with cache + retry + circuit-breaker + concurrency limit applied automatically.
llm.complete(prompt, …) → Completion
Same as ask, but returns the structured record: text, model, token counts, and whether the answer came from cache.
llm.stream(prompt, …) → Iterator[str]
Yields tokens as they arrive (real streaming). Passes through the limiter and breaker; never cached — a stream can't be safely replayed.
llm.health() → Health
Provider, model, reachability, breaker (a BreakerState), in-flight vs. capacity, and cache hit-rate.
AIBBProvider(url, *, token, pin) · kai_lib[aibb]
Same LLMProvider surface, but the model is on another box: point it at a KQAI — a hardened, authenticated, audited gateway to [Ollama + model] over pinned TLS. Swapping a local Ollama for a remote one is a config change, not an app change.

Data & memory

app.store · Store
store.put(ns, key, value) · get · delete · keys(ns)
A namespaced JSON key/value store — config, state, cached objects.
store.append_event(stream, kind, payload) → Event
Append one immutable, timestamped event to a named stream. The spine for telemetry, audit trails, and sequential-event data.
store.read_events(stream, *, limit=100, after_id=0) → [Event]
Read a stream forward, in order, from a cursor — for replay, analysis, or tailing.
store.query(sql, params) → [dict] · store.execute(sql, params) → int
A parameterized-SQL escape hatch (never string-built). SQLite by default (sovereign, zero-ops); Postgres for servers — same contract either way.

Connected

app.web · WebClient · opt-in
web.fetch(url) → FetchResult
GET a URL with a timeout, a response-size cap, retry + breaker, and an SSRF guard that refuses localhost / private addresses unless explicitly allowed.
web.search(query, *, limit=5) → [SearchResult]
Delegates to a pluggable search provider (bring your own backend/key). Raises SearchNotConfigured if none is set.

The typed vocabulary — new in v0.4

kai_lib.types · frozen
The stable records every call returns. All are frozen (immutable) and carry .as_dict() for the moment you actually need JSON — the dict is an export, never the API.
BreakerStateHealthWebHealthSystemHealthEventCompletionFetchResult

Configuration & one error tree

kai_lib.config · kai_lib.errors

Config — validated, from-env capable

ResilienceConfigLLMConfigStoreConfigWebConfig

Tune retries, backoff, breaker thresholds, concurrency, cache, model, timeouts, size caps — all checked on construction.

One error tree

Catch broadly (KAILibError) or narrowly. Retryable errors also subclass TransientError; a tripped breaker raises CircuitOpenError. Because WebBlockedError is a child of WebError, except WebError catches it too.

KAILibError ├─ TransientError # safe to retry │ └─ LLMTimeout · WebTimeout · StoreConnectionError ├─ CircuitOpenError # breaker open → fail fast ├─ ConfigError ├─ LLMError → ModelNotFoundError ├─ StoreError → StoreDependencyError └─ WebError → WebBlockedError · SearchNotConfigured
04 — WORKED EXAMPLES

Beyond hello-world.

Each uses only the public surface. Swap the backends via config and the code is unchanged — the whole point of a foundation.

A

Grounded assistant with an audit trail

Answer from a local model — but only when the system is healthy — and record every question and answer as an immutable event, so there's a complete, replayable record of what was said and when.

from kai_lib import KAIApp, BreakerState

app = KAIApp()                                   # local model + local store, sovereign

def answer(question: str) -> str:
    h = app.llm.health()                          # typed Health — no dict keys to guess
    if not h.healthy or h.breaker == BreakerState.OPEN:
        return "Service degraded — please retry shortly."   # fail honest, not fake

    reply = app.llm.ask(question, system="Answer only from what you know; say so if unsure.")
    app.store.append_event("assistant", "answered",
                          {"q": question, "a": reply, "model": h.model})
    return reply

# later: replay the whole conversation for review / export
for e in app.store.read_events("assistant", limit=500):
    print(e.ts, e.payload["q"], "→", e.payload["a"][:60])

To make the record provable (tamper-evident, third-party-verifiable), emit the same event to a dedicated audit service rather than growing crypto here — KAILib records, it doesn't notarize.

B

Resilient batch processing

Summarize a large pile of documents concurrently. The concurrency limiter caps in-flight work — it waits for a free slot rather than flooding the backend — the breaker fails fast if the model goes down mid-run, and the cache serves only identical prompts.

import asyncio
from kai_lib import KAIApp
from kai_lib.config import ResilienceConfig

# admit 8 calls at a time: gather() may launch thousands; the limiter holds the line
app = KAIApp(resilience=ResilienceConfig(max_concurrency=8))

async def summarize_all(docs: list[str]) -> list[str]:
    async def one(text):
        return await asyncio.to_thread(
            app.llm.ask, f"Summarize in 2 lines:\n{text}")
    return await asyncio.gather(*(one(d) for d in docs))

summaries = asyncio.run(summarize_all(load_docs()))
app.store.put("runs", "latest", {"n": len(summaries)})
print(app.llm.health().cache_hit_rate)          # typed Health.cache_hit_rate
C

Local-first, connected when it helps

Stay on the local model for the reasoning, but reach the network for a fact when the task genuinely needs one — explicitly, and guarded. A sovereign deployment simply never enables web; the same code runs offline.

from kai_lib import KAIApp
from kai_lib.config import WebConfig
from kai_lib.errors import WebError   # parent — also catches WebBlockedError

# web is off unless you construct it; here we opt in deliberately
app = KAIApp(web_config=WebConfig(timeout=15))

def brief(topic: str, source_url: str | None = None) -> str:
    context = ""
    if source_url:
        try:
            page = app.web.fetch(source_url)         # SSRF-guarded, size-capped
            context = page.text[:4000]
        except WebError as e:                     # blocked, too large, timeout — all WebError
            context = f"(source unavailable: {e})"    # degrade, don't crash
    return app.llm.ask(f"Brief me on {topic}.\nContext:\n{context}")
D

An edge gateway event pipeline

A field gateway streams sensor readings into the append-only log all day; a periodic pass asks the local model for an anomaly summary — entirely on-premise, no cloud dependency. The event stream doubles as the audit record and the analysis dataset.

from kai_lib import KAIApp
from kai_lib.config import StoreConfig

app = KAIApp(store_config=StoreConfig(dsn="/var/lib/edge/events.db"))

def on_reading(sensor: str, value: float):         # called from the device loop
    app.store.append_event(f"sensor/{sensor}", "reading", {"v": value})

def hourly_summary(sensor: str, last_id: int) -> str:
    events = app.store.read_events(f"sensor/{sensor}", after_id=last_id, limit=1000)
    series = [e.payload["v"] for e in events][-200:]    # bound the window on constrained hardware
    lo, hi = min(series), max(series)
    return app.llm.ask(f"Range {lo}–{hi}. Flag anything unusual in these {len(series)} readings: {series}")
E

A 24/7 service loop

Long-running services check health and the breaker before doing work, and back off when the backend is struggling — so a transient outage degrades gracefully instead of hammering a downed model. The with block guarantees a clean shutdown.

import time
from kai_lib import KAIApp, BreakerState

with KAIApp() as app:                        # context manager → guaranteed close()
    while serving:
        h = app.llm.health()
        if h.breaker == BreakerState.OPEN or not h.healthy:
            time.sleep(10); continue                # fail fast, breathe, retry
        job = next_job()
        deliver(app.llm.ask(job.prompt))
        app.store.append_event("service", "served", {"job": job.id})
F

The model on another box — over a guarded hop

The model doesn't have to live in-process. When it runs on a separate, hardened box, point an AIBBProvider at a KQAI — a secure gateway to [Ollama + model] — and the app code is unchanged. Same ask(), now over pinned TLS, authenticated and audited on the box.

from kai_lib import LLMClient
from kai_lib.llm import AIBBProvider        # the kai_lib[aibb] extra

client = LLMClient(AIBBProvider(
    "https://127.0.0.1:8443",          # a KQAI in front of a boxed Ollama
    token="…",                          # bearer token (client-cert mTLS is on the KQAI roadmap)
    pin="sha256/…"))                     # pin the box's cert — no MITM

print(client.ask("What's the torque spec for the caliper bolt?"))
# same call as a local model — now authenticated, encrypted, and audited on the box

Because AIBBProvider is just another provider, moving from a local Ollama to one — or a fleet — of KQAIs is a config change, not an app change. client.stream() streams live over the same secured channel. See kqai.html.

Interface and behavior only. Internal implementation, algorithms, and tuning remain proprietary to Koperwas Systems Inc.

05 — BUILT ON KAILib

The spine beneath today's systems — and tomorrow's.

KAILib is the shared foundation the portfolio stands on — from offline appliances to connected mobile and embedded systems. Each one adds its own science and purpose on top; none rebuilds the basics.

SYNTHEKOS
Sovereign local AI appliance

Grounded, verified local-AI appliances. The same principles KAILib is built on, at platform scale.

synthekos.com →
KETRACK
Real-time coordination

Live coordination for people in motion — real-time telemetry and voice, on hardware you control.

ketrack.com →
PORTAGE
AI intake & routing · hello311

Requests understood by AI, routed by your rules, with a signed record of every decision.

hello311.ca →
Your next system
Starts here

Mobile, embedded, cloud or on-prem — new systems begin on KAILib instead of a blank page, and inherit the foundation from day one.

build on the spine →
One foundation. Many systems.

Building something that has to hold up?

KAILib is the through-line beneath the whole portfolio and the ground floor for what's next — offline, connected, or both. To talk architecture, early access, or the road ahead, start a conversation.