Skip to main content

Kamiwaza Python SDK

Python client library for interacting with the Kamiwaza AI Platform. This SDK provides a type-safe interface to all Kamiwaza API endpoints with built-in authentication, error handling, and resource management.

Installation

pip install kamiwaza-sdk

Naming note: Install the package as kamiwaza-sdk, but import it as kamiwaza_sdk. A deprecated kamiwaza_client alias remains for older snippets, though new code should prefer kamiwaza_sdk.

Version compatibility: This SDK (version 0.5.1+) is incompatible with Kamiwaza versions before 0.5.1. Please ensure you're using the latest version of Kamiwaza.

Python SDK Usage

from kamiwaza_sdk import KamiwazaClient
from kamiwaza_sdk.authentication import UserPasswordAuthenticator
from kamiwaza_sdk.schemas.auth import PATCreate

client = KamiwazaClient("https://localhost/api")

# Option 1 (recommended): Personal Access Token
# export KAMIWAZA_API_KEY=<your-pat>
# client automatically loads the token and reuses it for every request.

# Option 2: bootstrap with username/password to mint a PAT
client.authenticator = UserPasswordAuthenticator("admin", "kamiwaza", client.auth)
pat = client.auth.create_pat(PATCreate(name="local-bootstrap")).token
print("Save this token:", pat)

Workroom-scoped automation

PAT/API-key clients should scope automation per request instead of calling workrooms.enter(), which is reserved for real selected-session binding. Use a local scoped client when a block of SDK calls should target one workroom:

with client.workroom_scope(workroom_id) as scoped:
    scoped.context.create_vectordb(name="project-vdb", engine="milvus")

workroom_scope() returns a new client that adds the explicit workroom scope header to its requests. It does not mutate the parent client or server-side selected-session state. It is not a client-side security boundary; the server must still authorize the caller for the requested workroom on every request.

Federation walkthrough (kamiwaza-mesh-v1.0.0)

Available in kamiwaza-sdk 1.0.0+ under the new top-level kamiwaza namespace, distinct from the legacy kamiwaza_sdk namespace above. See the design's §4.2.11 for the full surface.

The new kamiwaza namespace ships the federation-aware client. The eight-step demo author's setup.py flow uses only SDK calls — no kubectl exec, no manual SQL, no Keycloak admin REST:

  1. Pair LYRA with ORION — kz.federations.pair(...)
  2. Seed personas — kz.subjects.upsert(...) (replaces the v0.1.x two-phase KC recipe — see authoring-guide §6)
  3. Bind the cluster execution gate — kz.cluster.set_execution_gate(...) (replaces the kubectl exec recipe — see authoring-guide §9.1)
  4. Register the dataset — kz.datasets.create(...)
  5. Bind the dataset's attribute gate — kz.datasets.set_gate(...)
  6. Allowlist the brokered user + grant viewer — kz.federations["ORION"].users.add(...) plus kz.subjects.grants("user").create(...)
  7. Submit the federated job — kz.jobs.run(...)
  8. Observe the audit trail — kz.cluster.operations() / receiver-side gate_binding{,_set,clear} + subject_upsert audit events

Configure the client

import os
from kamiwaza import Kamiwaza

# Environment-driven config (recommended)
os.environ.setdefault("KAMIWAZA_BASE_URL", "https://lyra.kamiwaza.test")
os.environ.setdefault("KAMIWAZA_TOKEN", "<personal-access-token>")
kz = Kamiwaza.from_env()

# Or pass explicit values
kz = Kamiwaza(
    base_url="https://lyra.kamiwaza.test",
    token="<personal-access-token>",
)

# Use as a context manager so the underlying httpx transport is
# released cleanly:
with Kamiwaza.from_env() as kz:
    ...  # walkthrough below

Step 1 — Pair LYRA with ORION

The initiator drives the handshake. The receiver only needs the PSK propagated through DataHub plus its admin baseline ReBAC tuple (install-dev.sh seeds those automatically).

fed = kz.federations.pair(
    name="ORION",
    role="initiator",
    remote_url="https://orion.kamiwaza.test",
    remote_admin_token="<orion-admin-pat>",  # initiator-only
)
print(fed.id, fed.status)  # e.g. fed-orion-… PAIRED

If DataHub PSK propagation is mid-flight when the request lands on the receiver, the SDK retries with exponential backoff until the server's structured 503 (detail.reason == "psk_propagation_timeout") times out the budget — see kamiwaza.exceptions.FederationPairTimeoutError.

Step 2 — Declare the attribute vocabulary, then seed personas (M3 + M3.1)

Replaces the v0.1.x two-phase Keycloak admin recipe (see authoring-a-federated-demo.md §6). Two sub-steps:

Step 2a — Declare the realm's attribute vocabulary (M3.1, v0.3.6). Every attribute name a subject can hold must be declared in the realm BEFORE kz.subjects.upsert(...) writes it. Keycloak's realm default unmanagedAttributePolicy=None silently drops attribute writes for undeclared names — the M3.1 declared-vocabulary surface converts that silent drop into a 400 with structured remediation, so unknown names fail loudly at upsert time instead of returning success with empty attributes.

kz.cluster.declare_attribute("clearance", type="string")
kz.cluster.declare_attribute("country",   type="string")
kz.cluster.declare_attribute("programs",  type="string[]")  # multivalued

declare_attribute is idempotent on identical shape — safe to re-run during demo setup. Shape change on a declared-state attribute returns 400 shape_change_on_declared; deprecate + withdraw first to retire the old shape. See kz.cluster.list_attributes() to inspect the current vocabulary, and kz.cluster.deprecate_attribute(name) / kz.cluster.withdraw_attribute(name, force=True) for retirement.

For PII-grade attributes the gate consumes via the mesh-envelope user_attrs channel (not as a JWT claim), pass sensitive=True:

kz.cluster.declare_attribute("ssn_last4", type="string", sensitive=True)

For attributes attested by a peer cluster's brokered-user provisioning (rather than set by local admin), pass authority="mesh_peer" — local admin attempts to set these on local users return 400 wrong_authority_for_subject. Defaults (sensitive=False, authority="local_admin") match the demo flow's normal case.

Step 2b — Seed personas. The single PUT writes attributes in one round-trip, infers multivalued KC entries for list-shaped values, and rolls back attribute deltas on partial failure (T3.4).

cdr_baker = kz.subjects.upsert(
    "cdr-baker",
    attributes={
        "clearance": "TS",
        "country": "USA",
        "programs": ["IRIS", "ARGOS"],   # list → multivalued KC attribute
    },
    password="cdr-baker",
)
print(cdr_baker.id, cdr_baker.attributes["clearance"])  # kc-uuid TS

Audit emits subject_upsert{outcome=success} on the receiver. A partial-failure rollback emits subject_upsert_rollback{outcome=...} so operators can spot drift cases in logs (T3.7). Attempting upsert with an undeclared attribute name returns 400 attribute_not_registered with the undeclared names enumerated and remediation text pointing back at declare_attribute(...).

Step 3 — Bind the cluster execution gate (M3)

Replaces the kubectl exec ... RuntimeConfig().set_config(...) recipe (see authoring-a-federated-demo.md §9.1). The PUT validates the classpath is an ExecutionGate subclass and validates config against the gate's config_schema() before persisting (T2.6 jsonschema).

binding = kz.cluster.set_execution_gate(
    type="kamiwaza.services.authz.gates.default_gates.AllowAllExecutionGate",
    # config={} omitted — AllowAllExecutionGate declares no config_schema()
)
print(binding.gate_name, binding.kind)  # allow_all_execution_gate execution

Without an active binding, mesh job submission fails with 403 no_execution_gate_configured_for_mesh. The SDK surfaces wrong-kind attempts (binding an AttributeGate as an execution gate) as KamiwazaError with status 400.

Step 4 — Register the dataset (M3)

conjunctions = kz.datasets.create(
    name="conjunctions",
    platform="postgres",
    environment="PROD",
    properties={
        "connection_secret_urn": "urn:li:secret:postgres-conjunctions",
        "table": "public.conjunctions",
    },
)
print(conjunctions.urn)  # urn:li:dataset:(postgres,conjunctions,PROD)

Step 5 — Bind the dataset's attribute gate (M3)

ds_binding = kz.datasets.set_gate(
    conjunctions.urn,
    type="kamiwaza_extensions.classified_conjunction_gate.ClassifiedConjunctionGate",
    config={
        "classification_field": "classification",
        "releasable_to_field": "releasable_to",
        "program_compartment_field": "program_compartment",
    },
)
print(ds_binding.dataset_urn, ds_binding.gate_name)

The server verifies the classpath is an AttributeGate (wrong-kind → 400) and that config matches the gate's config_schema() (mismatch → 400 schema_validation_failed). Owner-on-dataset ReBAC enforces that only the dataset's owner can rebind the gate (T2.5 follow-up).

Step 6 — Allowlist the brokered user + grant viewer (M3)

# Receiver-side allowlist (same as WS-M1):
kz.federations["ORION"].users.add(
    external_id="cdr-baker@lyra-cluster-uuid",
    initial_tuples=[
        {
            "subject": "user:cdr-baker@lyra-cluster-uuid",
            "relation": "viewer",
            "object": "cluster:ORION",
        },
    ],
)

# Then attach a ReBAC viewer relation on the dataset (M3 subjects.grants):
kz.subjects.grants("cdr-baker").create(
    object_namespace="dataset",
    object_id=conjunctions.urn,
    relation="viewer",
)

If the user isn't on the allowlist when a mesh request arrives, ext-authz returns 403 with detail.reason == "brokered_user_not_allowlisted". The SDK surfaces that as kamiwaza.exceptions.BrokeredUserNotAllowlistedError.

Step 7 — Submit the federated job

target_cluster is the federation name (the same name used at pair time). Omit it to run locally on the cluster the SDK is talking to.

result = kz.jobs.run(
    target_cluster="ORION",
    entrypoint="python /workdir/query.py --rows 1000",
)
print(result.status, result.audit_actor)
# SUCCEEDED  cdr-baker@lyra-cluster-uuid

For longer jobs, prefer the async + poll pattern — submit_async returns immediately and wait polls with bounded backoff until the job reaches a terminal state:

job_id = kz.jobs.submit_async(
    target_cluster="ORION",
    entrypoint="python /workdir/long_query.py",
)
result = kz.jobs.wait(job_id, timeout=600)

For a governed receiver job, pass exact typed resources at submission. The server rejects the whole request if any resource or operation is not granted:

from kamiwaza_sdk import DelegatedAccess, DatasetDelegatedAccess

job_id = kz.jobs.submit_async(
    target_cluster="ORION",
    entrypoint="python summarize.py",
    timeout_seconds=36_000,
    delegated_access=DelegatedAccess(
        datasets=(
            DatasetDelegatedAccess(
                urn=DATASET_URN,
                operations=("discover", "read", "retrieve"),
            ),
        ),
    ),
)

Inside that managed job, use only the private credential-agent socket. The runtime client never reads an API key, user token, refresh token, or public base URL; capability renewal remains inside the agent:

from kamiwaza_sdk import JobRuntimeClient

with JobRuntimeClient.from_environment() as receiver:
    granted = receiver.datasets.list_granted()
    rows = receiver.retrieval.collect(dataset_urn=DATASET_URN)
    answer = receiver.models.chat(
        deployment_id=DEPLOYMENT_ID,
        messages=[{"role": "user", "content": summarize(rows)}],
    )

receiver.retrieval.stream(...) and receiver.models.stream_chat(...) expose streaming iterators. A sidecar restart is picked up on the next operation by re-reading and kernel-verifying the platform-owned agent identity file.

wait raises kamiwaza.exceptions.MeshJobTimeoutError when the budget expires before a terminal state. A failed job returns a JobResult with status="FAILED" and an error message — that's not exceptional, that's data.

Step 8 — Observe audit

The receiver-side audit log shows the job completing as the originating user (cdr-baker@lyra-cluster-uuid), not as a system principal. M3 adds two more event types operators can grep for:

  • gate_binding{action: set|clear, kind: execution|attribute} — every PUT/DELETE on the cluster + dataset gate endpoints (T2.12).
  • subject_upsert{,_rollback} and subject_grant_change — every AuthzSubjects mutation (T3.7).
# Federated job audit trail
kubectl -n kamiwaza logs deployment/core-scheduler \
    | grep federated_job_completed \
    | jq 'select(.audit_actor)'

# M3 gate-binding + subject-management audit
kubectl -n kamiwaza logs deployment/core-scheduler \
    | jq 'select(.event_type | startswith("gate_binding") or
                                  startswith("subject_"))'

The audit_actor field is the same value kz.jobs.run(...).audit_actor returns in step 7 — that round-trip is the demo gate's load-bearing signal.

Recoverable long-jobs

For jobs that may take longer than ~60 seconds, use kz.jobs.run(..., recoverable=True) instead of the default. The default holds the HTTP connection for the full job duration; FastAPI buffers the X-Job-Id response header along with the body and only flushes both on completion. If the connection drops mid-job, the SDK never sees the X-Job-Id and has no handle to recover the result from.

recoverable=True flips the SDK to a submit + poll shape under the covers:

  1. POST /api/cluster/jobs/submit returns the job_id immediately.
  2. The SDK polls /cluster/jobs/{id}/status with exponential backoff until the job reaches a terminal state.
  3. /cluster/jobs/{id}/result fetches the final payload.

Because the job_id is in the SDK's hands from the first response, a mid-job process crash is recoverable on a fresh SDK instance:

# Original process
job_id = kz.jobs.submit_async(
    entrypoint="python query.py",
    target_cluster="ORION",
    timeout_seconds=600,
)
# ... persist (job_id, target_cluster) somewhere (sqlite, etc.) ...
# ... process dies ...

# Fresh process, much later
saved_job_id = load_persisted_job_id()
saved_target_cluster = "ORION"
result = kz.jobs.wait(
    saved_job_id,
    timeout=600,
    target_cluster=saved_target_cluster,
)

The client that submitted the job remembers up to 256 recent remote handles, so wait(job_id, ...) and cancel(job_id) on that same client do not need the selector repeated. A new client has no such in-memory routing state.

Recommended: use recoverable=True for any job with timeout_seconds > 60. The two-call cost (submit + poll) is amortized over the long runtime.

Error handling cheat sheet

The SDK maps server-side error contracts to typed exceptions so customer code can branch on the failure mode. All inherit from kamiwaza.exceptions.KamiwazaError:

Exception Trigger
FederationPairTimeoutError Receiver couldn't see the PSK before the retry budget expired.
BrokeredUserNotAllowlistedError Mesh request from a user not in the receiver's allowlist.
MeshJobTimeoutError kz.jobs.wait(...) budget expired before terminal state.
MeshJobFailedError Job reached FAILED state and the caller asked for an exception.
NativeRealmRequiredError Operation requires a native (non-brokered) realm user.
KamiwazaError 403 ...read-only... Write aimed at the Global Workroom (shared read-only catalog) — by design; write to a workroom you own instead. See Context Service.
KamiwazaError (catch-all) Other 4xx/5xx; check .status_code and .body for details.
from kamiwaza import KamiwazaError
from kamiwaza.exceptions import FederationPairTimeoutError

try:
    kz.federations.pair(name="ORION", role="initiator", remote_url=...)
except FederationPairTimeoutError as exc:
    # Retriable — DataHub propagation didn't make the deadline this run.
    print(f"Retry later: {exc.body!r}")
except KamiwazaError as exc:
    # Catch-all for everything else.
    print(f"{exc.status_code}: {exc}")

Examples

The /examples directory contains Jupyter notebooks demonstrating various use cases. To run them locally against a Kamiwaza dev cluster, install JupyterLab in your env (pip install jupyterlab ipywidgets) and run jupyter lab from examples/. Set KAMIWAZA_BASE_URL and KAMIWAZA_API_KEY in the environment before launching so the notebooks can reach your cluster.

  1. Model Download and Deployment - A comprehensive guide to searching, downloading, deploying, and using models with the Kamiwaza SDK
  2. Quick Model Deployment - Streamlined approach to download and deploy models using a single function
  3. Model Evaluation - How to evaluate and benchmark multiple language models for performance comparison using the streamlined download_and_deploy_model function
  4. Structured Output - Using Kamiwaza's OpenAI-compatible interface to generate structured outputs with specific JSON schemas
  5. Function Calling - Demonstrates how to use function calling (tools) with Kamiwaza's OpenAI-compatible API
  6. Web Agent - Build an AI agent that can browse and interact with web pages
  7. RAG Demo - Retrieval Augmented Generation using Kamiwaza's vector database and embedding services
  8. App Garden and Tool Shed - Deploy containerized applications and MCP Tool servers
  9. Reference Chatbot App - A buildable Kamiwaza extension app that mirrors the default kz-ext create --type app starter

More examples coming soon!

Service Overview

Service Description Documentation
client.models Model management Models Service
client.serving Model deployment Serving Service
client.vectordb Vector database VectorDB Service
client.context Workroom-scoped vector DBs, ontologies, ingestion, retrieval Context Service
client.catalog Data management Catalog Service
client.embedding Text processing Embedding Service
client.retrieval Search Retrieval Service
client.cluster Infrastructure Cluster Service
client.lab Lab environments Lab Service
client.auth Security Auth Service
client.authz Authorization tuples/checks AuthZ Service
client.activity Monitoring Activity Service
client.openai OpenAI API compatible OpenAI Service
client.apps App deployment App Service
client.tools Tool servers (MCP) Tool Service
client.skills Skills Library catalog and package workflows Skills Service
client.ingestion Data ingestion Ingestion Service
client.enclaves Connectors + documents Enclaves Service

Auth / User Management (0.9.0)

  • Base URL rule: set base_url=https://<host> (no /auth suffix). Quick preflight: GET {base_url}/auth/ping → 200. If you include /auth, calls will double-prefix and fail.
  • Admin-only: creating/resetting users requires an admin bearer.
  • Auth-on semantics: create_local_user provisions Keycloak so the user can authenticate; reset_user_password updates Keycloak only (Keycloak is authoritative). Auth-off updates the local hash only.
  • Roles caveat: requested realm roles must exist; otherwise create will 500 + rollback. Omit roles or use known-good roles.
  • Self-signed TLS: set --verify-ssl false (or verify_ssl=False) when needed.
  • A runnable smoke script lives at scripts/fed_user_smoke.py (see script usage inside).

Integration Tests

The tests/integration suite spins up a MinIO fixture via Docker Compose and exercises the ingestion → catalog flow using the SDK. Run it with:

pytest -m integration

Note: Retrieval checks are currently marked xfail because the live deployment returns HTTP 500 while Ray-backed transport is being stabilised.

Extension Developer Tools (kz-ext)

The kz-ext CLI helps extension developers scaffold, validate, build, deploy, and debug Kamiwaza extensions.

Installation

# Install the SDK (includes extension tools)
pip install kamiwaza-sdk

# Optional extras:
pip install kamiwaza-sdk[publish]    # Adds boto3 for kz-ext publish
pip install kamiwaza-sdk[convert]    # Adds anthropic for kz-ext convert (OpenAI is included by default)
pip install kamiwaza-sdk[flight]     # Adds PyArrow for retrieval Flight streams
pip install kamiwaza-sdk[all]        # All three extras

# Verify
kz-ext --version

kz-ext has its own manifest-capability version because it can evolve on a different cadence from the containing kamiwaza-sdk distribution. Version 0.2.0 is the first enforceable capability baseline that guarantees support for kamiwaza.json.services.<service>.healthCheck (ENG-4832). Extension manifests declare their required CLI range with kz_ext_version; incompatible tooling fails before build, publish, or remote deployment.

For the Kamiwaza 1.2 release line, the distribution mapping is:

kamiwaza-sdk distribution bundled kz-ext capability validated platform range
1.1.0 0.2.0 >=1.2.0,<1.3.0

The kamiwaza-v1.2.0 and release/1.2.1 SDK sources use the same extension payload contract, so this single artifact supports both platform releases.

Quick Start

# 1. Authenticate (local dev — uses https://kamiwaza.test/api, skips SSL verify)
kz-ext login --dev
# Or specify a URL:  kz-ext login https://your-instance.example.com/api
# For self-signed certs:  kz-ext login --no-verify-ssl

# 2. Scaffold a new extension
mkdir my-app && cd my-app
kz-ext create --type app --name my-app

# The generated app is already a working AI starter with:
# - explicit model selection
# - a simple chat UI
# - AGENTS.md and CLAUDE.md for coding assistants

# 3. Validate the extension metadata
kz-ext validate

# 4. Run locally with Docker Compose
kz-ext dev local

# 5. Deploy to a Kamiwaza cluster (build, push, deploy — one command)
kz-ext dev

# 6. Iterate: change code, re-run (zero-downtime update via PATCH)
kz-ext dev

# 7. Inspect the running extension
kz-ext status
kz-ext logs --service backend --follow
kz-ext shell --service backend

# 8. Forward a port for direct debugging
kz-ext port-forward --service backend --port 8000

# 9. Convert an existing app to a Kamiwaza extension
kz-ext convert /path/to/existing-app

# 10. Publish to an extension catalog
kz-ext config publish-profile prod \
  --registry ghcr.io/my-org \
  --catalog-endpoint https://my-account.r2.cloudflarestorage.com \
  --catalog-bucket extensions-prod \
  --catalog-credentials aws-profile:prod

kz-ext publish --stage prod

Commands

Command Description
kz-ext login [url] Authenticate with a Kamiwaza instance (default: https://kamiwaza.test/api). Supports --api-key, --name, --list, --use, --no-verify-ssl.
kz-ext create --type <type> --name <name> Scaffold a new extension in the current (empty) directory. Types: app (Next.js + FastAPI), tool (FastMCP), service (minimal).
kz-ext validate [path] Validate kamiwaza.json, docker-compose.yml, and clear platform-runtime incompatibilities such as privileged ports or root-only web containers. Use --json for machine-readable output.
kz-ext dev local Run the extension locally via Docker Compose with Kamiwaza env vars injected. Auto-detects port conflicts and remaps to available ports. Supports --sdk-repo, --detach, and --auth (bridges the developer's identity from kz-ext login and routes loopback Kamiwaza URLs through the host gateway — see docs/extensions/cli-reference/dev-local.md).
kz-ext dev Build, push, and deploy to a Kamiwaza cluster. Uses zero-downtime PATCH updates for existing extensions. Supports --no-build, --no-push, --service, --revision, --sdk-repo.
kz-ext status Show deployment status: phase, per-service readiness, URL, and recent K8s events. Supports --name.
kz-ext logs Stream logs from deployed extension pods. Supports --service, --follow, --tail, --name.
kz-ext shell Open an interactive shell in a running extension container. Supports --service, --name.
kz-ext port-forward Forward a port from a deployed pod to localhost for debugging. Supports --service, --port, --name.
kz-ext convert <path> AI-powered conversion of existing apps to Kamiwaza extensions. Analyzes code, generates kamiwaza.json, and wires in SDK integration. Supports --dry-run.
kz-ext publish --stage <profile> Build production images, push to registry, and publish to an S3-compatible extension catalog. Supports --dry-run, --force, --no-build, --no-push.
kz-ext bump Bump extension version in kamiwaza.json. Defaults to patch. Supports --level major|minor|patch.
kz-ext config publish-profile Create, list, show, or delete named publish profiles. Supports --list, --show, --delete, --repo-level.
kz-ext doctor Check your development environment (Python, Docker, Compose, kubectl, connection health, runtime libs).

Development Workflow

The typical edit-deploy-test cycle:

  1. kz-ext dev builds Docker images with a unique dev tag, pushes to the cluster registry, and deploys via the platform API.
  2. On the first run, it creates a new extension (POST). On subsequent runs, it patches the existing deployment with new image tags (PATCH), triggering a Kubernetes rolling update with zero downtime.
  3. kz-ext status shows whether the rollout is complete, per-service readiness, and any issues (image pull failures, OOM kills, probe failures).
  4. kz-ext logs and kz-ext shell give direct access to running pods for debugging.

No version bumps, registry builds, or manual redeploy steps required during development.

Publishing

When your extension is ready for release:

  1. Configure a publish profile with kz-ext config publish-profile — specify a container registry and S3-compatible catalog endpoint.
  2. Bump the version with kz-ext bump (or kz-ext bump --level minor).
  3. kz-ext publish --stage prod builds production-tagged images, pushes to the profile's registry, and publishes to the catalog.
  4. kz-ext publish --stage prod --dry-run previews what would happen without making changes.

Publish profiles support multiple environments (dev/staging/prod) and CI via env var overrides (KZ_PUBLISH_REGISTRY, KZ_PUBLISH_CATALOG_ENDPOINT, etc.).

Converting Existing Apps

kz-ext convert /path/to/existing-app

Uses an AI agent to analyze existing Dockerfiles, compose files, and size-capped source context, then generates kamiwaza.json and wires in SDK integration (health endpoints, auth middleware, runtime libraries). Common secret-bearing files such as .env, credential JSON files, and private key files are excluded from that context. The conversion flow now validates generated output against the Kamiwaza runtime contract as well, including non-root execution, unprivileged HTTP ports, and read-only-root-filesystem-friendly web wrappers. All changes are git-tracked — review with git diff.

Optionally uses OPENAI_API_KEY (or ANTHROPIC_API_KEY) for AI-powered conversion. Falls back to basic kamiwaza.json generation without an API key. Set OPENAI_BASE_URL to use any OpenAI-compatible provider (Kamiwaza, vLLM, Ollama, etc.). Set KZ_PUBLISH_DOCKER_TOKEN or DOCKER_TOKEN for registry auth during publish.

Extension Types

  • App (--type app): Full-stack extension with Next.js frontend and FastAPI backend, pre-wired with @kamiwaza-ai/extensions-lib and kamiwaza-extensions-lib.
  • The app starter includes a working authenticated chat flow so developers can customize a real extension instead of starting from a status dashboard.
  • Tool (--type tool): MCP tool server using FastMCP with kamiwaza-extensions-lib.
  • Service (--type service): Minimal containerized service.

Local SDK Development (--sdk-repo)

When iterating on the runtime libraries themselves (kamiwaza-extensions-lib or @kamiwaza-ai/extensions-lib), use --sdk-repo to override the published packages with your local SDK source:

# Via CLI flag
kz-ext dev local --sdk-repo ~/repos/kamiwaza-sdk

# Or via repo-local config (gitignored)
mkdir -p .kz-ext
cat > .kz-ext/local.yaml << 'EOF'
sdk_repo: /Users/you/repos/kamiwaza-sdk
runtime_libs:
  python: local       # override Python lib (default: local when sdk_repo is set)
  typescript: local   # override TypeScript lib
build_typescript: true  # auto-build TS package if dist/ is missing or stale
EOF

kz-ext dev local   # reads .kz-ext/local.yaml automatically

How it works:

  • kz-ext dev local --sdk-repo: Mounts the SDK repo into containers at runtime and overrides the published packages with local source (copies Python lib files over installed package, npm pack + install for TypeScript).
  • kz-ext dev --sdk-repo: Bakes the local runtime libraries into Docker images at build time using BuildKit additional build contexts. The resulting images contain your local lib code and are pushed to the cluster normally.
  • kz-ext doctor: Validates the SDK override configuration — checks that the SDK repo exists, Python and TypeScript libs are present, and dist/ is built.

The override is ephemeral — it never modifies your extension repo's docker-compose.yml or Dockerfiles.

Port Auto-Detection

kz-ext dev local automatically detects occupied ports and remaps to the next available:

$ kz-ext dev local
Port 3000 in use — remapping frontend to 3001
Port 8000 in use — remapping backend to 8001
frontend: http://localhost:3001
backend:  http://localhost:8001

This lets you run multiple extensions simultaneously without port conflicts.

Multi-Connection Support

# Add named connections
kz-ext login https://prod.example.com/api --name prod
kz-ext login https://staging.example.com/api --name staging

# List connections
kz-ext login --list

# Switch active connection
kz-ext login --use staging

The Kamiwaza SDK is actively being developed with new features, examples, and documentation being added regularly. Stay tuned for updates including additional example notebooks, enhanced documentation, and expanded functionality across all services.

Metadata

Release files for kamiwaza-sdk 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kamiwaza-sdk 1.1.0
File Size Uploaded
kamiwaza_sdk-1.1.0.tar.gz 508.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kamiwaza-sdk 1.1.0
File Interpreter ABI Platform
kamiwaza_sdk-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / kamiwaza_sdk-1.1.0.tar.gz

Download URL kamiwaza_sdk-1.1.0.tar.gz
Size 508.9 kB
Tags Source
SHA-256 checksum
How to use checksums
07d7f1caea348bdeeeffa5c68d09822d04e67432f8347f181fe19d1de60642fa
BLAKE2b-256 checksum
How to use checksums
24fec6bc967536abeeea60ac71962e076779d06349c5aef3abe81e5f6fdc7419
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / kamiwaza_sdk-1.1.0-py3-none-any.whl

Download URL kamiwaza_sdk-1.1.0-py3-none-any.whl
Size 576.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
49bc45def48de66fc39fcb782e5b859d6e236c5360b88265522e6209139f1fcd
BLAKE2b-256 checksum
How to use checksums
d684c97d99c2e2a6dbfc828969640e3d97737bdf643e7023964319a7ac9de678
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.0

2 release files

0.9.3

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page