May 06, 2026
What’s in this post?
We took Hermes Agent, developed by the folks at Nous Research, and brought it to WebAssembly in two different ways, detailed below, and share what our general takeaways from this experiment are.
Should I replace my Hermes with one of these?
Probably not. If doing things with Python in WebAssembly is of interest to you, then continue reading!
Where did Hermes come from?
Having taken the world by storm, OpenClaw is an AI assistant which uses the computer you run it on similarly to a person (so it can do more than just recite Wikipedia articles). Following this, Hermes was written in Python on top of mini-swe-agent (unlike OpenClaw which is written in TypeScript on top of pi).
Both are “general-purpose agents” which are really batteries-included coding agents. The “magic” of their utility comes from the assembling of the “harness” the agent sits inside of when handling users’ prompts; which gives it the capability to do things like click around a browser or send an email.
Why WebAssembly?
I’m admittedly biased when it comes to WebAssembly but, having worked on multi-agent projects before, I was interested in seeing if WebAssembly would give a win with regard to isolation (ie spinning up multiple separate agents in parallel) or granular configurability (ie assembling agents precisely with certain tools for different “modes”).
Additionally, since Hermes is written in Python, I wanted to see if eagerly compiling to WebAssembly would offer closer-to-native performance.
How to WASM Hermes
Pyodide
Run Hermes in pyodide yourself
This app serves an index.html with the full agent running client-side in Pyodide. To run the below command, you may need to install the vers CLI first.
vers run-commit f46a2b21-73fe-4835-ad79-8eccd523fc07 \
--format json --wait \
| sed -n 's/.*"vm_id"[: ]*"\([^"]*\)".*/https:\/\/\1.vm.vers.sh/p'
Public Vers VM Commit: f46a2b21-73fe-4835-ad79-8eccd523fc07
How it works with Pyodide
The first approach is by using Pyodide, a Python runtime that’s ported to WebAssembly so Python programs can be interpreted and run in the browser. You can think of this as being similar to the approach that was taken with bringing Postgres to WebAssembly:
Postgres itself doesn’t get run in WebAssembly but instead a Linux emulator in WASM runs a modified version of Postgres so the whole thing can actually work together inside a browser.
Hermes in Pyodide source
You can view and modify the source code here: https://github.com/hdresearch/hermes-pyodide
pywasm
Run Hermes in pywasm yourself
This app serves the hermes_agent.wasm binary. Hit the “Run” button in the UI to execute it live.
vers run-commit f83df1ac-0a53-4ca6-bc26-205584fe65a3 \
--format json --wait \
| sed -n 's/.*"vm_id"[: ]*"\([^"]*\)".*/https:\/\/\1.vm.vers.sh/p'
Public Vers VM Commit: f83df1ac-0a53-4ca6-bc26-205584fe65a3
How it works with py2wasm
This second approach works by using py2wasm, a Python-to-WebAssembly compiler and the pywasm split design keeps the security boundary clean:
• Loop
• Context
• Local tools"] end B -->|"JSON in/out"| C subgraph C["Host"] C1["• Calling API
• Tool dispatch
• API keys"] end
The host extracts real schemas from the Hermes’ ToolRegistry at startup before sending them to the WASM binary via init protocol. The LLM always sees the same parameter names as the actual handlers (ie path instead of file_path or old_string instead old_text).
Hermes in pywasm source
You can view and modify the soure code yourself here: https://github.com/hdresearch/hermes-pywasm
Benchmarks
Below are benchmarks obtained from running on a M4 macbook. As admitted earlier, this probably won’t meaningfully replace running Hermes on your laptop. However, if porting the harness itself to alternative environments (ie a browser) is of interest to you, then you can see some of the tradeoffs between pyodide and py2wasm.
| Metric | Native Python | Pyodide (browser) | pywasm (WASI) |
|---|---|---|---|
| Cold start | 750 ms | 2–5 s | 110 ms |
| Single turn | 840 ms | ~850 ms | 100 ms |
| 20-turn conversation | 3,280 ms | ~3,300 ms | 110 ms |
| 50 parallel agents | 4,566 ms | N/A (browser) | 611 ms (wasmtime) |
| Worker pool throughput | 9 q/s | N/A (browser) | 81 q/s (wasmtime) |
| Deployment size | 733 MB | ~20 MB + packages | 26 MB |
| Pip packages | 171 | 171 (via Pyodide) | 0 |
| Runs in browser | ❌ | ✅ | ⚠️ needs WASI polyfill |
| API key exposure | server-side | client-side | Stored in host |
Takeaways
While the founder of Docker years ago suggested WASM+WASI was the missing sandboxing solution, it’s evidently not a magic bullet considering the missing capabilities from a full-fledged computer or container. If having a full but branchable VM with incredibly fast startup times sounds like what you’re looking for, then go on over to Vers and get started!