How the WebAssembly Component Integrates with Host Applications in Needle
Needle ships a pre-compiled WebAssembly component that exposes a WIT contract, enabling any WASI-Preview-2-compatible host to run the inference engine via a single run entry point without native dependencies.
The cactus-compute/needle repository distributes a WebAssembly component that packages the core inference engine as a portable, sandboxed binary. This integration method allows developers to embed Needle into applications written in Rust, Go, JavaScript, or any language supporting WebAssembly System Interface (WASI) components, bypassing the need for Python interpreters or platform-specific native libraries.
What Is the Needle WebAssembly Component?
The component consists of two artifacts published under the wasm-component platform tag: needle.component.wasm (the pre-compiled binary) and needle.wit (the interface contract). As documented in doc/apis.md (lines 179-188), these files collectively define a WASI Preview 2 component that exports a typed interface for host applications to instantiate and call.
The contract exposes a single entry point—run—which accepts a JSON payload containing the prompt, tool schemas, and generation parameters, then returns a serialized JSON response. This design ensures that all inference logic executes inside the WebAssembly sandbox using the engine’s 14 MB binary and built-in grammar constraints.
Fetching the Component via the CLI
Before integration, retrieve the component using the official CLI. The command respects generation-specific versioning and outputs both the binary and contract files:
needle download wasm-component --generation 2 --out .
Internally, the needle/agent/fetch.py module registers "wasm-component" as a supported platform (lines 22-23), enabling the downloader to resolve the correct artifact from the repository’s release assets. The resulting needle.component.wasm and needle.wit files provide everything needed to instantiate the engine in a compatible host runtime.
WIT Contract and Interface Design
The WebAssembly Interface Types (WIT) contract defines a language-agnostic boundary between the host and the guest. Host generators like wit-bindgen consume needle.wit to produce idiomatic bindings for the target language.
The interface guarantees type-safe exchange of complex data through a single function signature resembling:
run: func(request: string) -> string
Where the input string is a JSON object containing:
prompt: The text prompt for the modeltools: Optional array of tool schemas for function callinggeneration: Integer specifying the engine generation (e.g., 2)
The return value is a JSON string containing the model output and any tool-call results, mirroring the Python API’s agent.run behavior but executing entirely within the WASM sandbox.
Loading the Component in Host Runtimes
Any WASI-Preview-2-compliant runtime—including Wasmtime, Wasmer, or browser-based implementations—can load the component. The host must link standard WASI imports (e.g., fd_write, fd_read) during instantiation, after which the exported run function becomes callable like a native method.
Integrating from Python via wasmtime-py
The following example demonstrates loading the component using the wasmtime Python bindings, generated from the WIT contract:
import json
import wasmtime
# Initialize the Wasmtime engine and store
engine = wasmtime.Engine()
store = wasmtime.Store(engine)
# Import bindings generated from needle.wit (e.g., via wit-bindgen)
import needle_wit
# Load the component binary
component = wasmtime.Component.from_file(store.engine, "needle.component.wasm")
instance = needle_wit.NeedleComponent(store, component)
# Prepare the request payload
payload = {
"prompt": "What is the weather in Paris?",
"tools": [],
"generation": 2,
}
request = json.dumps(payload)
# Execute inference inside the WASM sandbox
response_json = instance.run(request)
response = json.loads(response_json)
print(response["results"])
This pattern replicates the high-level Python API while executing the inference engine inside the WebAssembly sandbox.
Integrating from JavaScript (Node.js)
For Node.js environments using Wasmer or similar runtimes, the component loads asynchronously with generated JavaScript bindings:
import { Component } from "@wasmer/wasi";
import fs from "fs";
import { NeedleComponent } from "./needle_wit.js";
// Read the component binary
const bytes = fs.readFileSync("needle.component.wasm");
const component = await Component.fromBytes(bytes);
// Instantiate with WASI imports linked
const needle = await NeedleComponent.instantiate(component);
// Build and send the request
const request = JSON.stringify({
prompt: "Summarize the latest news about AI.",
tools: [],
generation: 2,
});
const response = await needle.run(request);
console.log(JSON.parse(response).results);
Both examples follow the identical flow: deserialize the request to JSON, pass it to the run export, and parse the JSON response.
Integration Architecture and Execution Flow
The complete integration follows a predictable five-step lifecycle:
- Fetch – Download
needle.component.wasmandneedle.witusing the CLI or directly from release artifacts built by.github/workflows/publish-component.yaml. - Instantiate – The host runtime creates a component instance, linking WASI Preview 2 system calls for I/O.
- Call
run– Serialize the request (prompt + tool schemas) as JSON and invoke the exported function. - Engine Executes – The compiled Needle engine processes the request inside the sandbox, applying grammar constraints and tool-calling logic.
- Return – Deserialize the JSON response to obtain results identical to the native Python API.
Because the component adheres strictly to the WASI Preview 2 specification, it remains portable across any compliant host, from edge computing platforms to embedded devices.
Summary
- Needle distributes a WASI Preview 2 component (
needle.component.wasm) with a WIT contract (needle.wit) that defines a language-agnostic interface. - The
needle download wasm-componentcommand retrieves platform-specific artifacts, as implemented inneedle/agent/fetch.py. - Host applications instantiate the component using WASI-compatible runtimes (Wasmtime, Wasmer, etc.) and call the
runfunction with JSON payloads. - The integration requires no Python runtime or native dependencies, enabling deployment in Rust, Go, JavaScript, and other environments.
- All inference executes inside a sandboxed 14 MB WebAssembly binary, ensuring consistent behavior across host platforms.
Frequently Asked Questions
What is WASI Preview 2 and why does Needle use it?
WASI Preview 2 is the WebAssembly System Interface standard that defines modular, capability-based system APIs. Needle uses this specification because it guarantees that the component can run on any compliant runtime without modification, providing true portability across operating systems and host languages while maintaining a secure sandbox for inference execution.
Do I need Python installed to use the WebAssembly component?
No. The WebAssembly component is specifically designed for Python-free deployment. While the needle CLI requires Python to download the artifacts, the resulting needle.component.wasm file runs entirely within a WASI-compatible host runtime (e.g., Wasmtime or Wasmer) with no Python interpreter present.
How large is the Needle WebAssembly component?
The compiled component is approximately 14 MB, containing the complete inference engine and built-in grammar constraints. This size includes all necessary logic to execute inference and tool-calling without external dependencies or network calls during runtime.
Can I run Needle in a web browser using this component?
Yes, provided the browser environment supports WASI Preview 2 via polyfills or native implementations (such as those being developed for modern WebAssembly runtimes). The component architecture is browser-ready, though you must ensure the host JavaScript environment can provide the required WASI imports (filesystem, clocks) that the component expects.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →