@mutagent/sdk
███╗ ███╗██╗ ██╗████████╗ █████╗ ██████╗ ███████╗███╗ ██╗████████╗
████╗ ████║██║ ██║╚══██╔══╝██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝
██╔████╔██║██║ ██║ ██║ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║
██║╚██╔╝██║██║ ██║ ██║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║
██║ ╚═╝ ██║╚██████╔╝ ██║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝
███████╗██████╗ ██╗ ██╗
██╔════╝██╔══██╗██║ ██╔╝
███████╗██║ ██║█████╔╝
╚════██║██║ ██║██╔═██╗
███████║██████╔╝██║ ██╗
╚══════╝╚═════╝ ╚═╝ ╚═╝
The TypeScript client for the MutagenT platform API.
Table of Contents
- What the SDK covers
- 0.6.0 breaking changes
- Installation
- Quick Start
- Authentication
- Client groups
- Streaming
- Pagination
- Retries
- Error Handling
- Server Selection
- Custom HTTP Client
- Standalone functions
- Debugging
- API Reference
- See Also
- License
What the SDK covers
@mutagent/sdk is generated from the MutagenT platform OpenAPI document. One Mutagent client
exposes 13 groups of methods:
| Group | What it calls |
|---|---|
userProfile | The signed-in user's profile, password and login sessions |
organizations | Organizations, slug lookups and member counts |
organizationMembers | Organization membership and roles |
workspaces | Workspaces and the default workspace |
workspaceMembers | Workspace membership and roles |
invitations | Organization invitations |
agents | Agent records: create, read, update, delete, look up by slug |
llmProviders | LLM provider configurations, model catalog, connection tests |
managedAgents | Managed agent deployments: slots, revisions, operations |
traces | Trace ingestion and reads of traces, spans and logs |
sandbox | Sandbox providers, presets, sandbox lifecycle, commands, the sandbox token exchange, and Helix sessions addressed by sandbox id |
environments | Workspace Environments (named sets of variables and secrets) |
helixSessions | Helix sessions addressed by session reference: launch, list, input, signal, checkpoint, restore, stream |
Every method is also available as a standalone function (see Standalone functions).
0.6.0 breaking changes
0.6.0 is one breaking release after 0.5.x. Code written against 0.5.x needs the following changes.
Client groups
sandboxholds sandbox providers, presets, the sandbox lifecycle, commands, the token exchange (createSandboxToken) and the session routes addressed by sandbox id.- New group
helixSessions:launchHelixSession,listHelixSessions,sendHelixSessionInput,closeHelixSessionInput,signalHelixSession,checkpointHelixSession,listHelixSessionCheckpoints,restoreHelixSession,streamHelixSession,getHelixModels,setHelixDefaultModels. The ones that existed in 0.5.x were methods ofsandbox. - New group
environments. In 0.5.x its operations were methods ofsandbox. helixAgentDeploymentsis renamedmanagedAgents. Its method names are unchanged.providerConfigsis renamedllmProviders. Its methods are renamed too; see the table below.userProfilekeeps its name. Two of its methods are renamed; see the table below.
Operation names
39 operations are renamed. In the first 27 rows the 0.5.x name was derived from the route. The last 12 rows rename operations that already had their own names.
| 0.5.x | 0.6.0 |
|---|---|
sandbox.getApiSandboxProviders | sandbox.listSandboxProviders |
sandbox.postApiSandboxPreflight | sandbox.preflightSandbox |
sandbox.getApiSandboxPresets | sandbox.listSandboxPresets |
sandbox.postApiSandboxRun | sandbox.runSandboxCommand |
sandbox.postApiSandbox | sandbox.createSandbox |
sandbox.getApiSandbox | sandbox.listSandboxes |
sandbox.getApiSandboxById | sandbox.getSandbox |
sandbox.deleteApiSandboxById | sandbox.deleteSandbox |
sandbox.getApiSandboxByIdStream | sandbox.streamSandbox |
sandbox.postApiSandboxByIdExec | sandbox.execSandboxCommand |
sandbox.postApiSandboxTelemetryV1Traces | sandbox.ingestSandboxTraces |
sandbox.getApiSandboxByIdTraces | sandbox.listSandboxSpans |
sandbox.postApiSandboxByIdSession | sandbox.startSandboxHelixSession |
sandbox.getApiSandboxHelixDefaults | helixSessions.getHelixModels |
sandbox.putApiSandboxHelixDefaults | helixSessions.setHelixDefaultModels |
sandbox.getApiSandboxByIdSessions | sandbox.listSandboxHelixSessions |
sandbox.postApiSandboxByIdInput | sandbox.sendSandboxHelixSessionInput |
sandbox.postApiSandboxByIdSignal | sandbox.signalSandboxHelixSession |
sandbox.postApiSandboxByIdCheckpoint | sandbox.checkpointSandboxHelixSession |
sandbox.getApiSandboxByIdCheckpoints | sandbox.listSandboxCheckpoints |
sandbox.postApiSandboxByIdRestore | sandbox.restoreSandbox |
sandbox.postApiSandboxToken | sandbox.createSandboxToken |
sandbox.getApiSandboxEnvironments | environments.listEnvironments |
sandbox.getApiSandboxEnvironmentsByName | environments.getEnvironment |
sandbox.putApiSandboxEnvironmentsByName | environments.replaceEnvironment |
sandbox.patchApiSandboxEnvironmentsByName | environments.updateEnvironment |
sandbox.deleteApiSandboxEnvironmentsByName | environments.deleteEnvironment |
userProfile.listSessions | userProfile.listUserSessions |
userProfile.deleteSession | userProfile.revokeUserSession |
sandbox.listHelixWorkspaceSessions | helixSessions.listHelixSessions |
sandbox.inputHelixSession | helixSessions.sendHelixSessionInput |
providerConfigs.listProviders | llmProviders.listProviderConfigs |
providerConfigs.createProvider | llmProviders.createProviderConfig |
providerConfigs.getProvider | llmProviders.getProviderConfig |
providerConfigs.updateProvider | llmProviders.updateProviderConfig |
providerConfigs.deleteProvider | llmProviders.deleteProviderConfig |
providerConfigs.getModelsCatalog | llmProviders.getModelCatalog |
providerConfigs.listProviderModels | llmProviders.listProviderConfigModels |
providerConfigs.testProvider | llmProviders.testProviderConfig |
The standalone function names follow the same change, including the group prefix. For example
sandboxGetApiSandboxById is now sandboxGetSandbox, and providerConfigsTestProvider is now
llmProvidersTestProviderConfig.
Model, enum and error names
Model, enum and error class names come from the schema names in the API document, for example
Mode, HelixArm, HelixSignal, HelixLaunchRequest, LlmProviderType and
ErrorResponse. Names the generator invented in 0.5.x, such as Schemadefaul7, ModeArmModel and
NameSlugDescription5, no longer exist.
Session mode values
A Helix session mode is headless or interactive (Mode.Headless, Mode.Interactive). The
0.5.x values oneshot and rpc are gone.
Default server
The default server is https://api.mutagent.io. In 0.5.x it was http://localhost:3003. To call a
local server, pass serverURL: "http://localhost:3003" or serverIdx: 1.
Streams
streamHelixSession and streamSandbox send Accept: text/event-stream. They resolve to the event
text as one string when the server closes the stream. They do not yield events as they arrive.
Installation
npm
npm install @mutagent/sdk
pnpm
pnpm add @mutagent/sdk
yarn
yarn add @mutagent/sdk
bun
bun add @mutagent/sdk
This package ships CommonJS (require) and ES module (import) builds. Supported runtimes are listed
in RUNTIMES.md.
Quick Start
import { Mutagent } from "@mutagent/sdk";
const mutagent = new Mutagent({
security: {
apiKey: process.env["MUTAGENT_API_KEY"] ?? "",
},
});
async function run() {
const profile = await mutagent.userProfile.getProfile();
console.log(profile);
const workspaces = await mutagent.workspaces.listWorkspaces();
console.log(workspaces);
}
run();
Authentication
The security option has two fields. Both are read from the environment when you do not pass them.
| Option | Sent as | Environment variable | Used by |
|---|---|---|---|
apiKey | x-api-key header | MUTAGENT_API_KEY | Every group except sandbox, environments and helixSessions |
bearerAuth | Authorization: Bearer header | MUTAGENT_BEARER_AUTH | sandbox (except createSandboxToken), environments and helixSessions, which accept no other credential. The other groups also declare it |
When an operation accepts both and both are set, the SDK sends the API key.
API key
A platform API key starts with mg_live_. Create one in the MutagenT app under Settings, API Keys.
import { Mutagent } from "@mutagent/sdk";
const mutagent = new Mutagent({
security: { apiKey: process.env["MUTAGENT_API_KEY"] ?? "" },
});
Sandbox token
The sandbox, environments and helixSessions operations do not accept an API key. They require a
short-lived sandbox token, sent as a bearer token. Exchange an API key for one with
sandbox.createSandboxToken. That call takes the API key in its own first argument; it does not read
the client's security option or MUTAGENT_API_KEY.
import { Mutagent } from "@mutagent/sdk";
async function sandboxClient(workspaceId: string): Promise<Mutagent> {
const apiKey = process.env["MUTAGENT_API_KEY"] ?? "";
const platform = new Mutagent({ security: { apiKey } });
const { token, expiresIn } = await platform.sandbox.createSandboxToken(
{ apiKey },
{ workspaceId },
);
console.log(`sandbox token expires in ${expiresIn}s`);
// apiKey stays in place for the platform groups; bearerAuth is used by
// sandbox, environments and helixSessions.
return new Mutagent({ security: { apiKey, bearerAuth: token } });
}
security also accepts an async function that returns the credentials, which lets you refresh the
sandbox token before it expires.
Client groups
The examples below assume a client built as in Authentication. Examples for
sandbox, environments and helixSessions need a client that holds a sandbox token.
userProfile
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const profile = await mutagent.userProfile.getProfile();
const sessions = await mutagent.userProfile.listUserSessions();
console.log(profile, sessions);
}
organizations
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const organization = await mutagent.organizations.getOrganizationBySlug({ slug: "acme" });
const memberCount = await mutagent.organizations.getOrganizationMemberCount({ orgId: "<org-id>" });
console.log(organization, memberCount);
}
organizationMembers
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const members = await mutagent.organizationMembers.listOrganizationMembers({ orgId: "<org-id>" });
console.log(members);
}
workspaces
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const workspace = await mutagent.workspaces.createWorkspace({
name: "Support",
slug: "support",
});
await mutagent.workspaces.setDefaultWorkspace({ wsId: workspace.id });
}
workspaceMembers
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const members = await mutagent.workspaceMembers.listWorkspaceMembers({ wsId: "<workspace-id>" });
console.log(members);
}
invitations
import { Mutagent } from "@mutagent/sdk";
import { OrganizationRole } from "@mutagent/sdk/models";
async function example(mutagent: Mutagent) {
const invitation = await mutagent.invitations.createInvitation({
orgId: "<org-id>",
body: { email: "[email protected]", role: OrganizationRole.Editor },
});
console.log(invitation.id);
}
agents
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const agent = await mutagent.agents.createAgent({
name: "Support Agent",
slug: "support-agent",
systemPrompt: "You answer customer support questions.",
});
const sameAgent = await mutagent.agents.getAgentBySlug({ slug: "support-agent" });
await mutagent.agents.updateAgent({ id: agent.id, body: { description: "Tier 1 support" } });
console.log(sameAgent.id === agent.id);
}
llmProviders
import { Mutagent } from "@mutagent/sdk";
import { LlmProviderType } from "@mutagent/sdk/models";
async function example(mutagent: Mutagent) {
const provider = await mutagent.llmProviders.createProviderConfig({
name: "Anthropic",
provider: LlmProviderType.Anthropic,
apiKey: process.env["ANTHROPIC_API_KEY"] ?? "",
});
const test = await mutagent.llmProviders.testProviderConfig({ id: provider.id });
const models = await mutagent.llmProviders.listProviderConfigModels({ id: provider.id });
console.log(test, models);
}
managedAgents
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const agents = await mutagent.managedAgents.listHelixAgents({ limit: 20 });
for (const agent of agents.data) {
const detail = await mutagent.managedAgents.getHelixAgent({ slug: agent.slug });
console.log(detail);
}
}
traces
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const traces = await mutagent.traces.listTraces({ limit: 10 });
for (const trace of traces.data) {
const spans = await mutagent.traces.listTraceSpans({ traceId: trace.traceId });
console.log(trace.traceId, spans);
}
}
sandbox
Requires a sandbox token (see Sandbox token).
import { Mutagent } from "@mutagent/sdk";
import { SandboxArch } from "@mutagent/sdk/models";
async function example(mutagent: Mutagent) {
// One command in a new sandbox, deleted after the run.
const run = await mutagent.sandbox.runSandboxCommand({ command: ["uname", "-a"] });
console.log(run.exitCode, run.stdout);
// A sandbox you keep, run commands in, and delete.
const sandbox = await mutagent.sandbox.createSandbox({
definition: { name: "build", image: "<image>", arch: SandboxArch.X8664 },
});
const result = await mutagent.sandbox.execSandboxCommand({
id: sandbox.id,
body: { command: ["ls", "-la"] },
});
console.log(result.exitCode, result.stdout, result.stderr);
await mutagent.sandbox.deleteSandbox({ id: sandbox.id });
}
environments
Requires a sandbox token.
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
await mutagent.environments.replaceEnvironment({
name: "staging",
body: {
vars: { LOG_LEVEL: "debug" },
secrets: { DATABASE_URL: "<secret>" },
},
});
const environments = await mutagent.environments.listEnvironments();
console.log(environments);
}
helixSessions
Requires a sandbox token. A headless session runs the task in its arguments and ends. An
interactive session stays open and reads one JSON command per sendHelixSessionInput call.
import { Mutagent } from "@mutagent/sdk";
import { HelixSignal, Mode } from "@mutagent/sdk/models";
async function example(mutagent: Mutagent) {
const headless = await mutagent.helixSessions.launchHelixSession({
mode: Mode.Headless,
args: ["-p", "Summarise the README in the working directory"],
});
console.log(headless.reference, headless.sandboxId);
const session = await mutagent.helixSessions.launchHelixSession({
mode: Mode.Interactive,
environment: "staging",
});
await mutagent.helixSessions.sendHelixSessionInput({
reference: session.reference,
body: { line: JSON.stringify({ type: "prompt", id: "p1", message: "List the files" }) },
});
await mutagent.helixSessions.signalHelixSession({
reference: session.reference,
body: { signal: HelixSignal.Sigint },
});
}
Per-method reference, with every parameter and response type, is in docs/sdks/.
Streaming
helixSessions.streamHelixSession and sandbox.streamSandbox request Accept: text/event-stream. The
returned promise resolves to the whole event text as one string after the server closes the stream. The
SDK does not parse the events and does not yield them while the stream is open. Pass the last seq you
have read as since to receive only later events.
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent, reference: string) {
const eventText = await mutagent.helixSessions.streamHelixSession({ reference });
for (const block of eventText.split("\n\n")) {
console.log(block);
}
}
Pagination
agents.listAgents and organizations.listOrganizations return an async iterable of pages. Iterate
with for await...of:
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const pages = await mutagent.agents.listAgents({ limit: 20, offset: 0 });
for await (const page of pages) {
console.log(page.result.data.length);
}
}
traces.listTraces, traces.listLogs, managedAgents.listHelixAgents and
helixSessions.listHelixSessions take limit and cursor and return nextCursor. Pass
nextCursor back as cursor to read the next page.
Retries
Per-call retry config
import { Mutagent } from "@mutagent/sdk";
async function example(mutagent: Mutagent) {
const profile = await mutagent.userProfile.getProfile({
retries: {
strategy: "backoff",
backoff: {
initialInterval: 500,
maxInterval: 30000,
exponent: 1.5,
maxElapsedTime: 120000,
},
retryConnectionErrors: true,
},
});
console.log(profile);
}
Global retry config
import { Mutagent } from "@mutagent/sdk";
const mutagent = new Mutagent({
retryConfig: {
strategy: "backoff",
backoff: {
initialInterval: 500,
maxInterval: 30000,
exponent: 1.5,
maxElapsedTime: 120000,
},
retryConnectionErrors: true,
},
security: { apiKey: process.env["MUTAGENT_API_KEY"] ?? "" },
});
Error Handling
Every HTTP error extends MutagentError. Most operations document ErrorResponse, whose data has
error and message.
import { Mutagent } from "@mutagent/sdk";
import * as errors from "@mutagent/sdk/models/errors";
async function example(mutagent: Mutagent) {
try {
await mutagent.agents.getAgent({ id: 404 });
} catch (error) {
if (error instanceof errors.ErrorResponse) {
console.error(error.statusCode, error.data$.error, error.data$.message);
} else if (error instanceof errors.MutagentError) {
console.error(`HTTP ${error.statusCode}: ${error.body}`);
} else {
throw error;
}
}
}
Error properties
| Property | Type | Description |
|---|---|---|
error.message | string | Error message |
error.statusCode | number | HTTP status code, for example 404 |
error.headers | Headers | HTTP response headers |
error.body | string | HTTP response body; empty when the response has none |
error.rawResponse | Response | Raw HTTP response |
error.data$ | varies | Structured error data, on error classes that have it |
Error classes
Extend MutagentError: ErrorResponse, ErrorResponseWithStatus, ProviderError, DeploymentError,
WsError, ModelNotInListError, ModelResolutionError, NoProviderConfiguredError,
TestConnectionResultError, WorkspaceModelListingError, SandboxProviderUnreachableError,
SandboxPayloadTooLargeError, ResponseValidationError.
SandboxPayloadTooLargeError is the 413 response of helixSessions.launchHelixSession,
sandbox.startSandboxHelixSession, sandbox.execSandboxCommand, helixSessions.restoreHelixSession
and sandbox.restoreSandbox when the sandbox provider refuses the request for its size; its data has
error, message, provider, payloadBytes and limitBytes.
Client-side network errors: ConnectionError, RequestTimeoutError, RequestAbortedError,
InvalidRequestError, UnexpectedClientError.
The method pages in docs/sdks/ list which errors each method can throw.
Server Selection
serverIdx | Server | Description |
|---|---|---|
0 (default) | https://api.mutagent.io | Production |
1 | http://localhost:3003 | Development server |
import { Mutagent } from "@mutagent/sdk";
const local = new Mutagent({
serverURL: "http://localhost:3003",
security: { apiKey: process.env["MUTAGENT_API_KEY"] ?? "" },
});
Custom HTTP Client
The SDK sends requests through an HTTPClient that wraps fetch. You can pass your own fetcher and
add hooks:
import { Mutagent } from "@mutagent/sdk";
import { HTTPClient } from "@mutagent/sdk/lib/http";
const httpClient = new HTTPClient({
fetcher: (input, init) => fetch(input, init),
});
httpClient.addHook("beforeRequest", (request) => {
const next = new Request(request, {
signal: request.signal ?? AbortSignal.timeout(10_000),
});
next.headers.set("x-app-version", "1.0.0");
return next;
});
httpClient.addHook("requestError", (error, request) => {
console.error(`Request failed: ${request.method} ${request.url}`, error);
});
const mutagent = new Mutagent({
httpClient,
security: { apiKey: process.env["MUTAGENT_API_KEY"] ?? "" },
});
Standalone functions
Every method is also exported as a function named <group><Method> under @mutagent/sdk/funcs/. Use
them with MutagentCore when bundle size matters: a bundler can drop the functions you do not import.
A standalone function returns a Result holding either the value or a known error, instead of throwing
that error.
import { MutagentCore } from "@mutagent/sdk/core.js";
import { agentsGetAgentBySlug } from "@mutagent/sdk/funcs/agents-get-agent-by-slug.js";
const core = new MutagentCore({
security: { apiKey: process.env["MUTAGENT_API_KEY"] ?? "" },
});
async function run() {
const res = await agentsGetAgentBySlug(core, { slug: "support-agent" });
if (res.ok) {
console.log(res.value);
} else {
console.error(res.error);
}
}
run();
The full list is in FUNCTIONS.md and in the method pages under docs/sdks/.
Debugging
Pass a logger that matches console to log requests and responses. Debug logs include credentials such
as API keys and tokens, so use this only in local development.
import { Mutagent } from "@mutagent/sdk";
const mutagent = new Mutagent({
debugLogger: console,
security: { apiKey: process.env["MUTAGENT_API_KEY"] ?? "" },
});
Setting MUTAGENT_DEBUG=true enables a default debug logger.
API Reference
- docs/sdks/: one page per group, with every method, parameter and error
- FUNCTIONS.md: standalone functions
- RUNTIMES.md: supported runtimes and TypeScript compiler options
- docs.mutagent.io: platform documentation
See Also
- @mutagent/cli: command-line interface for MutagenT
- docs.mutagent.io: platform documentation
- API Reference: REST API reference
- mutagent.io: homepage
License
This software is proprietary and confidential. Unauthorized copying, distribution, or use is strictly prohibited.
(c) 2026 MutagenT. All rights reserved.
Built with care by the MutagenT Team
Twitter • Discord • Website • Documentation