/ home / posts / Bringing Hermes to WebAssembly

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).

graph LR subgraph outer[" "] direction LR subgraph inner["More tools + use computer"] A["Coding agent"] end inner -->|"Same as"| B["General-purpose agent"] end style A fill:#1a1a2e,stroke:#58a6ff,stroke-width:2px,color:#c9d1d9 style inner fill:#161b22,stroke:#58a6ff,stroke-width:1px,color:#8b949e style B fill:#238636,stroke:#2ea043,stroke-width:2px,color:#ffffff style outer fill:none,stroke:none

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

graph LR subgraph outer[" "] direction LR subgraph pyodide["Pyodide"] A["Hermes agent"] end subgraph browser["Web browser"] W["WebAssembly"] end pyodide --> W end style A fill:#1a1a2e,stroke:#58a6ff,stroke-width:2px,color:#c9d1d9 style pyodide fill:#161b22,stroke:#58a6ff,stroke-width:1px,color:#8b949e style W fill:#1a1a2e,stroke:#f0883e,stroke-width:2px,color:#c9d1d9 style browser fill:#161b22,stroke:#f0883e,stroke-width:1px,color:#8b949e style outer fill:none,stroke:none

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:

graph LR subgraph outer[" "] direction LR subgraph buildroot["Linux VM created with Buildroot"] P["Postgres"] end subgraph browser2["Web browser"] W2["WebAssembly"] end buildroot --> W2 end style P fill:#1a1a2e,stroke:#58a6ff,stroke-width:2px,color:#c9d1d9 style buildroot fill:#161b22,stroke:#58a6ff,stroke-width:1px,color:#8b949e style W2 fill:#1a1a2e,stroke:#f0883e,stroke-width:2px,color:#c9d1d9 style browser2 fill:#161b22,stroke:#f0883e,stroke-width:1px,color:#8b949e style outer fill:none,stroke:none

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:

graph LR A["Hermes"] --> B subgraph B["WASM"] B1["• Prompt
• 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!