ADR-0001 — WIT + WASM Component Model as the connector contract
- Status: Accepted
- Date: 2026-05-11
- Related specs: 02-connectors.md
Context
Section titled “Context”The connector contract is the load-bearing decision of the project. It determines:
- whether agents can reliably author connectors,
- whether user-authored code is safe to run inside the Hakiri runtime,
- whether connectors can ship out-of-band from the binary,
- whether the same connector code can run on a laptop, on a Cloudflare Worker, on Lambda, and on a Fargate task.
Three families of contract were on the table: a native Rust trait (built-in only), a Singer-style stdio JSONL subprocess (the Meltano ecosystem), and a WASM Component Model contract defined in WIT (WebAssembly Interface Types).
Decision
Section titled “Decision”All connectors — whether shipped in-tree or authored later — conform to a single WIT world. Built-in connectors are compiled as native Rust for speed but implement the same Rust trait that the WIT bindings generate, so the runtime treats every connector uniformly.
Agent-authored and third-party connectors compile to a .wasm Component and load into a wasmtime host pool. Host imports (HTTP, filesystem, logging, clocks) are explicit per-component capabilities the host grants individually — not ambient.
Consequences
Section titled “Consequences”Positive
- Real sandbox: no filesystem or network access by default. An agent-authored connector cannot exfiltrate secrets unless the operator grants the capability.
- Language-agnostic authoring: Rust, TinyGo, Python (componentize-py), JavaScript (jco) all target the same
.wasmartifact. - Portable runtime: the same
.wasmruns onwasmtime(server / laptop), on Cloudflare’s WASM stack (Worker/Container), and on any other Component Model host (Spin, wasmCloud). - Versioned contract: WIT has first-class semver on packages and worlds, so connector authors get a stable surface.
- Hot-swappable: dropping a new
.wasminto the catalog does not require restarting the binary.
Negative
- Cold-start cost per component instantiation. Mitigated by pooling, but it is a real cost relative to a native trait call.
- Smaller off-the-shelf binding ecosystem than Python/Java HTTP libraries. We absorb this by shipping
hakiri-connector-sdkfor Rust authors with the common boilerplate. - WASM Component Model on
workerd(Cloudflare Workers’ runtime) is less mature than onwasmtime. In the Cloudflare topology, agent-authored connectors run in the Container, not directly in the Worker.
Neutral
- Native built-ins and WASM Components share one Rust trait, so the runtime has no “is this a WASM connector” branch in hot paths.
Alternatives considered
Section titled “Alternatives considered”Native Rust trait only. Lowest overhead, but locks out agent and non-Rust authoring and forces every connector through the main binary’s release cycle. Cuts the agent-first principle off at the knees.
Singer / Meltano stdio JSONL subprocess. Largest connector ecosystem. Rejected because Singer’s stdio JSONL pipeline has a documented throughput ceiling (tens of MB/s before serialization dominates), brittle state semantics (each tap reinvents cursor encoding), and no sandbox — a misbehaving tap can do anything its host user can. The contract is also too loose to give agents reliable authoring scaffolding.
Native plugin (.so / .dylib via libloading). Zero overhead but zero sandbox, zero portability, and an ABI compatibility nightmare across Rust versions. Non-starter for agent-authored code.