# open

Open the SDK session on an instantiated runtime.

`runtime.open(config, options)` builds the agent runtime, opens the SDK's `TurnInbox` for `config.session_id`, and starts the event pump. A new session ID creates the session, and a stored one reopens it from its checkpoint. A runtime opens once, and a failed open closes it.

```ts title="host.ts"
import { sessionUuid, type AgentRuntime } from 'nanocode-wasm'

declare const runtime: AgentRuntime

// 1. Configure a Claude session with one host tool
await runtime.open(
  {
    endpoint: 'https://api.anthropic.com/v1/messages',
    provider: 'claude',
    scope: 'owner',
    session_id: sessionUuid(),
    subscription: false,
    tools: [
      {
        description: 'Read the current time.',
        name: 'now',
        parameters: { type: 'object' },
      },
    ],
  },
  {
    // 2. Send model requests. The host adds the credential.
    dispatch: (request, signal) =>
      fetch(request.endpoint, {
        body: request.body as Uint8Array<ArrayBuffer>,
        headers: [
          ...request.headers,
          ['x-api-key', process.env.ANTHROPIC_API_KEY ?? ''],
        ],
        method: 'POST',
        redirect: 'error',
        signal,
      }),
    // 3. Run host tool calls
    tools: { call: async () => ({ now: Date.now() }) },
  },
)
```

## Signature

```ts
// Throws HostFailure when the SDK refuses the configuration
open(config: AgentConfiguration, options: RuntimeOptions): Promise<void>
```

## Parameters

### config.code_mode

* **Type:** `boolean`
* **Default:** `false`

Runs Code Mode in the host's JavaScript runtime. The SDK installs `options.remote`, or a default [`LocalHand`](/docs/api/wasm/LocalHand), as the executor `local`, offers the model `exec` and `wait` with the host tools inside cells, and tells it that the cell's `fetch` works. It cannot be combined with `config.remote`.

```ts
// Runs cells in this page
const config = { code_mode: true }
```

### config.endpoint

* **Type:** `string`

The model endpoint. A Claude session posts to this URL, such as `https://api.anthropic.com/v1/messages`. A Codex session uses it as the Responses API base URL.

```ts
// A gateway URL that forwards to the provider
const endpoint = 'https://gateway.example.com/v1/messages'
```

### config.event_coalesce_ms

* **Type:** `number`
* **Default:** `0`

The window in milliseconds over which the SDK's `SessionEvents` pump coalesces events into one logged batch.

```ts
// Logs streamed deltas in 50 ms batches, as the browser demo does
const config = { event_coalesce_ms: 50 }
```

### config.executor

* **Type:** `string`
* **Default:** `'default'`

The name of the remote Code Mode executor that `config.remote` configures.

```ts
// Names the executor that Code Mode places work on
const config = { executor: 'sandbox', remote: true }
```

### config.hands

* **Type:** `boolean`
* **Default:** `false`

Enables hands. If this option is `true`, Code Mode accepts hands that [`attach`](/docs/api/wasm/AgentRuntime#attach) registers, and the agent receives the SDK's hand placement instructions.

```ts
// Accepts hands that connect later
const config = { hands: true }
```

### config.instructions

* **Type:** `string`

Host instructions added to the agent's developer context. If Code Mode has an executor or hands, these instructions come before the hand placement instructions.

```ts
// Adds a house rule to every turn
const config = { instructions: 'Answer in one paragraph.' }
```

### config.model

* **Type:** `string`
* **Default:** Opus 5.5 for `'claude'`, Sol for `'codex'`

A model of `config.provider`, such as `claude-haiku-5-5` or `gpt-6-luna`. A model that does not parse, or a model of the other provider, is a configuration error.

```ts
// A smaller Claude model
const config = {
  model: 'claude-haiku-5-5',
  provider: 'claude' as const,
}
```

### config.provider

* **Type:** `ModelProvider` (`'claude' | 'codex'`)
* **Default:** `'claude'`

The model backend of the session.

```ts
// A Codex session over the Responses API
const config = {
  endpoint: 'https://api.openai.com/v1',
  provider: 'codex' as const,
}
```

### config.remote

* **Type:** `boolean`
* **Default:** `false`

Configures a remote Code Mode executor, named by `config.executor`, as the default executor. During `open`, the SDK requests its catalog through `options.remote.execute` with `connection: null`, so `options.remote` is required.

```ts
// Runs Code Mode on a remote executor
const config = { remote: true }
```

### config.scope

* **Type:** `string`

The session log scope. Pass the same value to `submit`, `turn`, `pending`, `page`, and `cancel`. A `cancel` with this scope also stops a running turn.

```ts
// One scope per session owner
const config = { scope: 'owner' }
```

### config.session_id

* **Type:** `string`

The SDK session ID, a UUIDv7. [`sessionUuid`](/docs/api/wasm/sessionUuid) makes one. If the store holds this session, `open` reopens it.

```ts
import { sessionUuid } from 'nanocode-wasm'

// A new session
const config = { session_id: sessionUuid() }
```

### config.subscription

* **Type:** `boolean`

Selects subscription authentication. Claude clients then use subscription compatibility. Codex sessions then use `OpenAiAuth::host_managed_chatgpt()` over a Responses WebSocket, which requires `options.socket`. Otherwise Codex uses `OpenAiAuth::gateway_managed()` over HTTPS.

```ts
// An API-key session, where the host or its egress injects the key
const config = { subscription: false }
```

### config.thinking

* **Type:** `'none' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'`
* **Default:** the model's default effort

The reasoning effort of a new session. Any other value is a configuration error.

```ts
// Starts the session at low effort
const config = { thinking: 'low' as const }
```

### config.tools

* **Type:** `HostTool[]`
* **Default:** `[]`

Host tools offered to the model, directly and inside Code Mode. `options.tools.call` runs them. [HostTool](/docs/api/wasm/HostTool) documents the shape.

```ts
import type { HostTool } from 'nanocode-wasm'

// A tool with a JSON Schema for its input
const lookup: HostTool = {
  description: 'Look up a key.',
  name: 'lookup',
  parameters: {
    properties: { key: { type: 'string' } },
    required: ['key'],
    type: 'object',
  },
}
```

### options.dispatch

* **Type:** `(request: { endpoint: string; headers: [string, string][]; body: Uint8Array }, signal: AbortSignal, timing: RuntimeTiming) => Promise<Response>`

Sends a model HTTPS request and returns the fetch `Response`. Forward `body` unchanged. The SDK sends no credentials, so the host or its egress adds them. A `3xx` response fails the request with `provider redirect rejected`, and a response without a body fails it too.

```ts
import type { RuntimeOptions } from 'nanocode-wasm'

// Forwards the request and adds an API key header
const dispatch: RuntimeOptions['dispatch'] = (request, signal) =>
  fetch(request.endpoint, {
    body: request.body as Uint8Array<ArrayBuffer>,
    headers: [...request.headers, ['x-api-key', 'key']],
    method: 'POST',
    redirect: 'error',
    signal,
  })
```

`signal` aborts when the SDK cancels the request. `timing` is the [`RuntimeTiming`](/docs/api/wasm/types#runtimetiming) record of this dispatch, which `metrics` reports.

### options.finishing

* **Type:** `(request_id: string) => Record<string, unknown> | Promise<Record<string, unknown>>`

Returns fields to add to a turn's result when the turn finishes. The turn report then includes these fields.

```ts
import type { RuntimeOptions } from 'nanocode-wasm'

// Records the host's region on every finished turn
const finishing: RuntimeOptions['finishing'] = () => ({ region: 'eu' })
```

### options.remote

* **Type:** `{ failed?(): boolean; execute(request: RemoteRequest, id: number): Promise<unknown>; cancel(id: number): void; dispose(): Promise<void> }`

Carries the SDK's remote Code Mode frames for a configured executor (`request.connection` is `null`) and for hands (`request.connection` is the attached connection). [`RemoteExecutor`](/docs/api/wasm/RemoteExecutor) implements `execute`, `cancel`, and `dispose` for one socket. [`LocalHand`](/docs/api/wasm/LocalHand) implements them in process for `config.code_mode`. `failed()` makes `runtime.reusable` false, and `dispose()` runs when the runtime disposes.

```ts
import type { RemoteExecutor, RuntimeOptions } from 'nanocode-wasm'

declare const executor: RemoteExecutor
declare const hands: Map<string, RemoteExecutor>

// Routes each request to the executor or to the hand's connection
const remote: RuntimeOptions['remote'] = {
  cancel: (id) => executor.cancel(id),
  dispose: () => executor.dispose(),
  execute: (request, id) =>
    (request.connection
      ? hands.get(request.connection)!
      : executor
    ).execute(request, id),
  failed: () => executor.failure !== undefined,
}
```

A host that sends none of a `remote_send` batch throws [`RemoteRefusal`](/docs/api/wasm/RemoteExecutor#remoterefusal). The SDK then reports the batch's operations as not dispatched. Any other error leaves them as unknown outcomes.

### options.socket

* **Type:** `{ open(request: { headers: [string, string][] }, signal: AbortSignal, timing: RuntimeTiming): Promise<SocketHandshake>; admit(): Promise<void> }`

Opens Codex Responses WebSockets for subscription sessions. `open` sends the handshake with the SDK's headers and returns a [`SocketHandshake`](/docs/api/wasm/types#sockethandshake). `admit` runs before every frame is sent, so a host can wait for durability or reject a cancelled turn's frames.

```ts
import type { RuntimeOptions, SocketHandshake } from 'nanocode-wasm'

declare function connect(
  headers: [string, string][],
  signal: AbortSignal,
): Promise<SocketHandshake>

// Opens the socket through the host's egress and admits every frame
const socket: RuntimeOptions['socket'] = {
  admit: async () => {},
  open: (request, signal) => connect(request.headers, signal),
}
```

### options.tools

* **Type:** `{ call(name: string, input: unknown, signal: AbortSignal): Promise<unknown> }`

Runs host tools from `config.tools`. The result becomes the tool output, and a thrown error becomes a tool error. [HostTool](/docs/api/wasm/HostTool#optionstoolscall) documents the contract.

```ts
import type { RuntimeOptions } from 'nanocode-wasm'

// Answers every lookup with a fixed value
const tools: RuntimeOptions['tools'] = {
  call: async (name, input) => ({ input, name, value: 'bravo' }),
}
```

## Returns

* **Type:** `Promise<void>`

Resolves when the session is open. [`drive`](/docs/api/wasm/drive), [`attach`](/docs/api/wasm/AgentRuntime#attach), [`settle`](/docs/api/wasm/AgentRuntime#settle), and [`preconnect`](/docs/api/wasm/AgentRuntime#preconnect) then work.

## Errors

* **`HostFailure`:** The SDK refused the configuration, such as a model of the other provider or an unknown `thinking` value. `kind` is `'configuration'` and `permanent` is `true`, so a host can fail the turn instead of retrying it.
* **`Error`:** `agent runtime cannot be opened again` if the runtime was opened or closed before. Other errors come from the store or the SDK while the session opens.

Every failed `open` closes the runtime.

```ts
import {
  HostFailure,
  type AgentRuntime,
  type AgentConfiguration,
  type RuntimeOptions,
} from 'nanocode-wasm'

declare const runtime: AgentRuntime
declare const config: AgentConfiguration
declare const options: RuntimeOptions

try {
  await runtime.open(config, options)
} catch (error) {
  // A permanent failure does not succeed on retry
  if (error instanceof HostFailure && error.permanent)
    console.error(error.kind, error.message)
  else throw error
}
```
