The difficult part of a language-neutral plugin system is not starting another process. It is making every implementation agree about names, types, routing, streams, errors, and lifecycle.

Why cartridges are processes

Document and model tooling spans Rust, C++, Swift, Go, and Python ecosystems. Choosing one extension language would force cartridge authors either to abandon the best library for a job or to wrap it through another private protocol.

MachineFabric instead treats a cartridge as an executable. It reads standard input, writes standard output, and speaks Bifaci, a framed CBOR protocol with handshake, multiplexed streams, flow control, peer invocation, cancellation, errors, and keepalive. The host never loads cartridge code into the engine or UI process.

The current capdag new command scaffolds cartridge runtimes in Rust, Go, Swift, and Python. A JavaScript implementation participates in URN, notation, and planner behavior but deliberately has no cartridge runtime, host, or relay.

What CapDAG names

CapDAG is the typed addressing and composition layer above Bifaci. A cartridge advertises capabilities such as:

cap:disbind;in="media:document;ext=pdf";out="media:enc=utf-8;ext=txt;page;plain-text"
cap:describe-image;in="media:ext=png;image";out="media:enc=utf-8;image-description"
cap:in="media:enc=utf-8";out="media:enc=utf-8;plain-text";summarize

A Cap URN has four coordinates: input media, output media, non-directional operation/refinement tags, and effect. For a candidate to serve a request:

  • the request input must conform to what the candidate accepts (contravariance);
  • the candidate output must conform to what the request requires (covariance);
  • the candidate must satisfy the request’s explicit tag constraints; and
  • effects must agree unless the request explicitly leaves the effect open.

Omitting an effect means declared; categorical identity is the explicit cap:effect=none capability. The dispatch specification defines the predicate, and ranking defines selection among eligible candidates. In the matcher, equal specificity resolves by registration order; other ranking surfaces use their documented tie rules.

If no cartridge directly serves “summarize this PDF,” the planner searches the registered capability graph for a typed path: PDF to page text to summary. The graph is finite and fixed by registration. The result is Machine Notation that names every step, input, and output, so the route can be shown before execution. No language model chooses tools in this planning loop.

Some types can be refined only after inspecting a value. File adapters inspect bounded content to refine structural media tags; value adapters inspect strings such as model specifications to refine semantic tags. Both registries use the same longest-prefix, refine-or-pass-through shape, while differing in the value they inspect.

Model-family refinement matters because different families require different prompt templates. Treating a model specification as an unexamined string can route a request to an incompatible formatter and still produce plausible but incorrect text.

Five implementations, explicit boundaries

Rust is the behavioral reference. Go, Python, Swift/Objective-C, and JavaScript mirror the portions they implement, with shared numbered tests for shared behavior. JavaScript’s planner-only boundary is intentional. Runtime interoperability testing currently exercises Rust and Swift routers; Rust, Go, and Swift relay hosts; and Rust, Go, Python, and Swift cartridges. The repository tracks remaining protocol-v4 combinations explicitly rather than describing an unrun full matrix as complete.

The agreement that matters is semantic: the same normalized URN, dispatch request, or machine graph must have the same meaning wherever that feature is implemented. Threading and host structure may differ without changing the contract.

Local and remote capabilities

MachineFabric supplies platform-specific host isolation. On macOS, cartridges run below an XPC host and distributed packages use Apple code signing and notarization. Linux and Windows use their host daemons and package formats. The protocol also permits a cartridge to proxy a remote service. A pipeline may therefore combine local and remote transformations while preserving the same typed route and progress model; deployment policy determines where work runs.

Capabilities and media definitions are proposed through capfab. Cartridge packages are proposed through cartridge-shelf. Both are reviewed before they enter the published registries.

Start with Build your first cartridge, or read the CapDAG specification when you need the formal contract.