← The Kibitz Engine · deep dive
Kibitz is an account-free, serverless, peer-to-peer call + collaboration engine — an embeddable widget and a headless controller. This is the system overview the other docs slot into.
See also: verification.md (who gets in), agent-platform.md (agents in a room), threat-model.md (what's protected).
A room id (normalized from the link) maps to a deterministic signaling id. The first peer to claim it becomes the authority; later peers join as participants. The authority coordinates presence only — the roster, the lobby/knock gate, lock, kick, and the verification gate. It is just a participant's browser; if it leaves, the role migrates to another peer (heartbeat + reclaim), and the new authority rebuilds its state from what it inherited.
Presence runs as a star to the authority (each participant ↔ authority); content does not (next section).
| Plane | Carries | Topology | Encryption | Helper |
|---|---|---|---|---|
| Signaling / presence | room join, roster, lobby/lock/kick, gate announces | star → authority (PeerJS) | WSS/TLS to the broker | self-hosted broker signal.kibitz.chat |
| Media | audio / video / screen | full WebRTC mesh | DTLS-SRTP, E2E | Cloudflare TURN when direct fails |
| Data | chat, co-browse, directed messages, agent envelopes | full DTLS data mesh | DTLS, E2E | (same peer connections) |
The crucial property: media and data are a peer-to-peer mesh, end-to-end encrypted — no participant (not even the authority) relays content, and there is no media server that could decode or record it. The broker sees only presence metadata; TURN forwards encrypted packets it can't read. (See threat-model.md.)
A TURN relay (Cloudflare Realtime) is used only when two networks can't connect directly; it forwards the still-encrypted call.
mount(opts) boots the engine and returns a controller (MountedWidget):
headless: true) — renders no UI; the host app reads/drives the
call via the controller: getParticipants() / on('participants'|'join'|'leave'|…),
join/leave/toggleMic/shareScreen, broadcast/sendTo/onMessage, host ops
(setLobby/admit/deny/remove/setLocked), and the capability controls
(getCapabilityGrant/setCapabilityGrant/getAgentAudit — see §6).The Widget UI is just one consumer of this controller. The same controller powers the
Whist reference game (headless, draws its own table) and the
Agent SDK. An in-memory transport (createLocalBus) runs the real
presence engine with no network, for deterministic tests.
Two independent, composable layers, both peer-to-peer:
Who may enter a room is the verification gate: the link carries a verifier, the authority checks credentials before rostering.
Once in, what each participant may do is itself scoped — a general per-participant
permission model (humans and agents), not an agent-only bolt-on. Each participant carries a
Grant of what it may perceive (content that flows to it) and act (what it may
emit):
see-screen, hear-audio, read-chat, read-roster, receive-directed.send-chat, speak, act.Defaults are by kind (meta.role): a human is full; an agent is read-only —
read-chat/read-roster/receive-directed, no act, no media. The host can widen or revoke
any grant live, with a per-agent consent panel + a local-only audit feed (blocked acts +
grant changes). The model is pure and serializable (core/capabilities.ts).
The engine enforces it per-peer (not the app — there's no server to police it):
broadcastContent), and a withheld media lane is swapped for a flowing placeholder on
just that peer's connection (mesh.ts gatedTrack/setMediaGate) — so a read-only agent
receives no audio and no screen share, not even one frame.send-chat, so a tampered client still can't post.caps control
message, accepted only from the host id) so every peer enforces the same policy — uniform
even in 3+-human rooms, and re-synced to new joiners + across host migration.Disclosure: an agent may declare its model backend and whether what it perceives
**egress**es the E2EE room — shown to the host, never a privilege it grants itself. See
agent-platform.md.
All stateless and content-blind, on Cloudflare:
signal.kibitz.chat) — a PeerJS-compatible broker; sees presence
metadata, not content.The project is operated pseudonymously; nothing requires an account or holds call content.
<script src=".../widget.js"> or Kibitz.mount({ room }).mount({ room, headless: true }) → the controller.verifyIdentity, joinGate).