# Code Execution (/docs/code-execution)

Daytona runs Python, TypeScript, and JavaScript code in sandboxes through language kernels, so untrusted or generated code executes in isolation from your application.

Every run is a code process that executes in a session with a language kernel. The kernel keeps state between runs in the same session, so variables, imports, and functions defined in one run are available in the next. Runs use a shared kernel per language by default; isolated runs and interpreter contexts give code its own kernel. To run shell commands and manage long-running processes, see [process execution](/docs/process-execution). To follow a run's output live, see [log streaming](/docs/log-streaming).

<CodeExecutionVisual />

## Use cases [#use-cases]

Code execution is used when an application runs Python, TypeScript, or JavaScript that it did not write or does not trust.

- **AI-generated code.** An agent writes code, runs it in the sandbox, and reads the output and errors to correct its next attempt. The code runs isolated from your application. Each result also holds the exit status of the process.

- **Data analysis.** The kernel keeps data, imports, and functions in memory between runs, so each step builds on the previous one, as in a notebook. Runs without a context share one kernel per language, so later runs in that language see the same data. The first run in a language installs the kernel, so that run can take longer than later ones.

- **Charts and tables.** Runs that plot or display data return charts and tables as artifacts with the result. Each artifact is keyed by MIME type, so an application renders it in the right format. A flag on each result tells the value of the last expression apart from displayed outputs.

- **Code interpreters for users.** Each user or conversation gets its own interpreter context, so state from one does not reach another. A context has its own kernel, working directory, and environment. Its kernel uses memory even while idle, until the application [deletes the context](#delete-a-context).

- **One-off runs.** An isolated kernel runs code with no state from earlier runs. The session is deleted after the run, so nothing the code defines reaches other runs. An isolated run cannot be combined with an interpreter context.

## Run code [#run-code]

Run code in a sandbox. Runs without a context share one kernel per language, so state from one run is available to later runs in that language. The default language is Python.

The result contains the standard output and standard error, rich outputs, the exception if the code raised one, and the exit status of the process.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

response = sandbox.run_code('''
def greet(name):
    return f"Hello, {name}!"

print(greet("Daytona"))
''')
print(response.logs.stdout)
```

| **Parameter** | **Type**                 | **Description**                                                                                                  |
| ------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `code` | str | Sets the code to run. This parameter is required. |
| `language` | str | Sets the language: `python`, `typescript`, or `javascript`. The default is `python`. |
| `context` | InterpreterContext | Runs the code in an [interpreter context](#interpreter-contexts) instead of the shared kernel. |
| `isolated` | bool | Runs the code in a [temporary kernel](#run-code-in-an-isolated-kernel). The default is `False`. |
| `cwd` | str | Sets the working directory of the shared kernel. Only the run that starts the kernel sets it, and later runs ignore it. To run code in another directory, use an [interpreter context](#interpreter-contexts) or an [isolated run](#run-code-in-an-isolated-kernel). |
| `env` | Mapping\[str, str\] | Sets environment variables for the shared kernel. Only the run that starts the kernel sets them. A later run that passes different variables raises an error with code `UNSUPPORTED_OPERATION`. |
| `timeout` | float | Sets how many seconds the client waits. On timeout, the kernel is interrupted and the result of the run is returned with exit code `1`; a run still queued behind another run on the same kernel returns reason `timed_out` without an exit code. The kernel keeps its state. `0` means no limit. The default is no limit. |

The response has the following fields:

| **Field** | **Description** |
| --------- | --------------- |
| `logs` | Holds the standard output and standard error. |
| `results` | Holds the rich outputs. |
| `error` | Holds the exception, if the code raised one. |
| `process` | Holds the exit status of the process: `0` when the code finished, and `1` when it raised an exception or was interrupted. If the kernel stopped during the run, the reason is `lost` and the next run starts a new kernel without the earlier state. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

const response = await sandbox.runCode(`
def greet(name):
    return f"Hello, {name}!"

print(greet("Daytona"))
`)
console.log(response.logs.stdout)
```

| **Parameter** | **Type**                 | **Description**                                                                                                       |
| ------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `code` | string | Sets the code to run. This parameter is required. |
| `language` | string | Sets the language: `'python'`, `'typescript'`, or `'javascript'`. The default is `'python'`. |
| `context` | InterpreterContextReference \| InterpreterContextJSON | Runs the code in an [interpreter context](#interpreter-contexts) instead of the shared kernel. |
| `isolated` | boolean | Runs the code in a [temporary kernel](#run-code-in-an-isolated-kernel). The default is `false`. |
| `cwd` | string | Sets the working directory of the shared kernel. Only the run that starts the kernel sets it, and later runs ignore it. To run code in another directory, use an [interpreter context](#interpreter-contexts) or an [isolated run](#run-code-in-an-isolated-kernel). |
| `env` | Record\<string, string> | Sets environment variables for the shared kernel. Only the run that starts the kernel sets them. A later run that passes different variables raises an error with code `UNSUPPORTED_OPERATION`. |
| `timeoutSeconds` | number | Sets how many seconds the client waits. On timeout, the kernel is interrupted and the result of the run is returned with exit code `1`; a run still queued behind another run on the same kernel returns reason `timed_out` without an exit code. The kernel keeps its state. `0` means no limit. The default is no limit. |

The response has the following fields:

| **Field** | **Description** |
| --------- | --------------- |
| `logs` | Holds the standard output and standard error. |
| `results` | Holds the rich outputs. |
| `error` | Holds the exception, if the code raised one. |
| `process` | Holds the exit status of the process: `0` when the code finished, and `1` when it raised an exception or was interrupted. If the kernel stopped during the run, the reason is `lost` and the next run starts a new kernel without the earlier state. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Without sessionId the code runs on the shared per-language session "code-python"
# waitMs holds the response for up to that many milliseconds while the process runs (capped at 600000). logs=text attaches the first log page.
curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=5000&logs=text' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "kind": "code",
  "language": "python",
  "code": "def greet(name):\n    return f\"Hello, {name}!\"\n\nprint(greet(\"Daytona\"))"
}'
```

| **Field**   | **Type** | **Description**                                                                                |
| ----------- | -------- | ---------------------------------------------------------------------------------------------- |
| `kind` | string | Sets the process kind. Use `code` for a code run. |
| `language` | string | Sets the language: `python`, `typescript`, or `javascript`. With `sessionId`, the language must match the context, otherwise the request returns `BAD_REQUEST`. This field is required without `sessionId`. |
| `code` | string | Sets the code to run. |
| `sessionId` | string | Runs the code in an [interpreter context](#interpreter-contexts). Without `sessionId`, the code runs on the shared per-language session. |
| `cwd` | string | Sets the working directory of the shared kernel. Only the run that starts the kernel sets it, and later runs ignore it. |
| `env` | object | Sets environment variables for the shared kernel. Only the run that starts the kernel sets them. A later run that passes different variables returns `UNSUPPORTED_OPERATION`. Cannot be combined with `sessionId`. |

The response has the following fields:

| **Field** | **Description** |
| --------- | --------------- |
| `state` | The state of the process: `starting`, `provisioning`, `running`, or `terminal`. The first run in a language installs and starts the kernel. If that takes longer than `waitMs`, the state is not yet `terminal`. Wait with `GET /processes/{processId}/wait`, then read the logs. |

<Callout type="note" title="Notes">
- The request requires the `write:sandboxes` permission.
- `{toolboxProxyUrl}` is the `toolbox_proxy_url` field of the [sandbox](/docs/sandboxes#get-a-sandbox).
</Callout>

</TabItem>
</Tabs>

### Artifacts [#artifacts]

Rich outputs such as charts and tables are returned with the result, keyed by MIME type.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()
sandbox.process.run("pip install matplotlib numpy")

code = '''
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 30)
plt.plot(x, np.sin(x))
plt.title("Sine wave")
plt.show()
'''

response = sandbox.run_code(code)
if response.error:
    print(response.error.name, response.error.value)
for result in response.results:
    print(list(result.data))  # MIME types, for example ['image/png', 'text/plain']
```

The response has the following fields:

| **Field** | **Description** |
| --------- | --------------- |
| `results` | Holds the rich outputs. |
| `text`, `html`, `png`, `svg`, `json` | Each of these fields of a result mirrors the matching MIME type in `data`. |
| `is_main_result` | Is `True` for the value of the last expression and `False` for displayed outputs. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()
await sandbox.process.run('pip install matplotlib numpy')

const response = await sandbox.runCode(`
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 30)
plt.plot(x, np.sin(x))
plt.title("Sine wave")
plt.show()
`)

if (response.error) {
    console.log(response.error.name, response.error.value)
}
for (const result of response.results) {
    console.log(Object.keys(result.data)) // MIME types, for example ['image/png', 'text/plain']
}
```

The response has the following fields:

| **Field** | **Description** |
| --------- | --------------- |
| `results` | Holds the rich outputs. |
| `text`, `html`, `png`, `svg`, `json` | Each of these fields of a result mirrors the matching MIME type in `data`. |
| `isMainResult` | Is `true` for the value of the last expression and `false` for displayed outputs. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Install the packages the code imports
curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=60000' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"kind": "exec", "shellCommand": "pip install matplotlib numpy"}'

# When the install is not terminal yet, wait until it exits; timeoutMs=0 waits without a limit
curl '{toolboxProxyUrl}/{sandboxId}/processes/{processId}/wait?timeoutMs=0' \
  --header 'Authorization: Bearer YOUR_API_KEY'

# Rich outputs arrive as log frames on the "display" and "execute_result" channels.
# Each frame's data is a JSON MIME bundle, for example {"image/png": "...", "text/plain": "..."}.
curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=60000&logs=text' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "kind": "code",
  "language": "python",
  "code": "import matplotlib.pyplot as plt\nimport numpy as np\n\nx = np.linspace(0, 10, 30)\nplt.plot(x, np.sin(x))\nplt.title(\"Sine wave\")\nplt.show()"
}'
```

</TabItem>
</Tabs>

## Run code in an isolated kernel [#run-code-in-an-isolated-kernel]

Run code in a temporary kernel that starts with no state. Daytona creates a session with a new kernel, runs the code, and deletes the session after the run. Nothing the code defines is visible to other runs, and the code does not see state from the shared kernel or from interpreter contexts.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

sandbox.run_code("value = 42")

# The isolated kernel does not see variables from the shared kernel
response = sandbox.run_code("print(value)", isolated=True)
if response.error:
    print(response.error.name)  # NameError
```

| **Parameter** | **Type**          | **Description**                                         |
| ------------- | ----------------- | ------------------------------------------------------- |
| `isolated` | bool | Runs the code in a temporary kernel when set to `True`. Each run starts a new kernel, so `timeout` must also cover the kernel start. If `timeout` runs out before the kernel starts, the call raises an error with code `REQUEST_TIMEOUT`. The default is `False`. This parameter cannot be combined with `context`. |
| `cwd` | str | Sets the working directory of the temporary kernel. |
| `env` | Mapping\[str, str\] | Sets environment variables of the temporary kernel. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

await sandbox.runCode('value = 42')

// The isolated kernel does not see variables from the shared kernel
const response = await sandbox.runCode('print(value)', { isolated: true })
console.log(response.error?.name) // NameError
```

| **Parameter** | **Type**                 | **Description**                                              |
| ------------- | ------------------------ | ------------------------------------------------------------ |
| `isolated` | boolean | Runs the code in a temporary kernel when set to `true`. Each run starts a new kernel, so `timeoutSeconds` must also cover the kernel start. If `timeoutSeconds` runs out before the kernel starts, the call raises an error with code `REQUEST_TIMEOUT`. The default is `false`. This parameter cannot be combined with `context`. |
| `cwd` | string | Sets the working directory of the temporary kernel. |
| `env` | Record\<string, string> | Sets environment variables of the temporary kernel. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Create a session with a new kernel
curl '{toolboxProxyUrl}/{sandboxId}/sessions' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"id": "isolated-run", "kernel": "python"}'

# Run the code in that session
curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=60000&logs=text' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"kind": "code", "language": "python", "sessionId": "isolated-run", "code": "print(value)"}'

# Delete the session and its kernel
curl '{toolboxProxyUrl}/{sandboxId}/sessions/isolated-run' \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

<Callout type="note" title="Notes">
- The request requires the `write:sandboxes` permission.
- Delete the session even when the run fails.
</Callout>

</TabItem>
</Tabs>

## Interpreter contexts [#interpreter-contexts]

An interpreter context is a session with its own language kernel, working directory, and environment. State persists across runs in a context and is not shared with the shared kernel or other contexts. A context lives until deleted, so its kernel uses memory while idle.

In the Toolbox API, a context is a [session](/docs/api/toolbox/sessions) that runs a language kernel. Shell sessions are not created through this endpoint; see [sessions](/docs/process-execution#session-operations).

### Create a context [#create-a-context]

Create an interpreter context and run code in it. Run code with the context handle, or pass the handle to a run in the sandbox.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

ctx = sandbox.interpreter.create_context(language="python", env={"STAGE": "dev"})
try:
    ctx.run("value = 'stored in ctx'")
    result = sandbox.run_code("print(value)", context=ctx)
    print(result.logs.stdout)
finally:
    ctx.close()
```

| **Parameter** | **Type**            | **Description**                                                         |
| ------------- | ------------------- | ----------------------------------------------------------------------- |
| `language` | str | Sets the language: `python`, `typescript`, or `javascript`. This parameter is required. |
| `context_id` | str | Sets the context ID for reconnecting later. The ID has at most `128` ASCII letters, digits, `.`, `_`, and `-`, and is unique in the sandbox. An ID that is in use returns `NAME_CONFLICT`. If omitted, an ID is generated. |
| `cwd` | str | Sets the working directory of the kernel. |
| `env` | Mapping\[str, str\] | Sets the kernel environment variables. Runs in a context do not accept `env`. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

const ctx = await sandbox.interpreter.createContext({ language: 'python', env: { STAGE: 'dev' } })
try {
    await ctx.run(`value = 'stored in ctx'`)
    const result = await sandbox.runCode(`print(value)`, { context: ctx })
    console.log(result.logs.stdout)
} finally {
    await ctx.close()
}
```

| **Parameter** | **Type**                 | **Description**                                                         |
| ------------- | ------------------------ | ----------------------------------------------------------------------- |
| `language` | string | Sets the language: `'python'`, `'typescript'`, or `'javascript'`. This parameter is required. |
| `contextId` | string | Sets the context ID for reconnecting later. The ID has at most `128` ASCII letters, digits, `.`, `_`, and `-`, and is unique in the sandbox. An ID that is in use returns `NAME_CONFLICT`. If omitted, an ID is generated. |
| `cwd` | string | Sets the working directory of the kernel. |
| `env` | Record\<string, string> | Sets the kernel environment variables. Runs in a context do not accept `env`. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Create a context (session with a language kernel). Omit "id" to get a generated one.
curl '{toolboxProxyUrl}/{sandboxId}/sessions' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"id": "my-context", "kernel": "python", "env": {"STAGE": "dev"}}'

# Run code in the context; state persists between runs
curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=60000&logs=text' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"kind": "code", "language": "python", "sessionId": "my-context", "code": "value = \"stored in ctx\""}'

curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=60000&logs=text' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"kind": "code", "language": "python", "sessionId": "my-context", "code": "print(value)"}'
```

| **Field** | **Type** | **Description**                                                                         |
| --------- | -------- | --------------------------------------------------------------------------------------- |
| `id` | string | Sets the context ID for reconnecting later. The ID has at most `128` ASCII letters, digits, `.`, `_`, and `-`, and is unique in the sandbox. An ID that is in use returns `NAME_CONFLICT`. If omitted, an ID is generated. |
| `kernel` | string | Sets the context language: `python`, `typescript`, or `javascript`. |
| `env` | object | Sets the kernel environment variables. Runs in a context do not accept `env`. |

</TabItem>
</Tabs>

### List contexts [#list-contexts]

List a sandbox's interpreter contexts. The list also includes the shared kernel of each language that has run code, with the ID `code-python`, `code-typescript`, or `code-javascript`. The list does not include shell sessions.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

for ctx in sandbox.interpreter.list_contexts():
    print(f"Context: {ctx.context_id}, Language: {ctx.language}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

for (const ctx of await sandbox.interpreter.listContexts()) {
  console.log(`Context: ${ctx.contextId}, Language: ${ctx.language}`)
}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl '{toolboxProxyUrl}/{sandboxId}/sessions' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

</TabItem>
</Tabs>

### Reconnect to a context [#reconnect-to-a-context]

Reconnect to an existing context from another worker or process. Contexts are addressed by ID, so any client with the sandbox ID and the context ID can run code in the context.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

# Worker A: create a context with a known ID
ctx = sandbox.interpreter.create_context(language="python", context_id="my-context")
ctx.run("x = 42")

# Worker B: reconnect to the context by ID
context = sandbox.interpreter.connect_context("my-context", language="python")
response = context.run("print(x)")
print(response.logs.stdout)  # 42

# Or persist the context in worker A and reconnect from the saved dict, which carries the language
saved = ctx.to_json()  # {"sandboxId": "...", "contextId": "my-context", "language": "python"}
context = sandbox.interpreter.connect_context(saved)
```

| **Parameter** | **Type** | **Description**                                                                                        |
| ------------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `language` | str | Sets the context language. This parameter is required when you pass an ID. Without `language`, `connect_context()` raises `DaytonaError` with code `BAD_REQUEST`. |

<Callout type="note" title="Notes">
- Running code in the context requires the `write:sandboxes` permission.
- `connect_context()` takes a context ID with `language`, or the saved dict.
- `connect_context()` sends no request, so it does not check that the context exists.
</Callout>

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

// Worker A: create a context with a known ID
const ctx = await sandbox.interpreter.createContext({ contextId: 'my-context', language: 'python' })
await ctx.run('x = 42')

// Worker B: reconnect to the context by ID
const context = sandbox.interpreter.connectContext('my-context', 'python')
const response = await context.run('print(x)')
console.log(response.logs.stdout) // 42

// Or persist the context in worker A and reconnect from the saved object, which carries the language
const saved = ctx.toJSON() // { sandboxId: '...', contextId: 'my-context', language: 'python' }
const restored = sandbox.interpreter.connectContext(saved)
```

<Callout type="note" title="Notes">
- Running code in the context requires the `write:sandboxes` permission.
- `connectContext()` takes a context ID with the language, or the saved object.
- `connectContext()` sends no request, so it does not check that the context exists.
</Callout>

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Check that the context exists; an unknown ID returns 404 with SESSION_NOT_FOUND
curl '{toolboxProxyUrl}/{sandboxId}/sessions/my-context' \
  --header 'Authorization: Bearer YOUR_API_KEY'

# Run code in the context from any client
curl '{toolboxProxyUrl}/{sandboxId}/processes?waitMs=5000&logs=text' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"kind": "code", "language": "python", "code": "print(x)", "sessionId": "my-context"}'
```

| **Field**         | **Description**                                                              |
| ----------------- | ---------------------------------------------------------------------------- |
| `kernel`          | The language kernel of the context.                                          |
| `active`          | Whether the kernel of the context is running. When it is `false`, the next run starts a new kernel without the earlier state. |
| `cwd`             | The working directory the kernel started in. A change made by code is not tracked. |
| `kernelProcessId` | The ID of the long-lived kernel process.                                     |
| `processIds`      | The IDs of the runs in the context, in creation order.                       |

</TabItem>
</Tabs>

### Delete a context [#delete-a-context]

Delete an interpreter context. Deleting a context shuts its kernel down and frees its memory.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

ctx = sandbox.interpreter.create_context(language="python")
try:
    ctx.run("data = list(range(10_000_000))")
finally:
    sandbox.interpreter.delete_context(ctx)
```

<Callout type="note" title="Notes">
- The request requires the `write:sandboxes` permission.
- `delete_context()` takes a context handle or a context ID.
</Callout>

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

const ctx = await sandbox.interpreter.createContext({ language: 'python' })
try {
    await ctx.run('data = list(range(10_000_000))')
} finally {
    await sandbox.interpreter.deleteContext(ctx)
}
```

<Callout type="note" title="Notes">
- The request requires the `write:sandboxes` permission.
- `deleteContext()` takes a context handle or a context ID.
</Callout>

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl '{toolboxProxyUrl}/{sandboxId}/sessions/my-context' \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

</TabItem>
</Tabs>

## Errors [#errors]

The SDKs raise these errors with the codes in the following table, and the Toolbox API returns them in the `code` field. An exception in the code itself is not an error of the request: it is returned in the result.

| **Code**                    | **Meaning**                                                                                                                                                      | **What to do**                                                                   |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| **`SESSION_NOT_FOUND`**     | The context does not exist, or it was deleted.                                                                                                                   | Create the context again. Its earlier state is lost.                             |
| **`NAME_CONFLICT`**         | A context with this ID already exists in the sandbox.                                                                                                            | Use another ID, or reconnect to the existing context.                            |
| **`UNSUPPORTED_OPERATION`** | A run passed environment variables that its kernel does not take: a run on the shared kernel with variables other than those it started with, or an API run with `sessionId` and `env`. | Set the variables when you create an interpreter context.                        |
| **`BAD_REQUEST`**           | A context ID without a language, a language that does not match the context, an isolated run with a context, or an SDK run in a context that passes environment variables. | Pass the language of the context, run without `isolated`, or set the variables when you create the context. |
| **`REQUEST_TIMEOUT`**       | The timeout of an isolated run ran out before its kernel started.                                                                                                | Raise the timeout.                                                               |

## Permissions [#permissions]

Code execution runs through the toolbox of a sandbox. Access is governed by one project permission, which you can grant to an [organization role](/docs/organizations#roles) or an [API key](/docs/api-keys).

A [sandbox access token](/docs/sandboxes#create-an-access-token) with the toolbox:exec operation grants the same access to a single sandbox, without an API key. The sandbox read permission alone does not grant toolbox access.

| **Permission**        | **Grants**                               |
| --------------------- | ---------------------------------------- |
| **`write:sandboxes`** | Run code and manage interpreter contexts |
