> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surfacearea.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started with worlds

> Build your first world end to end. Authenticate, start from a connector or a contract, put data in, publish a version, open a session, run an agent against it, and iterate.

This page takes an empty directory to a hosted world with data in it, a session your agent
can call, a graded run, and a second version. Every step uses the `gateway` CLI from the
`@withgateway/sdk` npm package; the platform hosts the world. The package bundles the schema
runtime and runs it with any `python3 >= 3.12` it finds (no pip); without one, the platform
runs the same code for you.

For an agent doing the work, `gateway worlds skill worlds-getting-started` prints the same
steps in agent form, and `--install .` puts it in your repository's `.claude/skills/`.

## Before you begin

Install the SDK with the CLI and sign in with a project's keys.

```bash theme={null}
npm install -g @withgateway/sdk
gateway auth login --host https://<your-gateway> --public-key pk-lf-... --api-key sk-lf-...
gateway auth status
```

Or set `GATEWAY_HOST`, `GATEWAY_PUBLIC_KEY` and `GATEWAY_SECRET_KEY` in the environment. The
world lands in the project the keys belong to.

## The one-command path

When the SDK ships a template for your vendor, `gateway worlds create` builds the world on the platform in one call. No directory needed.

```bash theme={null}
gateway worlds schema templates                       # what is installed
gateway worlds create acme-slack --from slack -m "first world"
```

The template is pinned on the world, the platform compiles the tree through the schema runtime, and **the first version is `READY` and already serving the vendor's routes**. Open a session and the world answers — no pull, edit and push step first. `--from workspace:<slug>` does the same from a connector your organization published, and `--from ./some-dir` from a directory.

Use the longer path below to author the contract yourself.

## Choose where to start

| You have | Start from |
| - | - |
| A vendor the SDK ships a template for (run `gateway worlds schema templates`) | `gateway worlds create <slug> --from github`, or `gateway worlds schema init ./x --connector github` to edit it first |
| A connector your organization, or another one, already published | `gateway worlds connector list --hub`, then `--from workspace:<slug>` or `--connector workspace:<slug>` |
| A vendor API and a developer key | `--connector custom` plus a `connector.toml`; see [Mock any vendor API](/worlds/custom-connections) |
| A data model and nothing else | `--connector custom` and author `schema/world.json` |

<Info>
  A world is read and write. A lookup-only mock tests nothing about the decisions your
  agent makes when it creates, updates and polls. Plan the write routes from the start.
</Info>

### What a world is made of

A world is a `gateway-world/1` tree: `schema/world.json`, `gateway-env.toml`, optional
`tools/handlers.py`, and an optional `connector.toml` with `api/handlers.py`. Tools and HTTP
routes are two surfaces of one world, served by one session.

<Steps>
  <Step title="Start the world">
    ```bash theme={null}
    gateway worlds schema init ./vendor-world --connector custom --name vendor-world
    ```

    The directory holds the contract in `schema/world.json` (entities, fields, keys,
    relationships), optional `connector.toml` (the vendor connection and the routes the world
    answers), optional handlers in `tools/handlers.py` and `api/handlers.py`, and
    `scenarios/<name>/` for named starting states.

    The `custom` contract starts with one example entity, `records`. Declare your own with
    `gateway worlds schema entity add`, then remove the example with
    `gateway worlds schema entity remove ./vendor-world records`; `init` prints both as next steps.
  </Step>

  <Step title="Check it">
    ```bash theme={null}
    gateway worlds schema compile ./vendor-world
    gateway worlds schema check ./vendor-world
    gateway worlds connector validate ./vendor-world              # when connector.toml exists
    gateway worlds serve ./vendor-world --port 8080               # answer the routes locally
    ```

    `check` validates the compiled bundle. With a vendor OpenAPI document,
    `gateway worlds connector conform ./vendor-world --openapi vendor.yaml` calls every
    declared route and reports each mismatch.
  </Step>

  <Step title="Put data in">
    ```bash theme={null}
    gateway worlds data show ./vendor-world                       # kind and entity counts
    gateway worlds data import ./vendor-world rows.json           # rows checked against the contract
    ```

    `rows.json` is `{"<entity>": [row, ...]}`. Rows that break the contract are refused with the
    field named, and nothing is written. To load captures from the real vendor instead, run
    `gateway worlds connector capture` then `ingest`. Details on both: [Put data in a
    world](/worlds/data).
  </Step>

  <Step title="Publish a version">
    ```bash theme={null}
    gateway bench push ./vendor-world -m "first cut"
    ```

    Every push is a version, and every run records the version it ran against.

    `gateway bench push` and `gateway worlds create <slug> --from ./vendor-world` both store the
    tree as it is: the World Host serves its routes from `connector.toml` and its tools from the
    same session.

    With `[actions] on_push = ["tests"]` in `gateway-env.toml`, the platform runs the world's own
    test suite on every push. `gateway bench tests <slug>` lists those runs, newest first, and
    `--run <id>` prints one report. See [Test a world](/worlds/tests).

    Publish the template to let others in your organization start worlds from the same contract:

    ```bash theme={null}
    gateway worlds connector publish ./vendor-world --slug vendor -m "first cut"
    ```
  </Step>

  <Step title="Open a session">
    ```bash theme={null}
    gateway worlds session open vendor-world -t default --surface api
    ```

    The command prints the session descriptor: the session id, the surfaces it opened, and, with
    `--surface api`, the hosted `api.url` that answers the vendor's routes plus the `token` to
    send as `Authorization: Bearer <token>` on every request. Point your agent's client at it.

    On a schema world whose tree carries `connector.toml`, the host session serves tools and api
    together whether or not `--surface api` asked for it. On a tree with no `connector.toml` the
    ask is refused with a 400 saying the world declares no HTTP routes.

    To try rows without making a version, seed the session only:
    `gateway worlds session seed <sessionId> rows.json`.
  </Step>

  <Step title="Run and grade">
    One session grades one attempt. To run a whole world, point the CLI at an agent module whose
    default export is `async (session, task) => void`.

    ```bash theme={null}
    # every task in the world's scenario set, one live session each
    gateway worlds run vendor-world --agent ./agent.mjs --all

    # one task
    gateway worlds run vendor-world --agent ./agent.mjs --task vendor-alice-dedupe

    # push the checkout, run every task, exit 1 below the bar — the pull-request gate
    gateway worlds ci ./vendor-world --agent ./agent.mjs --min-score 0.7

    # hosted runner instead of a local agent: one job per model, provider-prefixed
    gateway environment run vendor-world -m openrouter/openai/gpt-5-mini
    ```

    Attach a set of scenarios from a file:

    ```bash theme={null}
    gateway environment link-task-set vendor-world --tasks scenarios.jsonl
    gateway environment performance vendor-world
    ```

    The `environment` namespace is the historical name for a world. The commands operate on the
    world you name.
  </Step>

  <Step title="Test the world itself">
    A world's own tests check that the world answers the way the vendor does. They are separate
    from the runs you grade an agent with, and they live in `<world>/tests/`: `*.json` HTTP cases
    and `test_*.py` files that receive `WORLD_URL` and `WORLD_API_KEY`.

    ```bash theme={null}
    gateway worlds test ./vendor-world              # against the world served here
    gateway worlds test vendor-world                # against the platform's copy
    gateway bench tests vendor-world                # the runs the platform recorded on push
    ```

    `gateway worlds test` exits 1 when any case fails. [Test a world](/worlds/tests) has the case
    format and the push wiring.
  </Step>

  <Step title="Iterate">
    ```bash theme={null}
    gateway worlds session export <sessionId> --out calls.jsonl   # what the agent actually called
    gateway bench pull vendor-world                               # the head version's files
    gateway bench diff <baseVersionId> <headVersionId>
    gateway bench propose ./vendor-world --title "add refunds" -m "why"
    ```

    Turn a real run's calls into rows for the next version, edit, and push again. Old runs keep
    pointing at the version they faced.
  </Step>
</Steps>

## Where it shows up

* **Connectors** in the project sidebar: shipped and workspace connectors, each with
  **Create world** and **Clone**, and **New connector** to start one on the platform: name it, then choose to keep it as a connector, create a world from it, or both. The form also shows the CLI commands that do the same.
* **A connector's page**: Overview (schema and verdict), API (the routes the world serves),
  Worlds (the worlds built from it).
* **A world's page** under **Worlds**: Overview, Scenarios, Schema, Data, Tests, Results,
  Evals and History tabs. History lists every version with its change reason; Schema shows
  the entities and the pin back to the connector; Tests holds the runs of the world's own
  suite, including the ones the platform ran on push.

## Working over MCP instead of a shell

Every step above has a tool on the platform's MCP server: `list_connectors`,
`get_connector`, `validate_connector_template`, `publish_connector`,
`init_world_from_connector`, `env_write_file` and `env_commit` to land files,
`import_world_data`, `seed_world_session`, `export_world_session`, `run_evaluation`,
`create_task_set`, `link_task_set`, `env_diff` and `env_propose`. Call `guide` with topic
`connectors` or `world-data` for the walkthrough. See [MCP Server](/mcp).

## Where to go next

**Running the world you just built.**

* [Spin worlds up and down](/worlds/sessions) for the session lifecycle: open, pin, seed, close.
* [Run many sessions at once](/worlds/parallel) for a whole scenario set in parallel.
* [Test a world](/worlds/tests) for the suite a world ships for itself.
* [Benchmarks on worlds](/worlds/benchmarks) to turn the world's tasks into k graded rollouts per model.
* [Run API worlds in CI](/worlds/ci) for gating a pull request on the score.
* [Simulations for your users](/worlds/for-your-users) for handing a world to the people who use your product.

**Building the next one.**

* [Put data in a world](/worlds/data) for the rows file, modes and live seeding.
* [Keep real data out](/worlds/redaction) for the `[redact]` policy before real records go in.
* [Mock any vendor API](/worlds/custom-connections) for `connector.toml`, capture, handlers and conformance.
* [Build a Slack world](/worlds/slack) for a populated example from the Connectors page.
* [What makes a world good](/worlds/good-world) for the bar to aim at.
* [Author worlds from chat](/worlds/assistant) to let the Assistant do the authoring.
* [The sample repository](/worlds/sample-repo) for a working world to read and copy.

**Elsewhere on the site.**

* [Worlds client](/sdk/environments) to drive sessions from Python.
* [Evaluation & Replay](/evaluation) for how a world's runs are scored.
* [Scenarios & task sets](/evaluation/data-task-sets) for curating the questions a world is asked.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.