MESH ONLINECODENAME:
v0.34

Move Artifacts

The bus is a coordination layer, not a file transfer. When work produces something large — a model checkpoint, a video frame, a directory tree — you move it as a content-addressed blob and put only a small reference on the bus.

Reference, don't embed

The event carries a BlobRef; the bytes travel separately, on demand, to whoever actually needs them. An event that carries the payload has turned a coordination message into a transfer, and every subscriber pays for it whether they wanted the bytes or not.

The address is the content

Blobs are addressed by their BLAKE3 hash. The address is the content, which has consequences worth stating rather than deriving:

  • There is no canonical home to provision. Blobs live on whichever nodes have capacity and drift toward the nodes that read them.
  • A reference is verifiable. Bytes that hash to the reference are the right bytes, from whichever peer served them.
  • Identical content is one blob. Storing the same bytes twice does not double the storage.

Three guarantees the transfer path makes

Peak memory is one chunk (~4 MiB), regardless of total size. A blob larger than RAM transfers fine; the transfer is streamed, not buffered.

A directory fetch is all-or-nothing. It either becomes the complete tree or leaves the destination untouched. There is no partially-materialized state to clean up.

A producer reading back its own write never sees a gap. The write path returns a token the read path waits on — read-your-own-writes, so the common write-then-immediately-read sequence is not a race.

Serving must be installed before fetching

A node cannot serve chunks, and in most bindings cannot issue fetches, until blob transfer has been installed on it with a storage adapter. This is one call and it is easy to omit, because omitting it produces a fetch that fails to find a holder rather than an error naming the missing install.

Bridged tools have no artifacts

Artifacts are a native capability. Tools brought in through the MCP bridge are mcp_bridge tier — request/response only, no artifacts. If the work needs to move bytes, it has to be a native capability, not a wrapped one. This is a tier boundary, not a limitation to route around.

Where the full surface lives

This page is the entry point per binding. The storage and gravity model, the adapter configuration, overflow behaviour and the operator CLI (net-mesh transfer send-blob / recv-blob / send-dir / recv-dir) are in Blob Storage (Dataforts) and the CLI Reference.

Move it — Go

Cross-peer blob transfer is not in the Go binding

Rust, TypeScript and Python each expose serve_blob_transfer, fetch_blob, fetch_blob_discovered and fetch_dir. Go exposes none of them. There is no net_transport.h binding in the Go module, and no transfer stream helpers.

What Go does have is MeshBlobAdapter, and it is worth being precise about what that is, because its name suggests more than it does:

go
adapter, err := net.NewMeshBlobAdapter(redex, "my-adapter", nil)
if err != nil {
    log.Fatal(err)
}
defer adapter.Close()
 
err = adapter.Store(blobRefBytes, data)     // local content-addressed store
data, err := adapter.Fetch(blobRefBytes)    // local read
ok, err := adapter.Exists(blobRefBytes)

Store, Fetch and Exists are local operations against this node's own blob store. They do not reach a peer. A Fetch for content this node has never stored returns not-found; it does not go looking.

The adapter is feature-gated server-side on dataforts,netdb,redex-disk. Built without them, the FFI returns null and the constructor returns ErrBlob.

What to do instead

Shell out to the CLI. net-mesh transfer send-blob / recv-blob / send-dir / recv-dir drives the same substrate transfer path, and from Go this is currently the supported route for moving bytes between peers. See the CLI Reference.

Or put the transfer on a node in another binding. A Rust or Python sidecar that owns the artifact path, coordinated over nRPC from Go, keeps your Go service in charge without needing a binding that does not exist.

Do not put the bytes in an event to work around this. That converts a coordination message into a broadcast transfer for every subscriber, which is the failure mode this whole page exists to prevent.

Reference, don't embed

The reference half works normally — Go can carry and pass a BlobRef even where it cannot fetch one:

go
_ = bus.Ingest(map[string]any{"frame_id": "abc123", "blob": blobRef})

Verify it worked

For the local adapter path:

go
if err := adapter.Store(blobRefBytes, data); err != nil {
    log.Fatal(err)
}
ok, err := adapter.Exists(blobRefBytes)
if err != nil {
    log.Fatal(err)
}
if !ok {
    log.Fatal("stored, but not readable back")
}
fmt.Println("stored:", len(data), "bytes")

There is no Go-side verification for a cross-peer fetch, because there is no cross-peer fetch. This page will not show you another language's code in its place.

Next: Errors and recovery.

§ parity · Dataforts — blobsfrom the capability record
Rust supportedNode / TS supportedPython supportedGo partialC supported