Quickstart — open a Space and call the runtime
This quickstart gets you through the live path without pretending there is a finished public SDK. Today, the working
browser client is the thin client used by the Spaces app (spaces/public/spaceClient.js), and the lower-level HTTP
surface is a single /space op-dispatched endpoint.
Use this page to understand the flow. For production integration access to the tenant-keyed /v1 API, see
Platform API.
1. Open the reference app
The fastest way to see the runtime is the hosted Spaces app:
https://witbitz-spaces.pages.dev
Create a Space, post a message, and watch the AI answer. That exercises the same primitives your own app would use:
- a Space record with a room key commitment
- a sealed config
- a sealed conversation ledger
- an agent turn
- shared widget/artifact state when tools are used
2. Discover the Space endpoint
The app discovers its runtime endpoint from a public config file:
curl -s https://witbitz-spaces.pages.dev/space-config | python3 -m json.tool
# {
# "spaceEndpoint": "https://api.witbitz.chat/v1/space"
# }
The response includes the spaceEndpoint the client posts to. In hosted production that endpoint fronts the /space
Lambda. In an on-prem deployment it is usually same-origin, commonly /v1/space or /space.
3. Check the running service
The attest op reports the source/build identity the running render was built from:
SPACE=$(curl -s https://witbitz-spaces.pages.dev/space-config \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["spaceEndpoint"])')
curl -sX POST "$SPACE" \
-H 'content-type: application/json' \
-d '{"op":"attest"}' \
| python3 -m json.tool
# {
# "service": "witbitz-space",
# "gitCommit": "...",
# "runtime": "aws-lambda",
# "note": "..."
# }
That does not create a room and does not require a key. It is the first sanity check that you are talking to the runtime described in these docs. The stronger build checks are in Verify it yourself.
4. Create a Space from a static app
The working client flow is:
- The browser mints a room key
mk. - The browser computes
commit(mk). - The browser registers only the room, commitment, and sealed config with
op:'create'. - The share link carries the room in the URL query and the key material in the fragment.
The server never receives mk at create time.
In the current codebase, this is wrapped by makeSpaceClient().create():
import { makeSpaceClient } from './spaceClient.js'
const client = makeSpaceClient({ endpoint: '/space' })
const space = await client.create({
keyModel: '1-of-1',
agentName: 'Witbitz',
persona: 'A concise collaborative assistant.',
tools: []
}, {
base: location.origin
})
console.log(space.room)
console.log(space.links[0])
For a hosted third-party app, treat this as the reference client pattern rather than a package contract. The formal developer SDK should wrap this shape.
5. Post a turn
Once a client has opened a member link and reconstructed mk, a turn posts the member message and the room key for
the decrypt-once render:
const { room, mk } = await client.open(space.links[0])
const reply = await client.turn(room, mk, {
from: 'Ada',
text: 'Plan a simple two-day trip to Paris.'
})
The render opens the sealed ledger, appends the member entry, runs the agent, appends the reply, re-seals the ledger, and drops the key.
6. Poll for changes
The preferred read path is pollSealed: the server returns the sealed ledger and the client opens it locally. For
gated rooms, the request also carries identity so the server can enforce the read gate before returning anything.
let etag = ''
let count = 0
const r = await client.pollSealed(room, mk, etag, count)
if (r.changed) {
etag = r.etag
count = r.version
console.log(r.entries)
}
The legacy poll path still exists and returns plaintext from the render. Use pollSealed for the hot read loop.
Next
Machine-readable source: quickstart.md · every doc in one fetch: llms-full.txt (HTML) · ← platform · create-space →