def add(self, job, args=None, role=WorkUnitRole()):
    # pyformat: disable
    """Adds a Job / JobGroup to the experiment.

    A new Experiment Unit is created to run the job.

    Args:
      job: A Job or JobGroup to add.
      args: Keyword arguments to be passed to the job. For Job and JobGroup args
        are recursively expanded. For example,

        ```
        wu.add(
            JobGroup(agent=Job(...)),
            args={'agent': {'args': {'learning_rate': 0.1}}},
        )
        ```

        would update `args` field of a job `agent` in the group.
      role: The role of this unit in the experiment structure.

    Returns:
      An awaitable that would be fulfilled when the job is launched.
    """
    # pyformat: enable
    role = pattern_matching.match(
        pattern_matching.Case([AuxiliaryUnitJob], lambda job: job.role),
        pattern_matching.Case([Any], lambda job: role),
    )(
        job)
    experiment_unit_future = self._create_experiment_unit(args, role)

    async def launch():
      experiment_unit = await experiment_unit_future
      await experiment_unit.add(job, args)
      return experiment_unit

    return asyncio.wrap_future(self._create_task(launch()))