v3/implementation/adrs/ADR-059-rvagent-wasm-integration.md
Status: Implemented (see ADR-070 for completion details) Date: 2026-03-17 Author: RuvNet
Ruflo v3 already integrates four @ruvector/* WASM packages for intelligence
(learning-wasm, attention, router, sona). A new package —
@ruvector/[email protected] — provides a complete sandboxed AI agent runtime
compiled to WebAssembly. It includes:
Package size: 196.8 kB packed / 620 kB unpacked, zero runtime dependencies.
A companion package — @ruvector/ruvllm-wasm — provides browser-native LLM
inference with HNSW routing, MicroLoRA, SONA Instant, WebGPU acceleration, and
pi-quantization. This ADR covers both integrations.
Integrate @ruvector/rvagent-wasm as an optional dependency in @claude-flow/cli,
following the established pattern used by @ruvector/learning-wasm et al.
| Layer | What | How |
|---|---|---|
| package.json | Optional deps | "@ruvector/rvagent-wasm": "^0.1.0", "@ruvector/ruvllm-wasm": "^2.0.1" |
| Ambient types | TypeScript compat | src/types/optional-modules.d.ts |
| Integration module | src/ruvector/agent-wasm.ts | Agent lifecycle, VFS, gallery, RVF, MCP bridge |
| MCP tools | src/mcp-tools/wasm-agent-tools.ts | 10 tools exposed via MCP protocol |
| Re-exports | src/ruvector/index.ts | Public API surface |
| Tool | Description |
|---|---|
wasm_agent_create | Create sandboxed WASM agent |
wasm_agent_prompt | Send prompt to WASM agent |
wasm_agent_tool | Execute tool on WASM agent |
wasm_agent_list | List active WASM agents |
wasm_agent_terminate | Terminate and free agent |
wasm_agent_files | List files in agent's VFS |
wasm_agent_export | Export agent state as JSON |
wasm_gallery_list | List gallery templates |
wasm_gallery_search | Search templates by query |
wasm_gallery_create | Create agent from template |
Package published to npm and live-tested on 2026-03-17. Ambient types declared in
src/types/optional-modules.d.ts. Integration module and MCP tools pending.
| Component | API | Status |
|---|---|---|
RuvLLMWasm | initialize(), reset(), version(), getPoolStats() | Working |
ChatTemplateWasm | .llama3(), .mistral(), .chatml(), .phi(), .gemma(), .custom(), .detectFromModelId() | Working |
ChatMessageWasm | .system(), .user(), .assistant() | Working |
GenerateConfig | maxTokens, temperature, topP, topK, repetitionPenalty, toJson(), fromJson() | Working |
SonaInstantWasm | instantAdapt(), recordPattern(), suggestAction(), stats(), toJson(), fromJson() | Working |
MicroLoraWasm | adapt(), applyUpdates(), stats(), reset() (via MicroLoraConfigWasm + AdaptFeedbackWasm) | Working |
KvCacheWasm | append(), stats(), clear(), tokenCount | Working |
BufferPoolWasm | withCapacity(), prewarmAll(), statsJson(), hitRate, clear() | Working |
InferenceArenaWasm | forModel(), reset(), used, capacity, remaining | Working |
HnswRouterWasm | Constructor, setEfSearch(), clear() | Working |
HnswRouterWasm | addPattern() | Fixed in v2.0.1 |
import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const wasmPath = require.resolve('@ruvector/ruvllm-wasm/ruvllm_wasm_bg.wasm');
const bytes = readFileSync(wasmPath);
// MUST use object form — initSync(bytes) is deprecated
initSync({ module: bytes });
The select_layer() function in WASM called f64::ln() which hits unreachable
in WASM targets. Fix: replaced wasm_random() with integer-based geometric
distribution that avoids floating-point logarithms entirely. Published as v2.0.1.
src/ruvector/ruvllm-wasm.ts will expose:
isRuvllmWasmAvailable() — Runtime detectioninitRuvllmWasm() — Node.js WASM initializationcreateHnswRouter() — WASM HNSW for semantic routingcreateSonaInstant() — <1ms adaptation loopscreateMicroLora() — Ultra-lightweight LoRA (ranks 1-4)formatChat() — Chat template formattingcreateKvCache() — KV cache management┌──────────────────────────────────────────────────────────┐
│ @claude-flow/cli │
│ │
│ src/ruvector/agent-wasm.ts ◄── Integration module │
│ ├─ createWasmAgent() (lifecycle) │
│ ├─ promptWasmAgent() (LLM interaction) │
│ ├─ createWasmMcpServer() (MCP bridge) │
│ ├─ listGalleryTemplates() (gallery) │
│ └─ buildRvfContainer() (packaging) │
│ │
│ src/mcp-tools/wasm-agent-tools.ts ◄── MCP exposure │
│ │
├──────────────────────────────────────────────────────────┤
│ @ruvector/rvagent-wasm (WASM, optional) │
│ ├─ WasmAgent (sandboxed agent runtime) │
│ ├─ WasmStateBackend (in-memory VFS) │
│ ├─ WasmMcpServer (JSON-RPC 2.0) │
│ ├─ WasmGallery (6 templates) │
│ └─ WasmRvfBuilder (binary containers) │
└──────────────────────────────────────────────────────────┘
| Issue | Severity | Workaround |
|---|---|---|
execute_tool(unknown) → WASM panic | Medium | Validate tool name before calling (implemented) |
gallery.get(unknown) → WASM panic | Medium | Wrap in try/catch (implemented) |
WasmMcpServer → memory access out of bounds | High | Avoid MCP server in v0.1.0 |
reset() does not clear file_count | Low | Recreate agent if clean state needed |
write_todos format undocumented | Low | Tool works, format TBD |
Template ID is swarm-orchestrator not swarm | Info | Updated in code and docs |
| Issue | Severity | Workaround |
|---|---|---|
HNSW addPattern panics at ~12 patterns | High | Limit to <12 or await fix |
SonaInstantWasm requires SonaConfigWasm | Info | API change from earlier versions |
MicroLoraWasm.adapt() takes AdaptFeedbackWasm | Info | API change; .apply() for transforms |
RuvLLMWasm has no .version() | Info | Use standalone getVersion() |
GenerateConfig float precision loss | Low | f32 roundtrip (0.7 → 0.699999...) |
| Stats objects return WASM pointers | Low | Use .toJson() or named accessors |