Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

94 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Wruntime

Note

This project was an experiment in LLM-assisted development. Much of the code in this repo was written with Claude.

A distributed runtime that networks WASM modules via transparent HTTP interception. Modules make ordinary HTTP calls to each other β€” Wruntime intercepts, routes, and delivers them automatically.

                                 β‘   http://example.echo/echo.EchoService/Echo  
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   caller   β”‚ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─►   β”‚    echo    β”‚
β”‚   (WASM)   β”‚        (appears direct)        β”‚   (WASM)   β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                                β””β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”˜
       β”‚                                             β”‚
       β”‚ β‘‘ intercepted                   β‘£ routed   β”‚
       β”‚                                             β”‚
       β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚
       └────────►│    wr-proxy     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚                 β”‚
                 β”‚  routes         β”‚
                 β”‚  load-balances  β”‚
                 β”‚  streams        β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚ β‘’ syncs
                   β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
                   β”‚  wr-manager β”‚
                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Modules address each other using http://{namespace}.{module}/{proto_package}.{ProtoServiceName}/{ProtoMethodName} URLs. The runtime handles service discovery, version routing, circuit-breaker-aware load balancing across instances, and OpenTelemetry tracing β€” all transparent to the module code. Request and response bodies are streamed through the proxy with zero buffering.

Quick start: Echo service

Two WASM modules β€” echo returns whatever it receives, caller sends a message to echo and prints the result.

1. Define the schema

// schemas/echo.proto
syntax = "proto3";
package echo;

service EchoService {
  rpc Echo (EchoRequest) returns (EchoResponse);
}

message EchoRequest  { string message = 1; }
message EchoResponse { string message = 1; }

Compile it:

protoc --descriptor_set_out=schemas/echo.binpb --include_imports echo.proto

2. Echo module (handler)

build.rs:

fn main() {
    prost_build::Config::new()
        .service_generator(Box::new(wr_build::WrServiceGenerator))
        .compile_protos(&["schemas/echo.proto"], &["schemas"])
        .unwrap();
}

src/lib.rs:

mod proto { include!(concat!(env!("OUT_DIR"), "/echo.rs")); }

// The complete local world is shown in docs/agents/guest-module-author/module_template.md.
#[allow(dead_code, unused_imports)]
mod bindings {
    wit_bindgen::generate!({ path: "wit", world: "echo", generate_all });
}

use wr_sdk::prelude::*;

struct Component;
wr_sdk::export!(Component with_types_in wr_sdk::bindings);

impl ServiceGuest for Component {
    fn handle(request: IncomingRequest, response_out: ResponseOutparam) {
        proto::echo_service_handle(&Component, request, response_out);
    }
}

impl proto::EchoService for Component {
    fn echo(&self, req: proto::EchoRequest) -> Result<proto::EchoResponse, ServiceError> {
        Ok(proto::EchoResponse { message: req.message })
    }
}

WrServiceGenerator generates a trait (EchoService) and a _handle function (echo_service_handle) from the proto definition β€” you implement the trait and delegate handle to the generated function.

3. Caller module (runner)

build.rs:

fn main() {
    prost_build::Config::new()
        .service_generator(Box::new(wr_build::WrClientGenerator))
        .compile_protos(&["schemas/echo.proto"], &["schemas"])
        .unwrap();
}

src/lib.rs:

mod proto { include!(concat!(env!("OUT_DIR"), "/echo.rs")); }

// The complete local world is shown in docs/agents/guest-module-author/module_template.md.
#[allow(dead_code, unused_imports)]
mod bindings {
    wit_bindgen::generate!({ path: "wit", world: "caller", generate_all });
}

use prost::Message;
use proto::EchoServiceClient;
use wr_sdk::prelude::*;

struct Component;
wr_sdk::export!(Component with_types_in wr_sdk::bindings);

impl ServiceGuest for Component {
    fn handle(request: IncomingRequest, response_out: ResponseOutparam) {
        let client = EchoServiceClient::new("example.echo");

        match client.echo(proto::EchoRequest { message: "hello".into() }) {
            Ok(resp) => send_response(response_out, 200, resp.encode_to_vec()),
            Err(e)   => wr_sdk::log!("error: {e}"),
        }
    }
}

WrClientGenerator generates a typed EchoServiceClient struct with one method per RPC. The client calls http://example.echo/echo.EchoService/Echo under the hood via wr_sdk::http::http_request.

4. Configure and run

engine.toml:

listen_address = "127.0.0.1:9100"

[node]
proxy_address   = "http://127.0.0.1:9001"
control_address = "http://127.0.0.1:9002"
peer_port       = 9443

[node.tls]
cert_path    = "certs/127.0.0.1.crt"
key_path     = "certs/127.0.0.1.key"
ca_cert_path = "certs/ca.crt"

[[module]]
name        = "echo"
namespace   = "example"
version     = "1.0.0"
wasm_path   = "target/wasm32-wasip2/debug/echo.wasm"
schema_path = "schemas/echo.binpb"

[[module]]
name        = "caller"
namespace   = "example"
version     = "1.0.0"
wasm_path   = "target/wasm32-wasip2/debug/caller.wasm"
schema_path = "schemas/echo.binpb"
# Build the WASM components
cargo build --target wasm32-wasip2 -p echo
cargo build --target wasm32-wasip2 -p caller

# Start the services (in separate terminals, or background them)
just manager
just proxy
just engine ./engine.toml

# Invoke the caller through the proxy
wr-cli --manager http://127.0.0.1:9000 invoke --destination http://example.caller/run

Host bindings

WASM modules can access host-provided capabilities through WIT interfaces:

Binding WIT Preferred SDK surface Description
Database wit/db.wit wr_sdk::db builders and owned rows Parameterized SQL queries, transactions, and streaming against a shared Postgres pool
Blobstore wit/blobstore.wit wr_sdk::blobstore::bucket scoped handle S3-compatible object storage constrained to a host-configured bucket allowlist
Tracing wit/tracing.wit span!, set_attrs!, and event! Typed OpenTelemetry spans and batched attributes from within modules
LLM wit/llm.wit wr_sdk::llm::CompletionBuilder Validated Anthropic Claude completions, streaming, and tool use

Prefer these facades for application code. wr_sdk::bindings::wruntime::* exposes the raw WIT bindings as an intentional escape hatch for unsupported operations and protocol/negative tests.

See docs/host-bindings.md for configuration and usage examples.

Deployment

Bundle once, deploy anywhere β€” the CLI packages cross-compiled binaries, WASM modules, and configs into a single tarball that works with both systemd and Docker. Shared settings (target, db_url, format, etc.) can live in a wr-deploy.toml so commands stay short.

# Bundle a node (proxy + engine) β€” target defaults to x86_64-unknown-linux-gnu
wr-cli node bundle --engine-config engine.toml

# Deploy to a remote host via SSH (format defaults to systemd)
wr-cli node deploy wr-node-bundle.tar.gz deploy@10.0.1.50 \
    --db-url "postgres://postgres@10.0.1.1:5432/wruntime" \
    --manager http://10.0.1.1:9000

# Or with a wr-deploy.toml providing db_url, just the positional args:
wr-cli node deploy wr-node-bundle.tar.gz deploy@10.0.1.50 \
    --manager http://10.0.1.1:9000

Manager deployment follows the same pattern (wr managers bundle / wr managers deploy). See docs/deployment.md for the deploy config reference, multi-node cluster setup, bundle structure, and template variables.

Prerequisites

Tool Purpose
Rust + Cargo (stable) Build all binaries
just Run project recipes (see Justfile)
protoc Compile .proto schemas to FileDescriptorSet binaries
wasm32-wasip2 target rustup target add wasm32-wasip2 β€” build WASM component modules
wasm-tools Strip/inspect WASM components (install: cargo install --locked wasm-tools)
just build               # debug build
just build-release       # release build
just dev-up              # start Postgres/RustFS for integration tests and examples
just multi-node          # run two local proxy nodes and three engines
just test                # all tests with test DB/S3 env vars set
just test-wasm           # WASM host binding tests
just validate-ecommerce  # ecommerce inline run with zero-warning enforcement

Project layout

wruntime/
β”œβ”€β”€ proto/
β”‚   └── wruntime.proto      # single source of truth for all gRPC messages
β”œβ”€β”€ wr-common/              # generated proto types (tonic + prost); shared NodeConfig
β”œβ”€β”€ wr-manager/             # central registry gRPC server
β”œβ”€β”€ wr-proxy/               # streaming HTTP routing proxy
β”œβ”€β”€ wr-engine/              # WASM runtime (wasmtime) + inbound HTTP server
β”œβ”€β”€ wr-sdk/                 # WASM module SDK: http, io, db, tracing, llm, export macros
β”œβ”€β”€ wr-build/               # build.rs helper: service/client generators from proto
β”œβ”€β”€ wr-cli/                 # CLI: invoke modules, list engines/services, query metrics (requires --manager or WR_MANAGER)
β”œβ”€β”€ wr-tests/               # integration tests
β”œβ”€β”€ wit/                    # WIT interfaces (db, blobstore, tracing, llm)
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ config/             # example single-node configs
β”‚   β”œβ”€β”€ ecommerce/          # example: inventory (handler) + client (runner)
β”‚   β”œβ”€β”€ codegen/            # example: LLM agent sandbox (code generation)
β”‚   β”œβ”€β”€ stockmarket/        # example: multi-module trading system
β”‚   └── multi-node/         # local and deployment multi-node topology

Documentation

  • Agent guide β€” choose guest module author or wruntime maintainer mode
  • Architecture β€” detailed system diagram, request flow, internal headers
  • Configuration β€” manager, proxy, and engine TOML configs; health checks; routing rules; multi-node setup
  • gRPC API β€” ManagerService and NodeService RPC reference, worker job queue API
  • Protobuf Schemas β€” writing, compiling, and validation behavior
  • Module SDK β€” wr-sdk + wr-build reference; handler and runner module guides
  • Host Bindings β€” database, blobstore, tracing, LLM, and filesystem access
  • Deployment β€” bundle, deploy, multi-node clusters, systemd and Docker
  • Testing β€” running integration tests

About

WASM + WASI runtime for sandboxed code execution

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages