Pick the shape that matches what differs per customer
Both shapes can be combined: a world per tenant, and a task per end user inside it.
Start with one world and per-user tasks. Move to a world per tenant only when
customers genuinely need different data or a different contract, because every
world is a version history you then have to keep.
Shape one: a world per tenant
Create one world per customer
gateway worlds create cuts a world from a shipped connector template, from a connector
your organization published, or from a directory holding a tree you authored.
The slug must be URL-safe and unique within the project, so prefix it with the tenant:
acme-crm, globex-crm. The world is stored as its schema tree, and when the connector
declares routes (connector.toml) the same session serves them beside the tools with no
second step.
Provision many tenants in one call
--batch takes a JSONL file (or - for standard input) of one world per line, and prints
one result line for each.
overlay and data (the seed rows, as
{"rows": {"<entity>": [...]}}). The command exits 0 when every world was created, 2 when
any line failed, and 1 on an error before the batch started.
Or call the API directly
POST /api/public/worlds is the same request, for provisioning from your own backend.
slug, containerId, kind, and the first version with its content
hash. A slug already in use answers 409; a tree the contract refuses answers 400 and names the
path that failed.
Load each tenant’s own records
Hash or drop personal fields before loading records from a real customer
system. A world is sealed from the outside, but it is still readable by
everyone in the project that owns it.
Shape two: one world, a task per end user
One published version serves any number of end users at once, each with their own goal, starting rows and grader. Supply the task when the session opens instead of publishing it in the bundle.--task-file, and over HTTP as the task field of
POST /api/public/world-sessions.
Inline and stored tasks run on the World Host engine, which serves worlds stored as trees,
with or without routes.
Tasks bundled in the world
A task can ship in the world instead of the request. Two formats exist, read by different engines:gateway worlds session open <world> -t <name> opens either kind by name. Details: the two bundled task formats.
Keep a task if the same user runs it again
Store a task your users return to in the project rather than in a request body. Stored tasks live outside any bundle, are versioned, and can be filtered by their metadata.worlds task validate checks a task’s seed and grader entities against a world version
without opening a session. worlds task update makes a new version; sessions already open
keep the copy they started with.
The whole loop, per end-user run
1
Open a session for the run
2
Hand your user's agent the URL and the token
The session’s
api.url and api.token are all an agent needs. Point it there instead of at
the real vendor; nothing else in its code changes.3
Grade the end state
4
Close it, and keep the ledger
What gets recorded, and to whom
Worlds and versions created with an API key are attributed to the key: the first version recordsapikey:<id> as its author and the world has no human owner. Everything lands in the
project the key belongs to, so one project is one customer-facing integration.
Runs record the version they faced, so a result stays interpretable after the tenant’s world
moves on. Old versions stay addressable, and --version-id on session open pins a run to
an exact one.
Verify
List what you provisioned.gateway worlds list prints each world’s id, slug and latest
version; --slug narrows it to one.
Check a tenant’s data landed. gateway worlds data show acme-crm prints the world’s kind
and entity counts, and --entity accounts prints that entity’s rows.
Prove the seal between tenants. Open a session on two tenants’ worlds and read the state
of each; neither should contain the other’s records.
Slugs are unique per project, so a tenant name that collides answers 409
rather than overwriting anything. Decide the naming scheme before you
provision the first customer — renaming a world later does not move the runs
that recorded its old identity.
Where to go next
- Spin worlds up and down for the session lifecycle and pinning.
- Run many sessions at once for many end-user runs at the same time.
- Put data in a world for the rows file and live seeding.
- Getting started to author the world the tenants are cut from.