> ## 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.

# Get Started with Surface Area

> One sitting, end to end - install the CLI, sign in, create a world from a connector, open a session, point an agent at it, grade the run, and read the result in the dashboard.

A [world](/worlds) is a sealed copy of the systems your agent works against. The platform hosts it, serves the vendor's routes, and pins every version, so two runs differ by exactly the thing you changed.

The eight steps below end with a world in your project, a live session your agent called, and a graded number you can compare against tomorrow's agent.

## What you need before the first command

| What | Why | Where it comes from |
| - | - | - |
| Node 18 or newer | The `gateway` command-line tool runs on it | `node --version` |
| A Surface Area project | Worlds, sessions and scores all live inside one project | The dashboard, per [Dashboard basics](./dashboard) |
| A project API key pair | Every command authenticates with it | Project **Settings** → **API keys** |

**Both keys are one credential.** A key pair is a public key (`pk-lf-…`) and a secret key (`sk-lf-…`), and every request sends both: the public key is the username half of HTTP Basic auth and the secret key is the password half — see [REST API overview](/rest-api#authenticate-with-http-basic-auth).

<Info>
  The secret key is displayed once, at creation time. Copy both keys out of the
  dialog before closing it; a lost secret key is replaced, never recovered.
</Info>

## The path, end to end

<Steps>
  <Step title="Install the command-line tool">
    The `@withgateway/sdk` npm package ships the `gateway` command. Install it globally so it is on your path.

    ```bash theme={null}
    npm install -g @withgateway/sdk
    gateway --help
    ```

    A successful install prints the command groups — `auth`, `worlds`, `bench`, `environment` and the rest. [Installation](./installation) covers the Python SDK.
  </Step>

  <Step title="Sign in to your project">
    `gateway auth login` stores the host and the key pair in a credentials file that every later command reads.

    ```bash theme={null}
    gateway auth login \
      --host https://withgateway.ai \
      --public-key pk-lf-... \
      --api-key sk-lf-...

    gateway auth status
    ```

    `gateway auth status` prints the host in effect and whether a key is configured. In continuous integration, set `GATEWAY_HOST`, `GATEWAY_PUBLIC_KEY` and `GATEWAY_SECRET_KEY` instead; the environment wins over the stored file.
  </Step>

  <Step title="Create a world from a shipped connector">
    A connector template is a vendor's data model and routes, already written. `gateway worlds create` cuts a world from one and publishes its first version in a single call.

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

    The command prints one line: the slug, the first version's content hash, and the world's page in the app (`https://<host>/project/<projectId>/world?env=<containerId>`). The first version is `READY`. `worlds schema templates` lists every template the package installs, so swap `slack` for the vendor you care about.

    The world is stored as its **schema tree** — the contract, the handlers, and the connector file that declares the vendor's routes. One session serves both of its surfaces: the world's tools, and its HTTP routes.

    <Info>
      Driving a coding agent instead of a terminal? The same call is the MCP tool
      `create_world`, which takes `slug`, `from`, an optional `overlay` and seed
      `data`. See [MCP Server](/mcp/tools).
    </Info>
  </Step>

  <Step title="Open a session and read where it answers">
    A session is one live, pinned copy of the world. Ask for the `api` surface and the platform serves the vendor's HTTP routes at a URL of their own.

    ```bash theme={null}
    gateway worlds session open acme-slack -t default -s api
    ```

    The descriptor comes back as JSON:

    ```json theme={null}
    {
      "sessionId": "ws_01J...",
      "ready": true,
      "surfaces": ["tools", "api"],
      "api": { "url": "https://...", "token": "..." }
    }
    ```

    `-t` names the task the session opens on, and a world built from a template ships one called `default`. `-s api` asks for the HTTP surface explicitly; a world whose connector declares routes serves them from the same session either way, and a world that declares none refuses the ask with a 400 naming the missing `connector.toml`.
  </Step>

  <Step title="Point your agent at the session">
    The `api.url` is a base URL and the `api.token` is a bearer token. Give your agent those two values where it would otherwise take the vendor's, and change nothing else about it.

    ```bash theme={null}
    export API_URL="https://..."     # api.url from the descriptor
    export API_TOKEN="..."           # api.token from the descriptor

    curl -s "$API_URL/<operation-path>" \
      -H "Authorization: Bearer $API_TOKEN"
    ```

    Send the token in the header, never in the URL. Which paths exist depends on the world's contract: the world's **API** tab lists every route, and `gateway worlds session status <sessionId>` prints the session's tools and surfaces.

    To confirm the world is live without knowing a route, dump its rows:

    ```bash theme={null}
    gateway worlds session state <sessionId>
    ```
  </Step>

  <Step title="Grade the end state">
    The task carries a grader. `grade` runs it against the world as it stands now and prints a reward.

    ```bash theme={null}
    gateway worlds session grade <sessionId>
    ```

    ```json theme={null}
    { "reward": 1.0, "rewards": { "channel_created": 1.0 }, "raw": {} }
    ```

    `reward` is the headline number, `rewards` breaks it down per check, and `raw` holds whatever the grader returned. Assertion and Python graders answer in seconds; a rubric judge is scored by the platform's worker and the command waits for the verdict.
  </Step>

  <Step title="Close the session">
    A session holds a running container, so hand it back when you are done.

    ```bash theme={null}
    gateway worlds session close <sessionId>
    ```

    Sessions close themselves after thirty idle minutes. `gateway worlds session pin <sessionId>` exempts one from the idle reaper while you work on it.
  </Step>

  <Step title="Read the result in the dashboard">
    Open the project and select **Worlds**, then your world. The page carries Overview, Scenarios, Schema, Data, Tests, Results, Evals and History tabs.

    **Overview** lists every live session with its engine, state, task, API URL and age, plus Pin and Stop. **History** lists every version with the change reason recorded on it, which is what makes an old score still readable months later.
  </Step>
</Steps>

## Run every scenario with one command

Point the CLI at an agent module and it opens a session per scenario, runs your agent, and grades each end state.

```javascript filename="agent/run.mjs" theme={null}
export default async function agent(session, task) {
  const url = await session.api();
  const headers = await session.apiHeaders();

  const response = await fetch(`${url}/v1/channels`, {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify({ name: "incident-8817" }),
  });

  if (!response.ok) throw new Error(`world answered ${response.status}`);
}
```

```bash theme={null}
gateway worlds run acme-slack --agent ./agent/run.mjs --all --surface api
```

The module default-exports `async (session, task) => void`. The summary JSON on stdout carries one entry per scenario with its reward, plus the `mean` across all of them.

## The two branches from here

| You want | Recipe |
| - | - |
| Every pull request checked against the world before it merges | [Evals in CI/CD](/use-cases/evals-in-ci) |
| Each of your own users running against a copy of their own data | [Simulations from real data](/use-cases/sims-from-real-data) |

## Where to go next

* Build a world from your own contract and your own data in [Getting started with worlds](/worlds/getting-started).
* Capture the sessions a world is seeded from in [Tracing](/tracing).
* Score production traffic and replay real sessions in [Evaluation & Replay](/evaluation).
* Learn the six words the product is built from in the [Glossary](/glossary).


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