Skip to main content


Dagger Functions can return custom objects, which in turn can define new functions. This allows for "chaining" of functions in the same style as the core Dagger API.

So long as your object can be JSON-serialized, its state will be preserved and passed to the next function in the chain.

Here is an example module with support for function chaining:

// A Dagger module for saying hello world!

package main

import (

type MyModule struct {
Greeting string
Name string

func (hello *MyModule) WithGreeting(ctx context.Context, greeting string) (*MyModule, error) {
hello.Greeting = greeting
return hello, nil

func (hello *MyModule) WithName(ctx context.Context, name string) (*MyModule, error) {
hello.Name = name
return hello, nil

func (hello *MyModule) Message(ctx context.Context) (string, error) {
var (
greeting = hello.Greeting
name = hello.Name
if greeting == "" {
greeting = "Hello"
if name == "" {
name = "World"
return fmt.Sprintf("%s, %s!", greeting, name), nil

And here is an example call for this module:

dagger call with-name --name=Monde with-greeting --greeting=Bonjour message

The result will be:

Bonjour, Monde!