langchain-hyperlight 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ .uv-cache/
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+
14
+ # Editors / OS
15
+ .idea/
16
+ .vscode/
17
+ .DS_Store
@@ -0,0 +1,15 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,304 @@
1
+ Metadata-Version: 2.5
2
+ Name: langchain-hyperlight
3
+ Version: 0.1.0
4
+ Summary: LangChain tool for executing untrusted code in Microsoft Hyperlight micro VMs (experimental, AI-generated)
5
+ Project-URL: Homepage, https://github.com/wildaces215/langchain-hyperlight
6
+ Project-URL: Repository, https://github.com/wildaces215/langchain-hyperlight
7
+ Project-URL: Documentation, https://github.com/wildaces215/langchain-hyperlight#readme
8
+ Author: theph03*nix215
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: code-execution,hyperlight,langchain,micro-vm,sandbox,wasm
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: hyperlight-sandbox[python-guest,wasm]>=0.5.0
25
+ Requires-Dist: langchain-core>=0.3.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
28
+ Requires-Dist: pytest>=8.0; extra == 'dev'
29
+ Provides-Extra: js
30
+ Requires-Dist: hyperlight-sandbox[hyperlight-js,javascript-guest]>=0.5.0; extra == 'js'
31
+ Description-Content-Type: text/markdown
32
+
33
+ > ⚠️ **VIBE-CODED — AI-GENERATED, NOT PRODUCTION-READY**
34
+ >
35
+ > This project was written by an AI ("vibe coded"). It is **experimental** and has had
36
+ > **no security review, fuzzing, or adversarial testing**. It has only been smoke-tested
37
+ > on **Linux (x86_64)**. **Use at your own risk** — do not rely on it for anything
38
+ > security-sensitive or mission-critical. See [Limitations](#limitations).
39
+
40
+ # langchain-hyperlight
41
+
42
+ A [LangChain](https://www.langchain.com/) tool that executes untrusted code inside a
43
+ [Microsoft Hyperlight](https://github.com/hyperlight-dev/hyperlight) **micro virtual machine**.
44
+
45
+ Hyperlight is a lightweight Virtual Machine Manager (VMM) designed to be embedded within
46
+ applications. It runs untrusted code in hardware-isolated micro VMs (KVM, MSHV, or Hyper-V)
47
+ with very low latency and minimal overhead. This package exposes that capability to LangChain
48
+ agents as a standard tool, so an LLM can safely run arbitrary code without touching the host.
49
+
50
+ ## Features
51
+
52
+ - **Hardware isolation** — code runs in a micro VM, not on the host.
53
+ - **Host tool dispatch** — register host callables that guest code invokes by name with
54
+ schema-validated arguments (`call_tool(...)`).
55
+ - **Capability-based file access** — read-only `/input`, writable `/output`, strict path isolation.
56
+ - **Network allow-listing** — network is off by default; opt in per-domain and per-HTTP-verb.
57
+ - **Snapshot / restore** — capture and rewind sandbox state.
58
+ - **Lazy sandbox creation** — constructing the tool is cheap; the micro VM boots on first use.
59
+
60
+ ## Limitations
61
+
62
+ This is an early-stage, AI-generated integration. Be aware of the following before adopting it.
63
+
64
+ ### Platform
65
+
66
+ - **x86_64 only.** Hyperlight currently targets x86_64; there are no `aarch64` (ARM) wheels.
67
+ Raspberry Pi, Apple Silicon, and AWS Graviton are unsupported.
68
+ - **glibc 2.34+.** The Rust backend ships `manylinux_2_34_x86_64` wheels, so it needs a recent
69
+ glibc. Works on Ubuntu 22.04+, Debian 12+, Fedora 36+, RHEL 9+. Does **not** work on
70
+ Ubuntu 20.04, Debian 11, RHEL 8, or musl-based distros (Alpine, Void) without building the
71
+ Rust backend from source.
72
+ - **Python 3.10–3.14.**
73
+ - **A hypervisor is required at runtime:** KVM (`/dev/kvm`) or MSHV on Linux.
74
+ - **Tested on Linux only.** This package has only been tested on **Linux (x86_64)**. It is
75
+ **not tested on Windows or macOS** — use on those platforms at your own risk.
76
+
77
+ ### Security model
78
+
79
+ - The micro VM isolates the *guest code* you run, but any **host tools you register via
80
+ `host_tools` run with full host privileges** inside the sandbox's `call_tool(...)`. Only
81
+ register callables you trust, and treat their inputs as untrusted.
82
+ - Network is off by default and gated by `allowed_domains`, but an allow-listed domain is
83
+ reachable by any code running in the sandbox.
84
+ - This package has **not** been security-reviewed. Do not treat it as a hardened sandbox
85
+ boundary without your own audit.
86
+
87
+ ### Maturity
88
+
89
+ - **Alpha / vibe-coded.** No fuzzing, no adversarial testing, no cross-platform CI matrix.
90
+ - The thread-confinement worker (required because the `WasmSandbox` is `unsendable` in PyO3)
91
+ is correct for the tested paths but has not been stress-tested under heavy concurrency.
92
+ - `host_tools` accepts plain Python callables only — it does not yet wrap LangChain
93
+ `BaseTool` instances directly.
94
+
95
+ ## Installation
96
+
97
+ > **Platform support:** this package is **tested on Linux (x86_64) only**. It is
98
+ > **not tested on Windows or macOS** — install and use on those platforms at your own risk.
99
+
100
+ ```shell
101
+ pip install langchain-hyperlight
102
+ ```
103
+
104
+ This pulls in `langchain-core` and `hyperlight-sandbox[wasm,python_guest]`.
105
+
106
+ > **Prerequisite:** a working hypervisor is required at *runtime* (not at install time):
107
+ >
108
+ > - **Linux:** KVM (`/dev/kvm`) or MSHV (`/dev/mshv`)
109
+
110
+ ## Quick start
111
+
112
+ ```python
113
+ from langchain_hyperlight import HyperlightSandboxTool
114
+
115
+ tool = HyperlightSandboxTool(
116
+ host_tools={
117
+ "add": lambda a=0, b=0: a + b,
118
+ "greet": lambda name="world": f"Hello, {name}!",
119
+ },
120
+ allowed_domains={"https://httpbin.org": ["GET"]},
121
+ )
122
+
123
+ result = tool.invoke({
124
+ "code": """
125
+ total = call_tool('add', a=3, b=4)
126
+ greeting = call_tool('greet', name='James')
127
+ print(f"3 + 4 = {total}")
128
+ print(greeting)
129
+ """,
130
+ })
131
+ print(result)
132
+ ```
133
+
134
+ ### Using it inside an agent
135
+
136
+ ```python
137
+ from langchain_core.tools import create_agent # or your agent of choice
138
+
139
+ agent = create_agent(model, tools=[tool])
140
+ ```
141
+
142
+ The tool is a standard `langchain_core.tools.BaseTool`, so it works with any LangChain agent
143
+ runtime (LangGraph, `create_agent`, `AgentExecutor`, etc.).
144
+
145
+ ## Relationship to Microsoft's Agent Framework
146
+
147
+ Microsoft ships an official Hyperlight integration for *its own* Agent Framework:
148
+ [`agent-framework-hyperlight`](https://github.com/microsoft/agent-framework/tree/main/python/packages/hyperlight)
149
+ (`HyperlightExecuteCodeTool` / `HyperlightCodeActProvider`). This package is the **LangChain**
150
+ equivalent: it targets `langchain_core.tools.BaseTool` and mirrors the same concepts — the
151
+ `execute_code` tool name, `file_mounts`, `allowed_domains`, and host-tool dispatch via
152
+ `call_tool(...)` — so the mental model transfers directly.
153
+
154
+ ### Thread safety
155
+
156
+ The Hyperlight `WasmSandbox` is `unsendable` in PyO3: it may only be accessed and dropped from
157
+ the OS thread that created it, or it panics. This tool routes every sandbox operation through a
158
+ dedicated single-threaded worker, so it is safe to call from arbitrary threads and event loops
159
+ (including LangChain's async `ainvoke`).
160
+
161
+ ## Guest environment
162
+
163
+ By default the sandbox runs **Python**. Inside the guest, these built-ins are available:
164
+
165
+ | Function | Purpose |
166
+ | --- | --- |
167
+ | `call_tool(name, **kwargs)` | Invoke a host-registered tool by name |
168
+ | `http_get(url)` / `http_post(url, body=...)` | HTTP to allow-listed domains only |
169
+ | `read_file(path)` / `write_file(path, data)` | Capability-based file I/O (`/input`, `/output`) |
170
+
171
+ ## Configuration
172
+
173
+ `HyperlightSandboxTool` forwards its constructor arguments to
174
+ [`hyperlight_sandbox.Sandbox`](https://github.com/hyperlight-dev/hyperlight-sandbox):
175
+
176
+ | Argument | Default | Description |
177
+ | --- | --- | --- |
178
+ | `backend` | `"wasm"` | `"wasm"` (Python/JS guest) or `"hyperlight-js"` |
179
+ | `module` | `"python_guest.path"` | Packaged guest module reference |
180
+ | `module_path` | `None` | Explicit path to a `.aot`/`.wasm` guest |
181
+ | `input_dir` / `output_dir` | `None` | Host directories mounted into the guest |
182
+ | `temp_output` | `False` | Use a temporary output directory |
183
+ | `heap_size` / `stack_size` | `None` | Guest memory limits (e.g. `"25Mi"`) |
184
+ | `host_tools` | `{}` | `{name: callable}` exposed to the guest |
185
+ | `allowed_domains` | `{}` | Network allow-list (see below) |
186
+ | `file_mounts` | `{}` | Host paths staged into the guest `/input` tree (see below) |
187
+
188
+ `allowed_domains` accepts a domain string, a `(target, methods)` tuple, an `AllowedDomain`, or a
189
+ sequence of any of these:
190
+
191
+ ```python
192
+ from langchain_hyperlight import AllowedDomain
193
+
194
+ tool = HyperlightSandboxTool(
195
+ allowed_domains=[
196
+ "api.github.com", # all methods
197
+ ("internal.example.com", "GET"), # GET only
198
+ AllowedDomain("https://httpbin.org", ("GET", "POST")),
199
+ ],
200
+ )
201
+ ```
202
+
203
+ `file_mounts` accepts a path string (same path on host and in the sandbox), a
204
+ `(host_path, mount_path)` tuple, a `FileMount`, or a sequence of any of these. Mounted files are
205
+ staged into a managed temporary `/input` tree and are readable in the guest via `read_file(...)`:
206
+
207
+ ```python
208
+ from langchain_hyperlight import FileMount
209
+
210
+ tool = HyperlightSandboxTool(
211
+ file_mounts=[
212
+ "/host/data", # -> /input/data
213
+ ("/host/models", "models"), # -> /input/models
214
+ FileMount("/host/config", "config"), # -> /input/config
215
+ ],
216
+ )
217
+ ```
218
+
219
+ The `create_hyperlight_tool()` factory is a thin convenience over the same constructor:
220
+
221
+ ```python
222
+ from langchain_hyperlight import create_hyperlight_tool
223
+
224
+ tool = create_hyperlight_tool(
225
+ host_tools={"add": lambda a=0, b=0: a + b},
226
+ allowed_domains=["api.github.com"],
227
+ )
228
+ ```
229
+
230
+ > **Note:** the tool always creates and owns its sandbox on a dedicated thread. Do not
231
+ > construct a `hyperlight_sandbox.Sandbox` yourself and try to share it across threads — the
232
+ > underlying `WasmSandbox` is `unsendable` and will panic if touched from a different thread
233
+ > than the one that created it. The tool manages this confinement for you.
234
+
235
+ ## Running on Bluefin / Fedora Silverblue (immutable)
236
+
237
+ Bluefin is an immutable Fedora (Silverblue) image. The package itself installs normally into a
238
+ virtual environment, but the **KVM hypervisor** must be available on the host:
239
+
240
+ 1. **Verify virtualization is enabled** in firmware (AMD-V / Intel VT-x):
241
+
242
+ ```shell
243
+ grep -E 'vmx|svm' /proc/cpuinfo
244
+ ```
245
+
246
+ 2. **Ensure the KVM device exists** (the `kvm_amd`/`kvm_intel` module is loaded):
247
+
248
+ ```shell
249
+ ls -l /dev/kvm
250
+ ```
251
+
252
+ If it is missing, the module is not loaded. On Bluefin this is usually a firmware/BIOS
253
+ setting (enable SVM/VT-x) rather than a package issue, since the kernel ships KVM.
254
+
255
+ 3. **Add your user to the `kvm` group** so you can open `/dev/kvm` without root:
256
+
257
+ ```shell
258
+ sudo usermod -aG kvm $USER
259
+ # log out and back in, then verify:
260
+ groups
261
+ ```
262
+
263
+ 4. **Install the package in a venv** (never layer Python packages system-wide on an immutable
264
+ image — use `uv`, `pipx`, or a `distrobox`/`toolbox` container):
265
+
266
+ ```shell
267
+ uv venv .venv
268
+ uv pip install --python .venv/bin/python langchain-hyperlight
269
+ ```
270
+
271
+ For a fully isolated dev environment, `distrobox` is the idiomatic Bluefin approach:
272
+
273
+ ```shell
274
+ distrobox create --name hyperlight-dev --image fedora:latest
275
+ distrobox enter hyperlight-dev
276
+ ```
277
+
278
+ ## Development
279
+
280
+ ```shell
281
+ uv venv .venv
282
+ uv pip install --python .venv/bin/python -e ".[dev]"
283
+ .venv/bin/pytest
284
+ ```
285
+
286
+ Tests that require a hypervisor are skipped automatically when `/dev/kvm` (or `/dev/mshv`) is
287
+ unavailable.
288
+
289
+ ## References
290
+
291
+ - [Hyperlight project site](https://hyperlight.org/) — official docs and getting-started guide
292
+ - [hyperlight-dev/hyperlight](https://github.com/hyperlight-dev/hyperlight) — the VMM itself
293
+ - [hyperlight-dev/hyperlight-sandbox](https://github.com/hyperlight-dev/hyperlight-sandbox) — the
294
+ multi-backend sandbox framework this tool wraps
295
+ - [hyperlight-dev/hyperlight-wasm](https://github.com/hyperlight-dev/hyperlight-wasm) — the Wasm
296
+ component backend
297
+ - [Microsoft Agent Framework Hyperlight integration](https://github.com/microsoft/agent-framework/tree/main/python/packages/hyperlight) —
298
+ the canonical `agent-framework-hyperlight` package this tool mirrors
299
+ - [Microsoft Learn: Hyperlight integration](https://learn.microsoft.com/en-us/agent-framework/integrations/hyperlight)
300
+ - [`hyperlight-sandbox` on PyPI](https://pypi.org/project/hyperlight-sandbox/)
301
+
302
+ ## License
303
+
304
+ Apache-2.0. Hyperlight is a [CNCF](https://cncf.io/) sandbox project.
@@ -0,0 +1,272 @@
1
+ > ⚠️ **VIBE-CODED — AI-GENERATED, NOT PRODUCTION-READY**
2
+ >
3
+ > This project was written by an AI ("vibe coded"). It is **experimental** and has had
4
+ > **no security review, fuzzing, or adversarial testing**. It has only been smoke-tested
5
+ > on **Linux (x86_64)**. **Use at your own risk** — do not rely on it for anything
6
+ > security-sensitive or mission-critical. See [Limitations](#limitations).
7
+
8
+ # langchain-hyperlight
9
+
10
+ A [LangChain](https://www.langchain.com/) tool that executes untrusted code inside a
11
+ [Microsoft Hyperlight](https://github.com/hyperlight-dev/hyperlight) **micro virtual machine**.
12
+
13
+ Hyperlight is a lightweight Virtual Machine Manager (VMM) designed to be embedded within
14
+ applications. It runs untrusted code in hardware-isolated micro VMs (KVM, MSHV, or Hyper-V)
15
+ with very low latency and minimal overhead. This package exposes that capability to LangChain
16
+ agents as a standard tool, so an LLM can safely run arbitrary code without touching the host.
17
+
18
+ ## Features
19
+
20
+ - **Hardware isolation** — code runs in a micro VM, not on the host.
21
+ - **Host tool dispatch** — register host callables that guest code invokes by name with
22
+ schema-validated arguments (`call_tool(...)`).
23
+ - **Capability-based file access** — read-only `/input`, writable `/output`, strict path isolation.
24
+ - **Network allow-listing** — network is off by default; opt in per-domain and per-HTTP-verb.
25
+ - **Snapshot / restore** — capture and rewind sandbox state.
26
+ - **Lazy sandbox creation** — constructing the tool is cheap; the micro VM boots on first use.
27
+
28
+ ## Limitations
29
+
30
+ This is an early-stage, AI-generated integration. Be aware of the following before adopting it.
31
+
32
+ ### Platform
33
+
34
+ - **x86_64 only.** Hyperlight currently targets x86_64; there are no `aarch64` (ARM) wheels.
35
+ Raspberry Pi, Apple Silicon, and AWS Graviton are unsupported.
36
+ - **glibc 2.34+.** The Rust backend ships `manylinux_2_34_x86_64` wheels, so it needs a recent
37
+ glibc. Works on Ubuntu 22.04+, Debian 12+, Fedora 36+, RHEL 9+. Does **not** work on
38
+ Ubuntu 20.04, Debian 11, RHEL 8, or musl-based distros (Alpine, Void) without building the
39
+ Rust backend from source.
40
+ - **Python 3.10–3.14.**
41
+ - **A hypervisor is required at runtime:** KVM (`/dev/kvm`) or MSHV on Linux.
42
+ - **Tested on Linux only.** This package has only been tested on **Linux (x86_64)**. It is
43
+ **not tested on Windows or macOS** — use on those platforms at your own risk.
44
+
45
+ ### Security model
46
+
47
+ - The micro VM isolates the *guest code* you run, but any **host tools you register via
48
+ `host_tools` run with full host privileges** inside the sandbox's `call_tool(...)`. Only
49
+ register callables you trust, and treat their inputs as untrusted.
50
+ - Network is off by default and gated by `allowed_domains`, but an allow-listed domain is
51
+ reachable by any code running in the sandbox.
52
+ - This package has **not** been security-reviewed. Do not treat it as a hardened sandbox
53
+ boundary without your own audit.
54
+
55
+ ### Maturity
56
+
57
+ - **Alpha / vibe-coded.** No fuzzing, no adversarial testing, no cross-platform CI matrix.
58
+ - The thread-confinement worker (required because the `WasmSandbox` is `unsendable` in PyO3)
59
+ is correct for the tested paths but has not been stress-tested under heavy concurrency.
60
+ - `host_tools` accepts plain Python callables only — it does not yet wrap LangChain
61
+ `BaseTool` instances directly.
62
+
63
+ ## Installation
64
+
65
+ > **Platform support:** this package is **tested on Linux (x86_64) only**. It is
66
+ > **not tested on Windows or macOS** — install and use on those platforms at your own risk.
67
+
68
+ ```shell
69
+ pip install langchain-hyperlight
70
+ ```
71
+
72
+ This pulls in `langchain-core` and `hyperlight-sandbox[wasm,python_guest]`.
73
+
74
+ > **Prerequisite:** a working hypervisor is required at *runtime* (not at install time):
75
+ >
76
+ > - **Linux:** KVM (`/dev/kvm`) or MSHV (`/dev/mshv`)
77
+
78
+ ## Quick start
79
+
80
+ ```python
81
+ from langchain_hyperlight import HyperlightSandboxTool
82
+
83
+ tool = HyperlightSandboxTool(
84
+ host_tools={
85
+ "add": lambda a=0, b=0: a + b,
86
+ "greet": lambda name="world": f"Hello, {name}!",
87
+ },
88
+ allowed_domains={"https://httpbin.org": ["GET"]},
89
+ )
90
+
91
+ result = tool.invoke({
92
+ "code": """
93
+ total = call_tool('add', a=3, b=4)
94
+ greeting = call_tool('greet', name='James')
95
+ print(f"3 + 4 = {total}")
96
+ print(greeting)
97
+ """,
98
+ })
99
+ print(result)
100
+ ```
101
+
102
+ ### Using it inside an agent
103
+
104
+ ```python
105
+ from langchain_core.tools import create_agent # or your agent of choice
106
+
107
+ agent = create_agent(model, tools=[tool])
108
+ ```
109
+
110
+ The tool is a standard `langchain_core.tools.BaseTool`, so it works with any LangChain agent
111
+ runtime (LangGraph, `create_agent`, `AgentExecutor`, etc.).
112
+
113
+ ## Relationship to Microsoft's Agent Framework
114
+
115
+ Microsoft ships an official Hyperlight integration for *its own* Agent Framework:
116
+ [`agent-framework-hyperlight`](https://github.com/microsoft/agent-framework/tree/main/python/packages/hyperlight)
117
+ (`HyperlightExecuteCodeTool` / `HyperlightCodeActProvider`). This package is the **LangChain**
118
+ equivalent: it targets `langchain_core.tools.BaseTool` and mirrors the same concepts — the
119
+ `execute_code` tool name, `file_mounts`, `allowed_domains`, and host-tool dispatch via
120
+ `call_tool(...)` — so the mental model transfers directly.
121
+
122
+ ### Thread safety
123
+
124
+ The Hyperlight `WasmSandbox` is `unsendable` in PyO3: it may only be accessed and dropped from
125
+ the OS thread that created it, or it panics. This tool routes every sandbox operation through a
126
+ dedicated single-threaded worker, so it is safe to call from arbitrary threads and event loops
127
+ (including LangChain's async `ainvoke`).
128
+
129
+ ## Guest environment
130
+
131
+ By default the sandbox runs **Python**. Inside the guest, these built-ins are available:
132
+
133
+ | Function | Purpose |
134
+ | --- | --- |
135
+ | `call_tool(name, **kwargs)` | Invoke a host-registered tool by name |
136
+ | `http_get(url)` / `http_post(url, body=...)` | HTTP to allow-listed domains only |
137
+ | `read_file(path)` / `write_file(path, data)` | Capability-based file I/O (`/input`, `/output`) |
138
+
139
+ ## Configuration
140
+
141
+ `HyperlightSandboxTool` forwards its constructor arguments to
142
+ [`hyperlight_sandbox.Sandbox`](https://github.com/hyperlight-dev/hyperlight-sandbox):
143
+
144
+ | Argument | Default | Description |
145
+ | --- | --- | --- |
146
+ | `backend` | `"wasm"` | `"wasm"` (Python/JS guest) or `"hyperlight-js"` |
147
+ | `module` | `"python_guest.path"` | Packaged guest module reference |
148
+ | `module_path` | `None` | Explicit path to a `.aot`/`.wasm` guest |
149
+ | `input_dir` / `output_dir` | `None` | Host directories mounted into the guest |
150
+ | `temp_output` | `False` | Use a temporary output directory |
151
+ | `heap_size` / `stack_size` | `None` | Guest memory limits (e.g. `"25Mi"`) |
152
+ | `host_tools` | `{}` | `{name: callable}` exposed to the guest |
153
+ | `allowed_domains` | `{}` | Network allow-list (see below) |
154
+ | `file_mounts` | `{}` | Host paths staged into the guest `/input` tree (see below) |
155
+
156
+ `allowed_domains` accepts a domain string, a `(target, methods)` tuple, an `AllowedDomain`, or a
157
+ sequence of any of these:
158
+
159
+ ```python
160
+ from langchain_hyperlight import AllowedDomain
161
+
162
+ tool = HyperlightSandboxTool(
163
+ allowed_domains=[
164
+ "api.github.com", # all methods
165
+ ("internal.example.com", "GET"), # GET only
166
+ AllowedDomain("https://httpbin.org", ("GET", "POST")),
167
+ ],
168
+ )
169
+ ```
170
+
171
+ `file_mounts` accepts a path string (same path on host and in the sandbox), a
172
+ `(host_path, mount_path)` tuple, a `FileMount`, or a sequence of any of these. Mounted files are
173
+ staged into a managed temporary `/input` tree and are readable in the guest via `read_file(...)`:
174
+
175
+ ```python
176
+ from langchain_hyperlight import FileMount
177
+
178
+ tool = HyperlightSandboxTool(
179
+ file_mounts=[
180
+ "/host/data", # -> /input/data
181
+ ("/host/models", "models"), # -> /input/models
182
+ FileMount("/host/config", "config"), # -> /input/config
183
+ ],
184
+ )
185
+ ```
186
+
187
+ The `create_hyperlight_tool()` factory is a thin convenience over the same constructor:
188
+
189
+ ```python
190
+ from langchain_hyperlight import create_hyperlight_tool
191
+
192
+ tool = create_hyperlight_tool(
193
+ host_tools={"add": lambda a=0, b=0: a + b},
194
+ allowed_domains=["api.github.com"],
195
+ )
196
+ ```
197
+
198
+ > **Note:** the tool always creates and owns its sandbox on a dedicated thread. Do not
199
+ > construct a `hyperlight_sandbox.Sandbox` yourself and try to share it across threads — the
200
+ > underlying `WasmSandbox` is `unsendable` and will panic if touched from a different thread
201
+ > than the one that created it. The tool manages this confinement for you.
202
+
203
+ ## Running on Bluefin / Fedora Silverblue (immutable)
204
+
205
+ Bluefin is an immutable Fedora (Silverblue) image. The package itself installs normally into a
206
+ virtual environment, but the **KVM hypervisor** must be available on the host:
207
+
208
+ 1. **Verify virtualization is enabled** in firmware (AMD-V / Intel VT-x):
209
+
210
+ ```shell
211
+ grep -E 'vmx|svm' /proc/cpuinfo
212
+ ```
213
+
214
+ 2. **Ensure the KVM device exists** (the `kvm_amd`/`kvm_intel` module is loaded):
215
+
216
+ ```shell
217
+ ls -l /dev/kvm
218
+ ```
219
+
220
+ If it is missing, the module is not loaded. On Bluefin this is usually a firmware/BIOS
221
+ setting (enable SVM/VT-x) rather than a package issue, since the kernel ships KVM.
222
+
223
+ 3. **Add your user to the `kvm` group** so you can open `/dev/kvm` without root:
224
+
225
+ ```shell
226
+ sudo usermod -aG kvm $USER
227
+ # log out and back in, then verify:
228
+ groups
229
+ ```
230
+
231
+ 4. **Install the package in a venv** (never layer Python packages system-wide on an immutable
232
+ image — use `uv`, `pipx`, or a `distrobox`/`toolbox` container):
233
+
234
+ ```shell
235
+ uv venv .venv
236
+ uv pip install --python .venv/bin/python langchain-hyperlight
237
+ ```
238
+
239
+ For a fully isolated dev environment, `distrobox` is the idiomatic Bluefin approach:
240
+
241
+ ```shell
242
+ distrobox create --name hyperlight-dev --image fedora:latest
243
+ distrobox enter hyperlight-dev
244
+ ```
245
+
246
+ ## Development
247
+
248
+ ```shell
249
+ uv venv .venv
250
+ uv pip install --python .venv/bin/python -e ".[dev]"
251
+ .venv/bin/pytest
252
+ ```
253
+
254
+ Tests that require a hypervisor are skipped automatically when `/dev/kvm` (or `/dev/mshv`) is
255
+ unavailable.
256
+
257
+ ## References
258
+
259
+ - [Hyperlight project site](https://hyperlight.org/) — official docs and getting-started guide
260
+ - [hyperlight-dev/hyperlight](https://github.com/hyperlight-dev/hyperlight) — the VMM itself
261
+ - [hyperlight-dev/hyperlight-sandbox](https://github.com/hyperlight-dev/hyperlight-sandbox) — the
262
+ multi-backend sandbox framework this tool wraps
263
+ - [hyperlight-dev/hyperlight-wasm](https://github.com/hyperlight-dev/hyperlight-wasm) — the Wasm
264
+ component backend
265
+ - [Microsoft Agent Framework Hyperlight integration](https://github.com/microsoft/agent-framework/tree/main/python/packages/hyperlight) —
266
+ the canonical `agent-framework-hyperlight` package this tool mirrors
267
+ - [Microsoft Learn: Hyperlight integration](https://learn.microsoft.com/en-us/agent-framework/integrations/hyperlight)
268
+ - [`hyperlight-sandbox` on PyPI](https://pypi.org/project/hyperlight-sandbox/)
269
+
270
+ ## License
271
+
272
+ Apache-2.0. Hyperlight is a [CNCF](https://cncf.io/) sandbox project.
@@ -0,0 +1,66 @@
1
+ """End-to-end example: a LangChain agent using the Hyperlight sandbox tool.
2
+
3
+ Requires a working hypervisor (KVM / MSHV) on Linux. See the README for setup.
4
+
5
+ Run with:
6
+ uv run examples/basic_agent.py
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from langchain_hyperlight import HyperlightSandboxTool
12
+
13
+
14
+ def main() -> None:
15
+ """Run the end-to-end demo: execution, tool dispatch, and snapshot/restore."""
16
+ # Register host capabilities that the guest may call by name.
17
+ tool = HyperlightSandboxTool(
18
+ host_tools={
19
+ "add": lambda a=0, b=0: a + b,
20
+ "multiply": lambda a=0, b=0: a * b,
21
+ "greet": lambda name="world": f"Hello, {name}!",
22
+ },
23
+ allowed_domains={"https://httpbin.org": ["GET"]},
24
+ )
25
+
26
+ # 1. Basic execution
27
+ result = tool.invoke({"code": 'print("hello from a micro VM!")'})
28
+ print("--- basic execution ---")
29
+ print(result)
30
+
31
+ # 2. Host tool dispatch
32
+ result = tool.invoke(
33
+ {
34
+ "code": """
35
+ total = call_tool('add', a=3, b=4)
36
+ product = call_tool('multiply', a=6, b=7)
37
+ print(f"3 + 4 = {total}")
38
+ print(f"6 * 7 = {product}")
39
+ print(call_tool('greet', name='James'))
40
+ """
41
+ }
42
+ )
43
+ print("\n--- tool dispatch ---")
44
+ print(result)
45
+
46
+ # 3. Snapshot / restore
47
+ tool.invoke({"code": "x = 42; print(f'x = {x}')"})
48
+ tool.snapshot()
49
+ tool.invoke({"code": "x = 99"})
50
+ tool.restore()
51
+ result = tool.invoke(
52
+ {
53
+ "code": """
54
+ try:
55
+ print(f"x = {x}")
56
+ except NameError:
57
+ print("x is not defined (state was rolled back)")
58
+ """
59
+ }
60
+ )
61
+ print("\n--- snapshot / restore ---")
62
+ print(result)
63
+
64
+
65
+ if __name__ == "__main__":
66
+ main()