Plugs and slots

A workshop is a graph of capabilities. Each SDK can act as a provider, a consumer, or both, and the wiring between them is what lets a workshop deliver a coherent environment out of independently published parts.

In Workshop, that wiring uses two named endpoints: plugs and slots. Both reference an interface type; slots provide a capability of that type, and plugs consume one. The workshop connects matching pairs at launch and lets you adjust the topology in the workshop definition when the defaults are not what you want.

Slots provide capabilities

A slot exposes a capability that other SDKs can consume; a single slot can serve connections from multiple plugs at once. What a slot exposes depends on its interface:

Some capabilities are inherently host-rooted, like a camera device or a host-side directory. Only the system SDK can expose host-rooted slots, which is why every workshop has one installed by default. Regular SDKs can still publish slots that expose directories or endpoints from inside the workshop; a mount slot in a regular SDK, for example, points at a path within the SDK or the workshop user’s home, not the host filesystem.

Plugs consume capabilities

A plug is the consumer end. It is named within the SDK that declares it, references an interface type, and carries any attributes the consumer needs to apply once a slot is connected. For instance, with a mount plug, the central attribute is the target path inside the workshop where the slot’s directory should appear.

A plug stays declared even if no slot is connected to it, which means an SDK can ship optional plugs that only activate when a corresponding provider is also installed.

Auto-connection

When a workshop launches or refreshes, Workshop tries to connect each plug to a slot of the same interface type. The attempt succeeds when the interface policy permits the plug to connect to a candidate slot. The policy is what gates auto-connection, not the number of candidate slots in the workshop.

Auto-connection behavior varies by interface:

  • The mount interface auto-connects to slots provided by the system SDK. Regular-SDK mount slots are not auto-connected by default; wire them by listing the pair in the workshop’s top-level connections.

  • The GPU interface auto-connects.

  • The tunnel interface auto-connects only from host to workshop, between a plug and a slot of the same name, and only when the plug’s endpoint is a loopback address or a Unix domain socket. See Connection for the full policy.

  • The camera, custom device, desktop, and SSH interfaces do not auto-connect. They have to be connected manually with workshop connect.

When more than one slot is policy-eligible for the same plug, Workshop attempts a connection for each of them in an order it does not guarantee. The right way to express a specific topology is to write it down in the workshop definition’s connections: list instead of leaving it to auto-connection.

Wiring mechanisms

The workshop definition gives you two distinct YAML mechanisms for shaping the topology:

  • An inline plug binding, written as bind: inside a plug entry, delegates one plug to another plug. Both plugs then point at the same target, which is how same-interface conflicts are resolved.

  • A top-level connections: list, written at workshop scope, pairs a specific plug with a specific slot. Use it to override the default auto-connect target, for example to wire a mount plug to a regular SDK’s slot rather than the system SDK’s. The pair still has to satisfy the interface’s auto-connection policy, so interfaces that block auto-connection outright (such as ssh-agent) cannot be wired this way and must be connected with workshop connect.

The two mechanisms are mutually exclusive for a given plug: if it’s bound to another plug, it cannot also appear in a top-level connections: entry.

Workshop also exposes the runtime-only workshop connect and workshop disconnect commands, which change the wiring of a running workshop.

Inline plug bindings

A plug binding lets one plug stand in for another:

workshop.yaml
sdks:
  - name: consumer-sdk
    plugs:
      tools:
        bind: provider-sdk:tools

Both plugs then point to the same resource, and any action performed on one, such as connecting or remounting, applies to all bound plugs.

Bindings are the right tool when two plugs of the same interface would otherwise conflict over the same target, typically because two SDKs each declare a plug with overlapping attributes.

A bound plug only carries the binding; it cannot also define plug attributes of its own. The attributes come from the plug it is bound to.

When you run workshop connections, both the bound plug and its target carry a bind.<N> note in the NOTES column, where <N> is the row number of the target plug in the same output.

Top-level connections

The top-level connections: list pairs a plug with a slot directly:

workshop.yaml
connections:
  - plug: consumer-sdk:tools
    slot: provider-sdk:bin

Each entry uses the <SDK-NAME>:<NAME> form on both sides. Once the workshop is launched or refreshed, that pairing is the one Workshop applies, regardless of what other slots could have matched.

This is the mechanism to use when the workshop has more than one provider for an interface and you want to be specific about which one a consumer reads from.

Example: two SDKs sharing a mount

Consider a workshop that installs two SDKs:

  • provider-sdk ships a mount slot named bin that exposes a directory inside its own filesystem.

  • consumer-sdk declares a mount plug named tools whose target is a path under its workshop user’s home.

Auto-connection alone does not wire consumer-sdk:tools to provider-sdk:bin: the mount interface auto-connects to system SDK slots by default, so consumer-sdk:tools lands on system:mount and provider-sdk:bin stays listed but unconnected. You name the pairing explicitly with a top-level connections: entry:

workshop.yaml
sdks:
  - name: provider-sdk
  - name: consumer-sdk

connections:
  - plug: consumer-sdk:tools
    slot: provider-sdk:bin

After workshop launch or workshop refresh, workshop connections shows the chosen pairing and you can verify that consumer-sdk reads from provider-sdk rather than the system SDK’s default mount slot.

See also

Explanation:

How-to guides:

Reference: