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

# Sessions

> Reference for the Session class

A `Session` holds one or more environments. See [Concepts → The lifecycle](/concepts/overview#the-lifecycle) for how `reset` / login / `evaluate` fit together; this page is the API reference.

## Creating

Provide exactly one of `envs`, `testcase`, or `artifacts`.

```python theme={null}
session = plato.sessions.create(envs=[Env.simulator("espocrm")])
session = plato.sessions.create(envs=[Env.artifact("artifact-abc123")])
session = plato.sessions.create(testcase="tc_abc123")
```

VMs are killed `timeout` seconds after creation (default `1800` = 30 min):

```python theme={null}
session = plato.sessions.create(envs=[...], timeout=3600)
```

`testcase=` auto-resets. `envs=` does not — call `session.reset()` first thing yourself.

To score a run with `evaluate()`, create the session with `testcase=` — it provisions the testcase's envs and links the scoring config in one step. Sessions created from `envs=` or `artifacts=` cannot be evaluated.

## Operations

### `reset()`

Initialize mutation logging on every env. Call this **before** login and the agent run — see [Concepts → Reset](/concepts/overview#the-lifecycle).

```python theme={null}
session.reset()
```

### `get_state()`

Flush pending writes and return mutations per env.

```python theme={null}
state = session.get_state()
for job_id, env_state in state.results.items():
    print(env_state.mutations)
```

### `evaluate(value=None)`

Score the session against its testcase. Only sessions created with `testcase=` can be evaluated — the testcase carries the scoring config. `value` is required for OUTPUT scoring; omit for MUTATION-only.

```python theme={null}
result = session.evaluate()
print(result.correct, result.score)
```

### `get_public_url(port=None)`

Browser-accessible URLs per env, keyed by alias.

```python theme={null}
urls = session.get_public_url()
# {"crm": "https://abc123--80.sims.plato.so", ...}
```

### `login(browser)` / desktop login

For app-sim sessions, pass a Playwright `Browser`. For desktop sessions, use `desktop.sdk.login(session)` instead — `session.login(browser)` raises if `session.desktop_env` is set. Full pattern: [Examples → Full evaluation](/sdk-v2/examples#4-full-evaluation-testcase-login-evaluate).

### `close()`

```python theme={null}
session.close()
plato.close()
```

Idempotent. Wrap session work in `try/finally` so VMs go away on crash.

## Accessing envs

```python theme={null}
for env in session.envs:
    print(env.alias, env.job_id)

crm = session.get_env("crm")           # by alias
desktop = session.desktop_env          # first env where is_desktop=True (or None)
```

## Properties

| Property         | Type                  | Description                              |
| ---------------- | --------------------- | ---------------------------------------- |
| `session_id`     | `str`                 | Unique session identifier                |
| `task_public_id` | `str \| None`         | Test case ID if created from `testcase=` |
| `envs`           | `list[Environment]`   | All envs in the session                  |
| `desktop_env`    | `Environment \| None` | First env where `is_desktop=True`        |
