Witbitz docs HomeTrustAll docs

The SDK — build an app on Witbitz

The SDK is one ES module a static page imports. With it your page creates and opens Spaces, sends and reads messages, runs the room's assistant, keeps your app's data in the room, signs people in and checks where a room runs — while the room key, the sealing and the polling stay inside it. Your server, if you have one, uses a second module, WitbitzAdmin, for your tenant's own settings.

Why your users can trust what you build with it: the overview and the trust model.

Status: public beta. Usable today from any static page. The core — create a room, open it, send, listen — is small and meant to stay stable; around it the surface has grown with the platform (lanes, the store, sign-in, connections, voice, certificates), and any change that can break your code is listed under Changes. It wraps the exact reference client the production Spaces app runs on — nothing is forked or reimplemented.

The whole thing

Creating a room needs your tenant id on the page and the page's origin declared once (Do I need a tenant?); opening or posting in a room someone shared needs neither.

html
<script type="module">
  import { Witbitz } from 'https://witbitz-spaces.pages.dev/sdk/3.10.0/witbitz-sdk.js'

  const wb = new Witbitz({ tenant: 't_…' })   // your tenant id

  // A private, agent-backed room. The link IS the auth — share it to let someone in.
  const space = await wb.createSpace({
    agent: { name: 'Helper', instructions: 'You help a small group plan and decide together.' }
  })

  space.on('message', (m) => console.log(m.from, m.text))   // yours, others', and the agent's — all arrive here
  await space.send('Plan us a weekend in Kyoto')            // the agent answers on its own turn → via on('message')

  console.log('Share this:', space.shareLink)
</script>

That page is a complete multiplayer AI app, private to its members: no backend of your own, no key handling, no database.

Try it

Three example apps run live; each one's source is beside it on the same origin.

Example What it shows
A shared assistant room (sdk-example.js, about 40 lines) Create or join a room. Open its share link in a second tab to see the same sealed room as another member.
The Confidential Room An advisor you can tell what you would never paste into an ordinary chatbot, beside a live panel that calls space.sealedProof() and shows the server holds only a sealed envelope, under a key it never receives.
The Ops Desk A private assistant that drafts real actions — refunds, emails — but never runs one itself: each is a card you approve, and only then does it run, on your device, from your handler. privateLane({ actions }), on('proposal') and approve().

The pages

Start with Rooms and messages and The assistant; the rest you need when your app needs it.

Page What it covers
Rooms and messages Create and open a room, read and send messages, replies, reactions, attachments, the room's name, live updates
The assistant Its name, instructions and model, when it answers, a turn you can hold, the assistant as a function, tools, voice
Approvals Proposals from end to end: what is parked, who decides, what runs on approval
The room as a store Your app's rows in the room, schemas, conditional writes
People Sign-in, gated rooms, admins and owners, direct chats, changing members, @usernames
Private and outside agents Each member's private assistant, assistants that ask each other, outside agents over A2A and MCP, AG-UI
Cloud computers A coding agent on the person's own computer in the cloud: make one, open it, its sessions, approvals and files
Embed a Space A room inside your site with one script tag, isolated in its own origin; your page's functions as its tools
Accounts and connections The backup and recovery code, one account on every device, device protection, connections, the Siri inbox
Where the keys live The confidential tier and its proofs, split-key rooms, vault mode
Your server WitbitzAdmin: keys, origins, rooms, customers and billing
Reference Every call, the configuration, the error codes, the limits
HTTP API The /v1 endpoints under the SDK, for when you want the wire
Changes What changed between versions, newest first

Load it

Versions

Load a version in production: https://witbitz-spaces.pages.dev/sdk/<version>/witbitz-sdk.js (and witbitz-admin.js, witbitz-sdk.d.ts, witbitz-admin.d.ts beside it; from 2.2.4 also witbitz-admin.mjs, the admin client in one file for your server). A released version never changes, so our next release reaches your app only when you move the number. Each version's manifest.json lists a sha384 integrity hash for every file it contains, if you want the browser to check them too. The versions so far: /sdk/versions.json.

Path What it is
/sdk/3.10.0/witbitz-sdk.js A release: fixed bytes. Use this in production. (/sdk/3.9.0/, /sdk/3.8.1/, /sdk/3.8.0/, /sdk/3.7.0/, /sdk/3.6.1/, /sdk/3.6.0/, /sdk/3.5.0/, /sdk/3.4.0/, /sdk/3.3.0/, /sdk/3.2.0/, /sdk/3.1.0/, /sdk/3.0.0/, /sdk/2.2.4/, /sdk/2.2.3/, /sdk/2.2.2/, /sdk/2.2.1/, /sdk/2.2.0/, /sdk/2.1.2/, /sdk/2.1.1/, /sdk/2.1.0/, /sdk/2.0.0/, /sdk/1.1.0/ and /sdk/1.0.0/ stay as they were.)
/sdk/latest/witbitz-sdk.js Redirects to the newest release. For demos and experiments.
/witbitz-sdk.js The live build of the Spaces app, between releases. Not for production.

Versions follow semver: a change that can break your code comes in a new major version, listed under Changes (3.0.0 retired fork() — members change in place). An older release keeps working at its fixed address until what it depends on is retired, and Changes says when. An npm package is coming.

Your page's CSP

The SDK is a single ES module; importing it from the address above pulls its other files from the same origin. Your page's Content Security Policy must allow:

For Add
The SDK and the Space API script-src and connect-src for the SDK's origin and your endpoint
Live updates and one account on every device connect-src wss://code-relay.witbitz.chat
Voice input connect-src wss://inference.tinfoil.sh
Reading aloud connect-src https://inference.tinfoil.sh and media-src blob:

A link reads <viewer>/space?room=<id>#mk=<key> — viewer is new Witbitz({ viewer }) (default: the reference app), so links open on your page if you set it to your origin and serve /space there. Variants in the fragment: #s=<share> (a shared-key room), #us=<half>&spc=<commit> (a split-key room), plus &enc=1 (confidential) and &gate=email (email-gated). The fragment never reaches a server. openSpace does not read the page's URL for you; to check it:

javascript
function isSpaceLink(href) {
  try {
    const u = new URL(href)
    const frag = new URLSearchParams(u.hash.slice(1).split('?')[0])
    return !!u.searchParams.get('room') && (frag.has('mk') || frag.has('s') || frag.has('us'))
  } catch { return false }
}
if (isSpaceLink(location.href)) space = await wb.openSpace(location.href)

The reference viewer is the fastest way to see a Space; a production app usually draws its own with on('message') and send, as the example does.

Do I need a tenant?

You want to From Needs
Open, read, post in, approve in an existing room any page the link — nothing else
Create a room your own origin new Witbitz({ tenant: 't_…' }) and that origin declared by your tenant (admin.origins.declare, server side). Otherwise the create answers 403 tenant_required.
Create a split-key room your own origin the above, plus appShare (your half's function) or tenant
Builder calls (origins, customers, billing, room deletes) your server new WitbitzAdmin({ tenantKey }) (wsk_…, or a restricted key wrk_…) — never in a page

So "any static page, no backend" holds for everything except creating rooms, which needs a tenant id on the page and a one-time origin declaration — no key on the page, still no backend.

Get a tenant (free; the secret key is shown once — keep it off your page), then declare the origin your page runs on:

shell
curl -sX POST https://api.witbitz.chat/v1/tenants/demo -H 'content-type: application/json' -d '{"name":"My app"}'
# → data.tenant.tenant_id (t_…, for the page) and data.keys.secret (wsk_…, for your terminal or server only)

curl -sX PUT https://api.witbitz.chat/v1/tenant/webhooks -H "authorization: Bearer $WSK" \
  -H 'content-type: application/json' -d '{"origins":["https://app.example.com"]}'

A demo tenant expires unless you upgrade it, keeping the same id and keys (Keeping it). The origin rules: Your page origins.

Machine-readable source: sdk.md · Generated 2026-10-27T07:05:42Z · build f301388c · every doc in one fetch: llms-full.txt (HTML)