Qualified Names

A fully qualified name is the unique identifier of any particular call, input, or output, and has the following structure:

  • For calls: <parent namespace>.<call alias>
  • For inputs and outputs: <parent namespace>.<input or output name>
  • For Structs and Objects: <parent namespace>.<member name>

A namespace is a set of names, such that every name is unique within the namespace (but the same name could be used in two different namespaces). The parent namespace is the fully qualified name of the workflow containing the call, the workflow or task containing the input or output declaration, or the Struct or Object declaration containing the member. For the top-level workflow this is equal to the workflow name.

For example: ns.ns2.mytask is a fully-qualified name - ns.ns2 is the parent namespace, and mytask is the task name being referred to within that namespace. Fully-qualified names are left-associative, meaning ns.ns2.mytask is interpreted as ((ns.ns2).mytask), meaning ns.ns2 has to resolve to a namespace so that .mytask can be applied.

When a call statement needs to refer to a task or workflow in another namespace, then it must use the fully-qualified name of that task or workflow. When an expression needs to refer to a declaration in another namespace, it must use a namespaced identifier, which is an identifier consisting of a fully-qualified name.

Example: call_imported.wdl

version 1.3

import "input_ref_call.wdl" as ns1

workflow call_imported {
  input {
    Int x
    Int y = d1.out
  }

  call ns1.double as d1 { int_in = x }
  call ns1.double as d2 { int_in = y }

  output {
    Int result = d2.out
  }
}

Example input:

{
  "call_imported.x": 5
}

Example output:

{
  "call_imported.result": 20
}

The workflow in the above example imports the WDL file from the previous section using an alias. The import creates the namespace ns1, and the workflow calls a task in the imported namespace using its fully qualified name, ns1.double. Each call is aliased, and the alias is used to refer to the output of the task, e.g., d1.out (see the Call Statement section for details on call aliasing).

In the following more extensive example, all of the fully-qualified names that exist within the top-level workflow are listed exhaustively.

Example: main.wdl

version 1.3

import "other.wdl" as other_wf

task echo {
  input {
    String msg = "hello"
  }

  command <<<
  printf '~{msg}\n'
  >>>

  output {
    File results = stdout()
  }

  requirements {
    container: "ubuntu:latest"
  }
}

workflow main {
  Array[String] arr = ["a", "b", "c"]

  call echo
  call echo as echo2
  call other_wf.foobar { infile = echo2.results }
  call other_wf.other { b = true, f = echo2.results }
  call other_wf.other as other2 { b = false }

  scatter(x in arr) {
    call echo as scattered_echo {
      msg = x
    }
    String scattered_echo_results = read_string(scattered_echo.results)
  }

  output {
    String echo_results = read_string(echo.results)
    Int foobar_results = foobar.results
    Array[String] echo_array = scattered_echo_results
  }
}

Example input:

{}

Example output:

{
  "main.echo_results": "hello",
  "main.foobar_results": 1,
  "main.echo_array": ["a", "b", "c"]
}

Example: other.wdl

version 1.3

task foobar {
  input {
    File infile
  }

  command <<<
  wc -l < ~{infile}
  >>>

  output {
    Int results = read_int(stdout())
  }

  requirements {
    container: "ubuntu:latest"
  }
}

workflow other {
  input {
    Boolean b = false
    File? f
  }

  if (b && defined(f)) {
    call foobar { infile = select_first([f]) }
  }

  output {
    Int? results = foobar.results
  }
}

Example input:

{
  "other.b": true,
  "other.f": "data/greetings.txt"
}

Example output:

{
  "other.results": 3
}

The following fully-qualified names exist when calling workflow main in main.wdl:

Fully-qualified NameReferencesAccessible
other_wfNamespace created by importing other.wdl and aliasing itAnywhere in main.wdl
mainTop-level workflowBy the caller of main
main.arrArray[String] declaration on the workflowAnywhere within main
main.echoFirst call to task echoAnywhere within main
main.echo2Second call to task echo (aliased as echo2)Anywhere within main
main.echo.msgString input of first call to task echoNo*
main.echo.resultsFile output of first call to task echoAnywhere within main
main.echo2.msgString input of second call to task echoNo*
main.echo2.resultsFile output of second call to task echoAnywhere within main
main.foobar.infileFile input of the call to other_wf.foobarNo*
main.foobar.resultsInt output of the call to other_wf.foobarAnywhere within main
main.otherFirst call to subworkflow other_wf.otherAnywhere within main
main.other.bBoolean input of the first call to subworkflow other_wf.otherNo*
main.other.fFile input of the first call to subworkflow other_wf.otherNo*
main.other.foobar.infileFile input of the call to foobar inside the first call to subworkflow other_wf.otherNo*
main.other.foobar.resultsInt output of the call to foobar inside the first call to subworkflow other_wf.otherNo
main.other.resultsInt? output of the first call to subworkflow other_wf.otherAnywhere within main
main.other2Second call to subworkflow other_wf.other (aliased as other2)Anywhere within main
main.other2.bBoolean input of the second call to subworkflow other_wf.otherNo*
main.other2.fFile input of the second call to subworkflow other_wf.other`No*
main.other2.foobar.infileFile input of the call to foobar inside the second call to subworkflow other_wf.otherNo*
main.other2.foobar.resultsInt output of the call to foobar inside the second call to subworkflow other_wf.otherNo
scattered_echoCall to echo within scatter of mainWithin the scatter
scattered_echo.resultsFile results of call to scattered_echo`Within the scatter
main.scattered_echo.msgArray of String inputs to calls to scattered_echoNo*
main.scattered_echo.resultsArray of File results of calls to echo within the scatterAnywhere within main
scattered_echo_resultsString contents of File created by call to scattered_echoWithin the scatter
main.scattered_echo_resultsArray of String contents of File results of calls to echo within the scatterAnywhere within main
main.echo_resultsString contents of File result from call to echoAnywhere in main's output section and by the caller of main
main.foobar_resultsInt result from call to foobarAnywhere in main's output section and by the caller of main
main.echo_arrayArray of String contents of File results from calls to echo in the scatterAnywhere in main's output section and by the caller of main

* Task inputs are accessible to be set by the caller of main if the workflow is called with allow_nested_inputs: true in its hints section.