Skip to main content

Module wiring

Modules in a workspace connect to each other through settings. A setting whose value is a "dag://<module>/<function>" DAG address is a module reference. It injects the value returned by a function on another installed module. This is how generic modules compose without knowing about each other, and without you writing a glue module.

Wire a service into a module​

A test-runner module accepts an optional Service; your app module has a function that returns one. Connect them in dagger.toml:

[modules.myapp]
source = "./ci/myapp"

[modules.playwright]
source = "dagger.io/js/playwright"

[modules.playwright.settings]
service = "dag://myapp/serve"

Now dagger check dag://playwright/test runs the browser tests against your app. Dagger resolves the reference when it constructs the playwright module and passes the running service in.

To find functions you can wire, run dagger artifact list --type Service. It lists every service-returning function in the workspace, in exactly the dag:// address form a setting accepts. Any function returning the right type works.

Wire a container​

References aren't limited to services. A Container argument wires the same way:

[modules.playwright.settings]
baseCtr = "dag://base-images/chromium"

Wire a file, directory, or workspace​

Build artifacts and workspaces can be passed between modules in the same way. A function returning a File, Directory, or Workspace can be referenced by a matching constructor argument:

[modules.packager.settings]
binary = "dag://builder/binary"
assets = "dag://frontend/assets"
source = "dag://source-prep/workspace"

Reference the workspace entrypoint​

The entrypoint module's functions are hoisted onto the workspace root, so a reference to one can drop the module name:

dagger module settings playwright service serve

The config always stores the full address:

[modules.myapp]
source = "./ci/myapp"
entrypoint = true

[modules.playwright.settings]
service = "dag://myapp/serve"

The dagger settings command only rewrites a bare name when the entrypoint has a function of that name. In dagger.toml, the entrypoint's functions are also addressed without the module name: dag://serve.

Use a reference on the command line​

A module reference is an ordinary address string, so it also works as a CLI flag for any object-typed constructor argument:

dagger api call playwright --service=dag://myapp/serve test

How references resolve​

  • The dag:// scheme marks a workspace artifact address. The path's leading segment is a module's install name, the [modules.X] key in this dagger.toml, and the rest names a zero-arg function on it whose return type matches the argument. The workspace entrypoint module's functions drop the module segment: dag://serve.
  • An address with dag:// is a module reference. A missing function or a mismatched type is then a hard error, never a silent fallback to an image or URL. dagger artifact list prints every address the workspace has.
  • A value without dag:// keeps its ordinary address meaning: an OCI ref for a Container, a tcp:// URL for a Service. So git:2.40 and alpine:3.20 stay image refs.

Migrate existing references​

Older workspace configurations used module:function or a bare entrypoint function name. Replace those values in object-typed settings and CLI flags with DAG addresses:

Previous valueDAG address
base-images:chromiumdag://base-images/chromium
myapp:servedag://myapp/serve
go-base (on entrypoint project-dev)dag://project-dev/go-base

This rule applies to object-typed settings for modules written in any SDK. For a Container setting, a bare name such as go-base is now an image reference. For File and Directory settings, it is a path. Keep ordinary image references, paths, URLs, and string-valued settings as they are.

The settings command accepts a bare entrypoint function name and writes its full DAG address. Hand-edited dagger.toml values and CLI object flags need the dag:// scheme explicitly.

SDK code that resolves workspace artifacts uses Workspace.resolve with a DAG address, then the matching typed loader such as Address.container or Address.service. In the 1.0 API, Query.address resolves external references only. Pass the resulting typed object to other module functions as usual. Clients using a pre-1.0 schema view retain the legacy Query.address behavior.

Design your module for wiring​

If you author modules, wiring changes how you shape a constructor:

  • Accept collaborators as optional constructor arguments. An optional Service, Container, File, Directory, or Workspace argument is a wiring point. Without one, users need a glue module to connect yours to anything.
  • Consume workspaces in the constructor. A module object cannot retain a Workspace as a field. Derive and store the File, Directory, or other value your module needs from the wired workspace instead.
  • Put workspace-level configuration on the constructor, not on function arguments. Settings map to constructor arguments. A shard count, a service, or a base image belongs there if the workspace should configure it once.
  • Degrade gracefully. When nothing is wired, do something sensible rather than failing: skip the service binding, or fall back to a default image. The workspace may have nothing to wire yet.

The Playwright module is a worked example of all three. Daggerize a Go Project wires a project's own module into the Go module's base setting, from the consumer's side.