<!-- Markdown mirror. Canonical: https://empryo.com/docs/tools/python-kernel -->

# Python kernel

> Give the agent a Python interpreter that stays running between calls, so loaded data, variables and imports are still there on the next step. Off by default.

The Python kernel gives the agent one Python interpreter that keeps running while you work in a project. Anything the agent loads or defines in one call is still there in the next call.

This is the difference from the `shell` tool. Every `python -c` in the shell starts a new process, so a script that loads a large file has to load it again for every question. With the kernel, the agent loads the data once and then asks as many questions as it needs:

```
python_kernel(code: "import pandas as pd; df = pd.read_csv('sales.csv'); df.shape")
→ (48211, 17)

python_kernel(code: "df.groupby('region').revenue.sum().sort_values().tail(3)")
→ region
  EMEA     1840221.55
  APAC     2110984.10
  NA       3922015.77
```

The second call did not read the file again. `df` was already in memory.

## Turning it on

The kernel is off by default. It runs any code the agent writes, with your user's permissions, which is as much power as the shell tool has. So you have to switch it on:

```json
"agentFeatures": { "pythonKernel": true }
```

You can also switch it on from the app:

- **Terminal UI:** run `/agent-features` and turn on **Python Kernel**.
- **Desktop:** open the **Router** panel, go to the **Behavior** section and turn on **Python kernel**.
- **For one headless run:** `EMPRYO_PYTHON_KERNEL=1 empryo --headless "…"`

You need `python3` (or `python`) on your `PATH`. If Empryo cannot find Python, the tool is not offered to the model at all.

## Parameters

| Field | Type | What it does |
|---|---|---|
| `code` | string | The Python to run. Like a REPL, the value of the last expression is returned |
| `reset` | boolean | Clear all variables first. Send it without `code` to just clear |
| `timeoutMs` | number | Stop after this many milliseconds. Default 120000 (2 minutes), maximum 600000 (10 minutes) |

Each call returns what the code printed to stdout and stderr, plus the value of the last expression. If the code raises an exception, the call fails with the traceback, and the interpreter keeps running with its variables intact.

## Behaviour worth knowing

- **IPython is used when it is installed.** You get rich output, `display` and `_`. Without IPython it uses plain Python. You do not need to install anything either way.
- **There is one kernel per project folder.** Two tabs open on the same repository share the same variables. The data belongs to the project, not to one chat.
- **The working directory is the project root**, so relative paths work as you expect.
- **A code run that hits its time limit is stopped** and the kernel restarts, so the turn does not hang. The reply tells the agent this happened. All variables are lost when that happens.
- **It is not a Jupyter client.** Empryo talks to the Python process directly, so you do not need Jupyter installed.

## When not to use it

Use `shell` for one-off commands such as `pytest`, `ruff` or a script you already have. The kernel adds nothing there, and it leaves a process running after the call.

Use the [project tool](/docs/tools/project) for lint, typecheck and tests, because it already knows your toolchain.

The kernel is worth it when each step builds on data the previous step left in memory, such as exploring a dataset or debugging a calculation step by step.
