-
Notifications
You must be signed in to change notification settings - Fork 18
Workshop Operator Guide
This page is for the person who runs a Kai install: choosing which client surfaces to enable, giving people access to the Workshop, deciding how far to expose it on the network, and operating it day to day with the CLI and diagnostics. For what users see once they are in, start with Workshop Collaboration Basics.
KAI_ENABLED_ADAPTERS decides which client surfaces the install serves. The configuration wizard asks under "-- Client mode --" and writes the value for you; re-running make config is the supported way to change modes later.
| Wizard choice | KAI_ENABLED_ADAPTERS | Effect |
|---|---|---|
| hybrid (default) | telegram,workshop |
Both surfaces |
| workshop-only | workshop |
No Telegram application and no bot token; the wizard skips the token prompt |
| telegram-only | telegram |
No Workshop client routes |
An absent variable means both adapters, so an install upgraded from an older release keeps working without edits. An empty value or an unknown adapter name is a hard startup error. The HTTP server starts in every mode; the mode only gates which client surfaces it serves.
A fresh workshop-only install provisions its first admin automatically: the wizard creates one canonical human, the Kai agent, their direct channel, and a protected runtime profile, then prints the first enrollment token once. Copy it before the screen scrolls away.
Workshop humans are canonical records in the database, not entries in users.yaml (that file is Telegram-only now). The full lifecycle runs through the CLI:
-
Provision.
provision-humancreates the person and their direct channel, with a role (adminormember) and optionally a handle. A freshly provisioned human has no transport access and no runtime. -
Assign a runtime.
assign-runtimebinds a protected runtime profile to the human's direct-channel agent. Without this step they can enroll but their agent cannot run. -
Issue an enrollment token.
issue-enrollmenttakes--principal-idor--telegram-user-id(exactly one) and prints a short-lived token. Defaults: 10 minutes to redeem, 1 hour maximum. The server stores only a hash. - The person enrolls. They open the Workshop URL, name their device, and redeem the token for a session credential: 30 days by default, 90 maximum, also stored hashed.
-
Revoke when needed.
revoke-device --device-idends a device and all of its sessions;revoke-enrollment --grant-idcancels an unredeemed token.
Enrollment and redemption are rate limited, and both listeners share the same limiters, so the LAN listener gives an attacker no separate budget.
Enabling Telegram later for a Workshop-provisioned person links the Telegram identity to the same canonical human; they keep their channels and history.
The default posture is loopback only: the Workshop lives at http://127.0.0.1:8080/workshop/ and nothing else can reach it.
WORKSHOP_LAN_HOST opens a second listener for one private, non-loopback IPv4 address on the same port as the loopback listener (WEBHOOK_PORT, default 8080). Validation is strict: loopback, public, multicast, and IPv6 addresses are all rejected, and setting the variable while Workshop is disabled is a startup error. The LAN listener registers only the client API routes; webhook ingress, internal APIs, and Telegram stay loopback-only.
Both listeners speak plain HTTP. The wizard warns: "Workshop bearer sessions will use plain HTTP on this trusted LAN address. Use a TLS terminator for untrusted networks." Take that seriously; a bearer token on an untrusted network is a stolen session. Front the LAN listener with a TLS-terminating proxy for anything beyond a trusted home or office network.
The server caps long-lived event streams at 12 per person and 96 per process; beyond that it answers 429 with a Retry-After header. The caps mostly matter when one person leaves many tabs open.
Every command runs as python -m kai workshop <command>, and must run as the OS account that owns $KAI_DATA_DIR/kai.db.
| Subcommand | Purpose |
|---|---|
list-humans |
List canonical humans and their direct channels |
provision-human --provisioning-key K --display-name N --role admin|member [--handle H] [--workshop-id W] |
Create a canonical human without transport or runtime access |
list-runtime-profiles |
List protected transport-neutral runtime profiles |
assign-runtime --principal-id P --channel-id C --runtime-profile-id R |
Bind a runtime profile to a human's direct-channel agent |
issue-enrollment (--principal-id P | --telegram-user-id T) [--channel-id C] |
Issue one short-lived enrollment token |
revoke-device (--principal-id P | --telegram-user-id T) --device-id D |
Revoke one device and all of its sessions |
revoke-enrollment (--principal-id P | --telegram-user-id T) --grant-id G |
Revoke one unredeemed enrollment grant |
transcript export --channel-id C writes a channel's canonical conversation history as NDJSON to stdout.
status, reconcile, and set --channel-id C inspect and repair where Kai delivers integration notifications (GitHub activity).
status, list, refresh, refresh-all, upsert --model-id M --display-label L --capabilities-json J, and deactivate manage the durable model catalogue behind runtime model pickers. Discovery adapters only fetch metadata; upsert is how you add an operator-curated entry by hand.
make install-status prints the Workshop status functions alongside the rest of the install report: bootstrap state, agent authority, handles, notifications, unread and lifecycle state, delivery authority, runtime sessions, memory authority, canonical message integrity, transcript authority, and legacy residue checks. The report is deliberate about privacy: it prints counts and health, never message text, so it is safe to paste into an issue.
The browser client is a React application in workshop-client/, but operators never need Node to run Kai: the built bundle is committed to the repository and Python serves those committed bytes directly. CI enforces the arrangement with npm run verify-generated, which rebuilds the bundle and fails if the committed output is stale.
Two development lanes exist:
-
make client-checkruns the client typecheck, tests, and the verify-generated comparison; this is the client half of CI. -
make workshop-devstarts a Vite dev server against a running Kai install for live preview. It is foreground-only by design: review, then Ctrl-C. The dev origin is separate from the installed one, so enroll that origin once with its own token.
-
Configuration Wizard -- the full
make configwalkthrough, including client mode. - Multi-User Setup -- multi-user concepts shared by both surfaces.
- Protected Installation -- service accounts and per-agent OS isolation.
- Exposing Kai to the Internet -- tunnel and TLS options in front of the webhook port.