# Manager-Based Workflows

In the project you generated, the cartpole task is described in `env_cfg.py`.
However, a configuration file is only a description: it never steps the
simulation itself. Isaac Lab reads the configuration, builds an environment, and hands
each job (applying actions, reading observations, scoring the task) to a
helper object called a *manager*. This lesson shows how those pieces fit
together, following the code from
[Isaac Lab Project Generation](https://docs.nvidia.com/learning/physical-ai/getting-started-with-isaac-lab/2026-10.0/isaac-lab-basics/02-isaac-lab-projects.md) all the way to a
single call to `env.step(actions)`.

![Configuration defines what work to do, the environment schedules when managers run, and managers execute their configured terms. In the reward example, RewardManager combines the weighted alive and pole_pos term results into a reward for each environment.](images/manager-based-config-to-runtime.svg)

Use the `isaac-lab-workspace/isaac_lab_tutorial` project you generated earlier,
and open `env_cfg.py` as you read. You only need to look at the file; you will
run the task in the following lessons.

## From Configuration to Runtime

Find `BalanceEnvCfg`, the class that inherits from [`ManagerBasedRLEnvCfg`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.envs.html#isaaclab.envs.ManagerBasedRLEnvCfg). Its
fields assemble the scene, actions, observations, events, rewards, and
terminations. Its simulation settings also select `BalancePhysicsCfg` and set
the physics time step and the control *decimation* (how many physics steps
happen for each control step).

Think of these classes as a recipe. When Isaac Lab constructs a
[`ManagerBasedRLEnv`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.envs.html#isaaclab.envs.ManagerBasedRLEnv) object, it follows the recipe: it builds the scene, then
creates one manager for each job the task needs.

The `scene = BalanceSceneCfg(...)` field creates an
[`InteractiveScene`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.scene.html#isaaclab.scene.InteractiveScene),
which holds the cartpole and its surroundings. Managers look up named assets in
this scene. For example, a term can use the
[`SceneEntityCfg`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.SceneEntityCfg)
to pick out the cart joint from the robot asset. The configuration below selects
the joint that connects the slider to the cart:

```text
SceneEntityCfg("robot", joint_names=["slider_to_cart"])
```

The action, observation, event, reward, and termination fields each configure
one manager. A helpful way to remember the split: the configuration says
*what* work to do, and the environment decides *when* to do it.

## Terms Are the Smallest Pieces

Each manager is built from *terms*. A term is one small, named piece of the
task: a single function (or callable class) plus the parameters it needs.
Here is where to find the terms in the cartpole configuration:

- **Actions:** Open `ActionsCfg` and find the term that targets the cart joint.
  The [`ActionManager`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.ActionManager) interprets the incoming action and applies it as a joint
  effort (a force on the cart).
- **Observations:** Find the `policy` group in `ObservationsCfg`. Its terms read
  joint positions and velocities, which become the policy’s next input.
- **Events:** `EventCfg` contains reset terms that vary the cart and pole’s
  initial states, so the policy does not always start from the same pose.
- **Rewards:** `RewardsCfg` combines weighted terms, such as a survival reward
  and a pole-angle reward.
- **Terminations:** `TerminationsCfg` checks the time limit and the cart
  bounds.

You do not always have to write the functions yourself. The generated
`balance/mdp/rewards.py` holds the task-specific pole-angle reward, while the
other terms reuse functions that ship with Isaac Lab.

### How Managers Handle Terms

Each term has a name in its configuration class. For example, these two
reward terms are named `alive` and `pole_pos`:

```python
@configclass
class RewardsCfg:
    alive = RewardTermCfg(func=mdp.is_alive, weight=1.0)
    pole_pos = RewardTermCfg(
        func=mdp.joint_pos_target_l2,
        weight=-1.0,
        params={
            "asset_cfg": SceneEntityCfg(
                "robot", joint_names=["cart_to_pole"]
            ),
            "target": 0.0,
        },
    )
```

The `RewardsCfg` excerpt uses the full `RewardTermCfg` name; the generated file may import
it as `RewTerm` as a common shorthand. Reward terms are defined by their name, function, parameters, and weight.

- `func` identifies the callable (like a function or class with `__call__`)
- `params` supplies the callable’s keyword arguments
- `weight` controls its contribution to the total reward

`mdp.is_alive` is [supplied by Isaac
Lab](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.envs.mdp.html#isaaclab.envs.mdp.rewards.is_alive).
It returns one value per environment, equal to 1 when the environment has not
terminated and 0 when it has. Here is the function that `pole_pos` calls, from
the generated project’s `mdp/rewards.py`.

```python
def joint_pos_target_l2(env: ManagerBasedRLEnv, target: float, asset_cfg: SceneEntityCfg) -> torch.Tensor:
    """Penalize joint position deviation from a target value."""
    asset: Articulation = env.scene[asset_cfg.name]
    joint_pos = wrap_to_pi(asset.data.joint_pos.torch[:, asset_cfg.joint_ids])
    return torch.sum(torch.square(joint_pos - target), dim=1)
```

Each term function receives the environment as its first argument, so it can
read the selected asset from `env.scene`. `SceneEntityCfg` identifies the
`robot` asset and resolves `cart_to_pole` to a joint index. The reward function
reads that joint’s angle, wraps it to the interval from `-pi` to `pi`, and
squares its difference from the zero target. Wrapping makes angles separated by
a full revolution equivalent. The function returns one error per environment;
the negative weight turns each error into a penalty. It does not average the
errors across all cartpoles, because each environment needs its own reward.

The [reward manager](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.RewardManager)
combines the weighted term values and multiplies the result by the control-step
duration. A raw term value, its configured weight, and its contribution to the
episode return are therefore different quantities.

Managers handle their terms through three stages:

1. **Prepare:** Parse the configuration, validate the term definitions, and
   resolve scene entity names into joint or body selections. Construct any
   callable class terms with their configuration and environment.
2. **Execute:** When the environment requests the manager’s work, call the
   relevant terms with the environment and configured parameters. Event terms,
   for example, run for the requested mode, such as reset or interval.
3. **Reset:** Clear the relevant manager buffers and reset stateful terms for
   the environments whose episodes ended. Other environments can continue
   using their existing state.

A term can be an ordinary function or a callable class. Class terms can retain
state between calls; they inherit from
[`ManagerTermBase`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.ManagerTermBase)
and implement the methods their manager requires, including reset behavior
when needed.

Each manager handles its term results according to its job:

- `RewardManager` sums weighted contributions into a reward for each
  environment.
- `TerminationManager` combines Boolean conditions with logical OR, while
  keeping terminal states and timeouts distinguishable.
- `ObservationManager` organizes signals into groups and can concatenate the
  terms in each group into a tensor.
- `ActionManager` splits the action vector among its terms, then processes and
  applies their controls.
- `EventManager` executes operations for the requested event mode.

The environment schedules the managers; each manager executes its configured
terms and handles their results.

### Base and RL Environments

[`ManagerBasedEnv`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.envs.html#isaaclab.envs.ManagerBasedEnv) contains the scene, action, observation, and event managers.
Its reinforcement learning subclass, `ManagerBasedRLEnv`, adds reward and
termination managers, and can also use command and curriculum managers:

- A [*command* manager](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.CommandManager) samples a goal for the robot to track.
- A [*curriculum* manager](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.CurriculumManager) gradually changes the difficulty of the task.

The cartpole task needs neither: its upright target is fixed, and its
difficulty does not change during training. Tasks such as walking to a target
can use them.
[The manager API](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#module-isaaclab.managers)
lists every manager and term configuration class.

![An RL agent exchanges actions and step results with ManagerBasedRLEnv. The environment contains action, observation, command, reward, termination, curriculum, event, and recorder managers, and connects to the interactive scene and simulation.](images/manager-based-rl-environment-architecture.svg)

## Follow One Control Step

When the agent calls `env.step(actions)`, the environment runs one control step
across all of the parallel cartpole environments at once:

1. `ActionManager` processes the incoming action once for the control step. It
   applies the resulting control before each physics substep.
2. The selected physics backend advances the scene. The cartpole configuration
   uses a decimation of two, so one control step advances two physics steps.
3. The RL environment evaluates the reward and termination terms. An
   environment that reaches its time limit or cart bound ends its episode, and
   reset events prepare its next initial state.
4. [`ObservationManager`](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#isaaclab.managers.ObservationManager) supplies the next policy observation. The step also
   returns the reward, `terminated`, `truncated`, and an information
   dictionary.

![A call to env.step processes the action, applies it across physics substeps, evaluates terminations and rewards, resets affected environments, updates commands and events, computes fresh observations, and returns the step results.](images/manager-based-env-step-flow.svg)

To learn more about any detail of this sequence, see the
[`ManagerBasedRLEnv.step` API
reference](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.envs.html#isaaclab.envs.ManagerBasedRLEnv.step).

Every term works on a *batch* of environments, so one `step()` call can advance
many independent cartpoles. One cartpole can reset while the others keep going.
Notice also that the action is processed once per control step but applied
before every physics step. That is why `decimation` matters: it sets how long
each action is held.

## Default Configuration and Overrides

You can run a task without choosing every setting yourself. The task’s
configuration gives you a starting point, including a default physics backend.
In the generated cartpole project, look for this line in `BalanceEnvCfg`’s
`__post_init__()` method:

```python
self.sim.physics = BalancePhysicsCfg()
```

`BalancePhysicsCfg` lists the task’s physics choices and sets Newton with
MJWarp as the default. The key line is `default = newton_mjwarp`. Here is an
abbreviated view of the configuration, with the backend settings omitted so
you can focus on how the default is selected:

```python
@configclass
class BalancePhysicsCfg(PresetCfg):
    newton_mjwarp: NewtonCfg  = NewtonCfg(...)
    ovphysx      : OvPhysxCfg = OvPhysxCfg(...)
    default = newton_mjwarp
```

`newton_mjwarp` names a configured backend option. Assigning that configuration
to `default` makes it the choice Isaac Lab uses when you do not supply a physics
selector. (The ellipses `...` above are placeholders.)

If you run the command below, Isaac Lab uses that default automatically:

```bash
uv run isaaclab random_agent               \
  --task IsaacLabTutorial-Balance-Cartpole \
  --visualizer none
```

To try another backend, add a physics selector to your command. For example,
this command runs the same task with OV PhysX:

```bash
uv run --extra ovphysx isaaclab random_agent \
  --task IsaacLabTutorial-Balance-Cartpole   \
  --visualizer none                                 \
  physics=ovphysx
```

There are two parts to that change: `--extra ovphysx` makes the integration
available, and `physics=ovphysx` tells the task to use it for this run. You can
try a different backend this way without editing `env_cfg.py`. Each task has
its own available choices. To see yours, use the help or preset listing
introduced in [The Isaac Lab CLI](https://docs.nvidia.com/learning/physical-ai/getting-started-with-isaac-lab/2026-10.0/isaac-lab-basics/04-isaac-lab-cli.md).

Before building the environment, Isaac Lab settles on the configuration for
your run: the task’s default, with any overrides you supplied. It then creates
the matching `PhysicsManager` and the backend’s versions of the assets and
sensors. Once the scene is ready, the task managers resolve their terms against
it—for example, finding the cart joint that an action term will control.

## Review

### Check Your Understanding

How do you calculate the control interval from the physics time step and
decimation?

### Answer

Multiply the physics time step by decimation. For example, a physics time step
of 1/120 second and decimation of 2 give a control interval of 1/60 second.

### Apply What You Learned

How would you trace one cartpole control step through the configured managers
and physics substeps? Distinguish action processing from application, identify
the manager operations, and calculate the control interval from the
configuration.

### <svg version="1.1" width="1.0em" height="1.0em" class="sd-octicon sd-octicon-dependabot" viewBox="0 0 16 16" aria-hidden="true"><path d="M5.75 7.5a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5a.75.75 0 0 1 .75-.75Zm5.25.75a.75.75 0 0 0-1.5 0v1.5a.75.75 0 0 0 1.5 0v-1.5Z"></path><path d="M6.25 0h2A.75.75 0 0 1 9 .75V3.5h3.25a2.25 2.25 0 0 1 2.25 2.25V8h.75a.75.75 0 0 1 0 1.5h-.75v2.75a2.25 2.25 0 0 1-2.25 2.25h-8.5a2.25 2.25 0 0 1-2.25-2.25V9.5H.75a.75.75 0 0 1 0-1.5h.75V5.75A2.25 2.25 0 0 1 3.75 3.5H7.5v-2H6.25a.75.75 0 0 1 0-1.5ZM3 5.75v6.5c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75v-6.5a.75.75 0 0 0-.75-.75h-8.5a.75.75 0 0 0-.75.75Z"></path></svg> Agent Tutor Prompt

Copy this prompt and include your answer:

> Review my answer to this question: How would you trace one cartpole control step through the configured managers and physics substeps? Distinguish action processing from application, identify the manager operations, and calculate the control interval from the configuration.

> My answer: [paste your answer here].

> Check my reasoning about action processing and application, observations, rewards, resets, endings, and episode duration. Ask for missing context rather than assuming it. Identify what I explained well, point out one gap or misconception, and ask a follow-up question that helps me improve my answer. Let me revise it before supplying a complete answer.

### Key Takeaways

- Configuration classes declare task terms; managers execute them.
- A control step may include several physics substeps.
- The physics backend advances the scene; rendering produces images when needed.

### Resources

- [Isaac Lab Managers API](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/api/lab/isaaclab.managers.html#module-isaaclab.managers) — API reference for manager classes, term configurations, and scene entity selection.
- [Creating a Manager-Based Base Environment](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/how-to/create_manager_base_env.html) — A guide to configuring a scene, actions, observations, and events in a manager-based environment.
- [Creating a Manager-Based RL Environment](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/how-to/create_manager_rl_env.html) — A guide to adding rewards, termination conditions, and other reinforcement learning components to a manager-based environment.
- [Backend Architecture](https://isaac-sim.github.io/IsaacLab/release/3.0.0/source/concepts/backends_and_presets.html) — An explanation of backend selection, common simulation interfaces, and the physics manager lifecycle.
