# How to Export Microduck RL Checkpoints: A Complete Guide to ONNX Conversion

> Export Microduck RL checkpoints easily with the official CLI script. Convert trained models to ONNX format, embedding the observation normalizer for seamless deployment. Learn how now.

- Repository: [Pollen Robotics/microduck_rl](https://github.com/pollen-robotics/microduck_rl)
- Tags: how-to-guide
- Published: 2026-09-08

---

**The recommended way to export Microduck RL checkpoints is to use the official CLI wrapper [`scripts/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/scripts/export.py), which converts trained models to ONNX format with the observation normalizer baked directly into the graph.**

This guide covers the complete export workflow for the [pollen-robotics/microduck_rl](https://github.com/pollen-robotics/microduck_rl) reinforcement learning stack. Whether you're preparing a policy for real robot deployment or sharing results, following the official export pipeline ensures your **Microduck RL checkpoint** maintains full functionality.

## Why Use the Official Export Pipeline

Manual ONNX conversion of RL checkpoints often fails because the **observation normalizer** is excluded from the exported graph. According to the docstring in [`src/mjlab_microduck/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/export.py), this omission produces non-functional models on hardware. The official pipeline `runner.export_policy_to_onnx` (lines 52–57) is the **only** path that guarantees normalization is preserved.

Additional benefits include:

- Encapsulated environment setup and device handling
- Automatic WandB integration for remote checkpoint retrieval
- Consistency with the `publish` command for verified policy distribution

## Using the Export CLI

The [`scripts/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/scripts/export.py) wrapper provides the simplest interface. It imports `mjlab_microduck.export.main`, parses arguments, and delegates to `run_export`.

### Basic Export Command

```bash
uv run scripts/export.py <TASK_ID> --wandb-run-path <entity/project/run> [--checkpoint <N>]

```

| Parameter | Description |
|-----------|-------------|
| `TASK_ID` | Registered task name from `mjlab.tasks` (e.g., `Mjlab-Velocity-Flat-MicroDuck`) |
| `--wandb-run-path` | Full WandB run identifier where the checkpoint was logged |
| `--checkpoint` | Optional iteration number; uses latest if omitted |

### Export a Specific Checkpoint

```bash
uv run scripts/export.py Mjlab-Velocity-Flat-MicroDuck \
    --wandb-run-path yourname/microduck/1234567890abcdef \
    --checkpoint 3000 \
    --onnx-file my_policy.onnx

```

This retrieves iteration 3000 from the specified WandB run and writes `my_policy.onnx` to disk.

### Export with Video Recording

```bash
uv run scripts/export.py Mjlab-Velocity-Flat-MicroDuck \
    --wandb-run-path yourname/microduck/1234567890abcdef \
    --video \
    --video-length 200 \
    --onnx-file latest_policy.onnx

```

The `--video` flag generates a visual verification of the exported policy behavior.

## Programmatic Export from Python

For integration into training pipelines or automated workflows, use `run_export` directly:

```python
from mjlab_microduck.export import run_export, ExportConfig

cfg = ExportConfig(
    onnx_file="policy.onnx",
    wandb_run_path="yourname/microduck/1234567890abcdef",
    checkpoint=3000,
)
result = run_export("Mjlab-Velocity-Flat-MicroDuck", cfg)
print(f"Exported ONNX to {result.onnx_path}")

```

The `ExportResult` object provides provenance data including the source checkpoint path and iteration number.

## Understanding the Export Implementation

The core logic resides in [`src/mjlab_microduck/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/export.py). The `run_export` function executes the following sequence:

1. **Environment loading** — `load_env_cfg(task_id, play=True)` initializes the environment in play mode
2. **Configuration retrieval** — `load_rl_cfg` fetches the RL hyperparameters
3. **Checkpoint resolution** — `get_wandb_checkpoint_path` downloads from WandB or locates local `logs/` files
4. **Runner instantiation** — `load_runner_cls` creates an `OnPolicyRunner` and loads weights
5. **ONNX export** — `runner.export_policy_to_onnx` bakes in the normalizer
6. **Metadata attachment** — `attach_metadata_to_onnx` embeds provenance information

## Key Files Reference

| File | Purpose |
|------|---------|
| [`src/mjlab_microduck/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/export.py) | Core export implementation with `run_export` and ONNX handling |
| [`scripts/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/scripts/export.py) | CLI entry point wrapping `export.main` |
| [`AGENTS.md`](https://github.com/pollen-robotics/microduck_rl/blob/main/AGENTS.md) | Export command documentation and usage overview |
| [`README.md`](https://github.com/pollen-robotics/microduck_rl/blob/main/README.md) | Quick-start examples for common workflows |

## Summary

- **Use [`scripts/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/scripts/export.py)** as the primary interface for converting Microduck RL checkpoints to ONNX
- **Always include `--wandb-run-path`** to resolve checkpoint locations automatically
- **Specify `--checkpoint`** for reproducible exports or omit for the latest iteration
- **Call `run_export` programmatically** when integrating into automated pipelines
- **Verify normalizer inclusion** by using the official pipeline—manual conversion risks deployment failure

## Frequently Asked Questions

### Where is the observation normalizer stored in the exported model?

The normalizer is baked into the ONNX graph itself through `runner.export_policy_to_onnx` in [`src/mjlab_microduck/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/export.py). This ensures the exported model performs identically to the training runner without requiring external normalization files.

### Can I export checkpoints stored locally instead of on WandB?

Yes. The `get_wandb_checkpoint_path` function in [`src/mjlab_microduck/export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/export.py) falls back to local `logs/` directories when WandB paths are unavailable. Use the same CLI syntax—the resolver handles both sources transparently.

### What task IDs are available for export?

Task IDs correspond to registrations in `mjlab.tasks`. Common examples include `Mjlab-Velocity-Flat-MicroDuck` and other MuJoCo-based locomotion tasks. Check your training configuration or the `mjlab` task registry for the exact identifier used during training.

### Why does my manually converted ONNX model behave differently on hardware?

Manual conversion typically omits the observation normalizer, causing input distribution mismatch. The official `run_export` routine (lines 52–57 of [`export.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/export.py)) explicitly preserves this component. Always use the provided export tools for deployment-ready models.