What a capability is
When you right-click a file and the Transmute menu shows what the file can become, each entry is reachable through one or more capabilities: typed operations a cartridge can perform on a typed input to produce a typed output.
A capability is a contract, not a button in MachineFabric’s code. It specifies:
- What it accepts: an input media URN (for example
media:document;ext=pdf,media:audio;ext=wav,media:fmt=json;llm-generation-request;record). - What it produces: an output media URN (for example
media:enc=utf-8;page,media:fmt=ndjson;llm-text-stream). - How it is named: a Cap URN of the form
cap:in="media:X";<tags>;out="media:Y"that identifies the operation precisely enough for the planner to route to it. - What arguments it takes: optional parameters extracted from stdin, CLI positions, or flags.
CapDAG, the open protocol MachineFabric is built on, defines how capabilities are named, matched, and routed. This page covers what capabilities mean inside MachineFabric: what the Transmute menu shows, what the standard capabilities are, and what cartridges declare. For protocol-level details:
- CapDAG cap URN structure: how a Cap URN composes input, output, and tags.
- CapDAG tagged URN domain: URN syntax, normalization, wildcard semantics.
- CapDAG dispatch: the rule that decides which candidate serves a request.
- CapDAG ranking: how the most specific candidate is selected when more than one matches.
- CapDAG media URNs: the typed payloads that flow between cartridges.
How the Transmute menu reaches a capability
Before the menu opens, FabricLoom does the following:
- It reads the file’s media type. A PDF becomes
media:document;ext=pdf, a WAV becomesmedia:audio;ext=wav, and so on. - The planner walks the capability graph. Every cap that accepts that input directly, plus every cap reachable through one or more chained cartridges, contributes a possible destination.
- The menu shows destinations, not steps, such as “render to image,” “transcribe,” and “summarize.” You pick the destination and the planner picks the route.
- The route is shown before it runs. For multi-step pipelines the graph appears so you can see the route before any data moves.
- Cartridges are invoked in order. Each one runs in the platform cartridge host (the macOS XPC service or the Linux/Windows host daemon), with progress streamed back live and results stored in your library.
When the same destination is reachable by more than one route, ranking picks the most specific match. A PDF-specific extractor beats a generic document extractor, and an LLM cap that names a specific model beats a generic one.
Standard capabilities
CapDAG ships a small set of standard caps that every cartridge can rely on. CAP_IDENTITY is mandatory, and the rest are common operations the registry has helpers for.
Mandatory
| Cap URN | Purpose |
|---|---|
cap:effect=none (CAP_IDENTITY) |
Pass input through unchanged. Every cartridge must declare it. The runtime auto-registers a handler, so you only include it in the manifest. |
Standard (optional)
| Cap | Purpose |
|---|---|
CAP_DISCARD |
Accept any input, produce media:void. Default implementation provided. |
CAP_ADAPTER_SELECTION |
Inspect content and return the media URNs that describe it. Used for file-type detection. |
LLM, embeddings, models
The cartridge SDK exposes URN constants and builders for the LLM, embeddings, and model-management caps that MachineFabric routes through routinely:
- LLM inference:
CAP_LLM_INFERENCE_GGUF,CAP_LLM_INFERENCE_MLX,CAP_LLM_INFERENCE_CANDLE,CAP_LLM_INFERENCE_CONSTRAINED - LLM introspection:
CAP_LLM_VOCAB,CAP_LLM_MODEL_INFO - Embeddings:
CAP_GENERATE_EMBEDDINGS,CAP_EMBEDDINGS_DIMENSIONS - Vision:
CAP_DESCRIBE_IMAGE - Models: download, list, status, contents, availability, path (URN builders in the standard library)
The associated payload media URNs:
| Media URN | Carries |
|---|---|
media:fmt=json;llm-generation-request;record |
An LlmGenerationRequest: prompt, model spec, sampling params, optional constraints |
media:fmt=ndjson;llm-text-stream |
An LlmStreamMessage stream: tokens, status, completion, tool requests, errors |
media:fmt=json;llm-vocab-response;record |
An LlmVocabResponse |
media:fmt=json;llm-model-info;record |
An LlmModelInfo |
The full request, stream, vocab, and info shapes are in the Cartridge SDK reference. The dispatch rule that routes a generation request to the right backend (GGUF, MLX, or Candle) follows the same ranking logic as every other request: the request’s model_spec plus tags determines the candidate.
Document and content caps
Standard URN builders in the CapDAG library cover the common document operations:
disbind_urn(input_media): decompose a document into pages with text contentrender_page_image_urn(input_media): render document pages as imagescoercion_urn(source_type, target_type): generic format coercionformat_conversion_urn(in_media, out_media): JSON / YAML / CSV interconversiongenerate_json_urn(lang_code),make_decision_urn(lang_code),make_multiple_decisions_urn(lang_code): structured-output LLM caps
For everything else (custom extraction, sentiment tagging, OCR, transliteration), cartridges define their own caps. The URN must parse (per CapDAG URN syntax), and the input and output media URNs it references must either exist in the registry or be proposed alongside the cartridge (Contributing).
# Examples of valid custom caps
cap:in="media:enc=utf-8;sentiment-input";out="media:sentiment-tag;enc=utf-8";tag-sentiment
cap:in="media:ext=png;image";analyze;target=faces;out="media:fmt=json;record"
cap:in="media:audio;ext=wav;speech";ml-model;out="media:enc=utf-8;record;transcription";transcribe
What a cartridge declares
Cartridges declare their capabilities in a CapManifest returned at startup. The host reads the manifest at install time to register the cartridge with the router.
The minimal Python shape is below. The Build your first cartridge tutorial builds this cartridge from the scaffold.
from capdag.bifaci.manifest import CapManifest, default_group
from capdag.cap.definition import Cap, CapArg, CapOutput, PositionSource, StdinSource
from capdag.standard.caps import CAP_IDENTITY
from capdag.urn.cap_urn import CapUrn, CapUrnBuilder
def build_manifest() -> CapManifest:
tag_sentiment = Cap(
urn=(
CapUrnBuilder()
.marker("tag-sentiment")
.in_spec("media:enc=utf-8;sentiment-input")
.out_spec("media:sentiment-tag;enc=utf-8")
.build()
),
title="Tag sentiment",
aliases=["tag-sentiment"],
)
tag_sentiment.args = [
CapArg(
media_urn="media:enc=utf-8;sentiment-input",
required=True,
sources=[
StdinSource("media:enc=utf-8;sentiment-input"),
PositionSource(0),
],
arg_description="UTF-8 text to classify.",
)
]
tag_sentiment.output = CapOutput(
media_urn="media:sentiment-tag;enc=utf-8",
output_description="One of 'positive', 'neutral', 'negative'.",
)
identity = Cap(
urn=CapUrn.from_string(CAP_IDENTITY),
title="Identity",
aliases=["identity"],
)
return CapManifest(
name="sentiment-tagger",
version="0.1.0",
channel="nightly",
registry_url=None,
description="Classify text as positive, neutral, or negative.",
cap_groups=[default_group([identity, tag_sentiment])],
)
The host enforces these rules:
CAP_IDENTITYis mandatory. Every cartridge’s manifest must list it. The Python runtime auto-registers a handler, so you only declare the cap.channelandregistry_urlare fixed at build time. They must agree with the engine’s compile-time configuration and with the on-disk install record (cartridge.json). A mismatch is rejected at discovery time.cap_groupsare atomic registration units. A group succeeds or fails as a whole, which keeps related caps consistent.
Construct a Cap URN with the builder API (CapUrnBuilder().marker().in_spec().out_spec().build()) and not as a hand-written string. The runtime canonicalizes tags alphabetically, so a hand-written URN string will almost certainly not match the canonical form. See the Build your first cartridge tutorial for the pattern of building the URN once and keeping the resulting string.
Routing in practice
When MachineFabric needs a capability:
- It builds a request, which is a Cap URN describing what is needed.
- The router runs the dispatch predicate against every registered candidate and collects the eligible ones.
- Among eligible candidates, ranking picks the most specific.
- The selected cartridge is spawned if it is not already running, the request is sent over the Bifaci protocol (CapDAG’s binary frame protocol between host and cartridge), and the response is streamed back.
- For multi-step requests, the planner finds the path through the capability graph and the executor runs each step in order, in parallel where the graph allows.
If two candidates match with equal specificity, the first registered wins. A specialized cartridge for a specific file type therefore reliably overrides a more general one for that type, while the general cartridge remains available for everything else.