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

# Environments and sandbox providers

> List, create, update and delete workspace Environments, and list sandbox providers and presets, with the TypeScript SDK.

<Note>
  **Early access.** Cloud sessions and managed agent runs are not open to every account yet: we are
  letting accounts in gradually while we test. They run in a cloud sandbox operated by Mutagent, so
  there is nothing to host. A sandbox with nothing to do for 15 minutes stops; send the session a
  message and it wakes up, delivers your message and carries on in the same conversation.
</Note>

An Environment holds the variables and secrets your cloud sessions' tools need, such as a GitHub token
or a database URL. The TypeScript SDK lists, describes, creates, updates, replaces and deletes
Environments, and lists the sandbox providers and presets a Helix Cloud launch can name.

An Environment has variables and secrets only. It has no tools: tools come with the agent, see
[Tools and skills](/platform/managed-agents/tools-and-skills). Model keys do not go in an Environment;
they come from your [LLM providers](/sdk/typescript/providers).

Environment calls are on `client.environments`. The token exchange, sandbox provider and preset calls
are on `client.sandbox`.

## Get a sandbox token

Environment and sandbox provider calls take a short-lived sandbox token, not your API key. Exchange
the API key for a token with `createSandboxToken`, which takes the API key as its first argument and
the workspace as its second. Then create a client that holds both.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;

const platform = new Mutagent({ serverURL });
const { token, expiresIn } = await platform.sandbox.createSandboxToken(
  { apiKey },
  { workspaceId: '<workspace-id>' },
);

const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });
console.log(`token valid for ${expiresIn} seconds`);
```

| Response field | What it is |
| - | - |
| `token` | The sandbox token. The SDK sends it for every call that needs it. |
| `expiresIn` | Seconds until the token expires. Exchange the API key again after that. Do not store the token. |

`workspaceId` is the workspace's ID; `client.workspaces.listWorkspaces()` returns it as
`workspaces[].id`. The API key must be allowed to create resources in that workspace, and a key limited
to one workspace or organization can only get a token inside it. Refusals: 401, 403, 422, 429.

## List Environments

`listEnvironments` returns every Environment in the workspace.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const { environments } = await client.environments.listEnvironments();
for (const environment of environments) {
  console.log(environment.name, environment.vars.length, environment.secrets.length);
}
```

Each Environment has this shape. No call returns a stored value.

| Field | What it is |
| - | - |
| `name` | The Environment name, such as `ci` or `prod`. |
| `vars` | The variables, as `{ name, fingerprint }`. |
| `secrets` | The secrets, as `{ name, fingerprint }`. Secrets are stored encrypted. |
| `createdAt`, `updatedAt` | ISO timestamps, or `null`. |

A fingerprint is the first 8 hex characters of the SHA-256 of the value. Compare fingerprints to check
that a stored value is the one you hold.

## Describe one Environment

`getEnvironment` returns one Environment in the same shape.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const ci = await client.environments.getEnvironment({ name: 'ci' });
console.log(ci.vars.map((entry) => `${entry.name} ${entry.fingerprint}`));
```

404 when the workspace has no Environment with that name.

## Create an Environment or set entries

`updateEnvironment` creates the Environment when it does not exist, and otherwise
changes only the entries you name. A string value sets an entry. `null` removes it. Entries you do not
name are kept.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const ci = await client.environments.updateEnvironment({
  name: 'ci',
  body: {
    vars: { DATABASE_URL: '<database-url>', OLD_FLAG: null },
    secrets: { GITHUB_TOKEN: '<github-token>' },
  },
});
console.log(ci.name, ci.updatedAt);
```

It returns the Environment as `getEnvironment` does.

## Replace an Environment

`replaceEnvironment` sets the whole Environment. Entries the body does not name are
deleted, secrets included.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const prod = await client.environments.replaceEnvironment({
  name: 'prod',
  body: {
    vars: { DATABASE_URL: '<database-url>' },
    secrets: { GITHUB_TOKEN: '<github-token>' },
  },
});
console.log(prod.vars.length, prod.secrets.length);
```

### Rules for both calls

| Rule | Refusal |
| - | - |
| The Environment name matches `^[A-Za-z0-9._-]{1,64}$`. | 422 |
| A variable or secret name matches `^[A-Z_][A-Z0-9_]*$`. A value is a string, or `null` to remove the entry when you set entries. | 422 |
| One Environment holds at most 64 KiB. | 422 |
| A variable named like an LLM provider key, such as `ANTHROPIC_API_KEY`, is refused unless you pass `allowProviderKey: QueryFlag.One`, the value `'1'`. `QueryFlag` is exported by `@mutagent/sdk/models`. With it, the value replaces the workspace key for runs that load this Environment. | 409 |

## Delete an Environment

`deleteEnvironment` deletes the Environment and its secrets.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const result = await client.environments.deleteEnvironment({ name: 'ci' });
console.log(result.deleted, result.name);
```

It returns `{ deleted: true, name }`. 404 when there is no Environment with that name, including a
delete you retry. Sessions already running keep the values they started with. A later launch that
names the deleted Environment is refused with 404.

## List sandbox providers

`listSandboxProviders` lists the sandbox providers a launch can name, and the default.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const { names, default: defaultName } = await client.sandbox.listSandboxProviders();
console.log(names, defaultName);
```

| Response field | What it is |
| - | - |
| `names` | The sandbox provider names. |
| `default` | The sandbox provider a launch uses when it names none, or `null`. |

Pass a name as `sandboxProvider` when you [launch a session](/sdk/typescript/helix-cloud#launch-a-task).
The SDK has no call that adds or configures a sandbox provider. See
[Sandbox providers](/helix/cloud/sandbox-providers).

## List presets

`listSandboxPresets` lists the presets a launch can name as `preset`, and the default.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

const { presets, default: defaultPreset } = await client.sandbox.listSandboxPresets();
for (const preset of presets) {
  console.log(preset.name, preset.arch, preset.provider, preset.environment);
}
console.log(defaultPreset);
```

| Field | What it is |
| - | - |
| `presets[].name` | The preset name. |
| `presets[].description` | What the preset runs. |
| `presets[].arch` | The CPU architecture. |
| `presets[].provider` | The sandbox provider the preset runs on, when it names one. |
| `presets[].environment` | The Environment the preset loads, when it names one. |
| `default` | The preset a launch uses when it names none, or `null`. |

## Errors

A refused call throws a subclass of `MutagentError`. `statusCode` is the HTTP status and `body` is the
JSON the server returned, with `error` and `message`.

```typescript theme={null}
import { Mutagent } from '@mutagent/sdk';
import { MutagentError } from '@mutagent/sdk/models/errors';

const serverURL = 'https://api.mutagent.io';
const apiKey = process.env.MUTAGENT_API_KEY!;
const { token } = await new Mutagent({ serverURL })
  .sandbox.createSandboxToken({ apiKey }, { workspaceId: '<workspace-id>' });
const client = new Mutagent({ serverURL, security: { apiKey, bearerAuth: token } });

try {
  await client.environments.getEnvironment({ name: 'missing' });
} catch (err) {
  if (err instanceof MutagentError) {
    console.log(err.statusCode, JSON.parse(err.body).message);
  } else {
    throw err;
  }
}
```

The same Environments from the command line: [mutagent env](/cli/commands/env).


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