To share common data across [builds](../../core-concepts/#build) and [experiences](../../core-concepts/#experience), ReSim supports [assets](../../core-concepts/#asset).

## Why use assets?

Consider a simulation stack that requires a large HD map, 3D environment meshes, and ML model weights. Every experience in your test suite needs this data, but none of it changes between experiences, it only changes when your simulation environment or models are updated.

Without assets, you have two options, neither ideal:

- **Bake the data into your Docker image** - This can bloat the image, slow down CI builds, and force a full image rebuild every time a map or model is updated even if the code hasn't changed
- **Duplicate the data across experience locations** - This can waste storage, make updates error-prone, and increase data transfer costs

*Assets* solve this by letting you define shared data once, revision it independently of your code, and mount it into any build at runtime. Your Docker image stays lean, your experiences stay focused on per-test inputs, and your shared data is versioned and cached.

```
flowchart LR
    Asset["Asset\n(e.g. HD Map)"] -->|"linked to"| Build[Build]
    Experience["Experience\n(e.g. Scenario)"] -->|"run with"| Test[Test]
    Build -->|"run in"| Test
    Test -->|"part of"| Batch[Test Batch]

    subgraph container ["Container at Runtime"]
        AssetMount["/tmp/resim/assets/world/"]
        InputMount["/tmp/resim/inputs/"]
    end

    Asset -->|"mounted at"| AssetMount
    Experience -->|"mounted at"| InputMount
```

## Prerequisites

Assets are stored in cloud blob storage, using the same data sources as experiences. If you have already configured access for your experience data, no additional setup is needed.

If not, see the [Experience Data Sources](../experience-data-sources/) guide for instructions on setting up access to:

- [AWS S3](../experience-data-sources/#aws-s3)
- [Google Cloud Storage](../experience-data-sources/#google-cloud-storage)

## Asset locations

Each asset can have multiple locations. ReSim supports the same location prefixes as experiences:

| Source               | Prefix  | Example                            |
| -------------------- | ------- | ---------------------------------- |
| AWS S3               | `s3://` | `s3://my-bucket/assets/sim-world/` |
| Google Cloud Storage | `gs://` | `gs://my-bucket/assets/sim-world/` |
| Local                | None    | `/assets/sim-world/`               |

For cloud storage locations, each location should have a unique prefix containing the asset files. Anything within that prefix will be synced. We recommend a prefix structure that mirrors your ReSim projects:

Text

```
📂 .
└── 📂 my-project
   └── 📂 assets
      ├── 📂 sim-world
      │  ├── 🗺️ hd_map.bin
      │  └── 📂 meshes
      │     └── 🏙️ urban_env.glb
      └── 📂 ml-models
         └── 🤖 perception_v3.onnx
```

## How asset files are accessed

For cloud-based assets, files are synced from cloud storage and mounted **read-only** at `/tmp/resim/assets/<mountFolder>/` when a build runs. The `mountFolder` is specified when creating the asset and determines where inside the container the files appear.

For example, an asset with `mountFolder` set to `world` and location `s3://my-bucket/assets/sim-world/` results in:

Text

```
/tmp/resim/assets/world/
├── hd_map.bin
└── meshes/
    └── urban_env.glb
```

Your entrypoint script can then read from `/tmp/resim/assets/world/` just as it would from any local directory.

If an asset has multiple locations, all files are synced into the same mount directory. Take care to avoid file or directory name clashes at the root of the locations, just as with [experience locations](../adding-experiences/#experience-locations).

[Asset caching](../../guides/asset-caching/) is enabled by default, so only files that have been added or changed since the last run are downloaded.

Note

Because assets are shared across potentially concurrent jobs, the `/tmp/resim/assets/<mountFolder>/` directory is mounted **read-only**. If your workload needs to modify asset data, copy the files to a writable location first.

## Creating an asset

You can create a new asset like so:

Bash

```
resim assets create \
    --project "my-project" \
    --name "Simulation World" \
    --description "HD map and 3D meshes for urban simulation environment" \
    --locations "s3://my-assets-bucket/my-project/assets/sim-world/" \
    --mount-folder "world" \
    --version "1.0.0"
```

This command returns the UUID and revision number of the created asset. The asset starts at *revision* `0`. Revisions are automatically incremented.

| Flag             | Required | Description                                         |
| ---------------- | -------- | --------------------------------------------------- |
| `--name`         | Yes      | A human-readable name for the asset                 |
| `--description`  | Yes      | A description of what the asset contains            |
| `--locations`    | Yes      | One or more cloud storage locations                 |
| `--mount-folder` | Yes      | The subdirectory name under `/tmp/resim/assets/`    |
| `--version`      | Yes      | A version string (e.g. `1.0.0`, `v2`, a commit SHA) |
| `--cache-exempt` | No       | If set, the asset will not be cached between runs   |

### Examples with different sources

**AWS S3:**

Bash

```
resim assets create \
    --project "my-project" \
    --name "ML Models" \
    --description "Perception model weights" \
    --locations "s3://my-bucket/assets/ml-models/" \
    --mount-folder "models" \
    --version "v3.1"
```

**Google Cloud Storage:**

Bash

```
resim assets create \
    --project "my-project" \
    --name "Calibration Data" \
    --description "Sensor calibration parameters" \
    --locations "gs://my-gcs-bucket/assets/calibration/" \
    --mount-folder "calibration" \
    --version "2024-Q4"
```

## Revising an asset

When the underlying data changes (e.g. a new map version or updated model weights), we create a **new revision** of the asset rather than modifying it in place. This preserves an immutable history of every version of the asset data, enabling reproducibility.

Bash

```
resim assets revise \
    --project "my-project" \
    --asset "Simulation World" \
    --locations "s3://my-assets-bucket/my-project/assets/sim-world-v2/" \
    --version "2.0.0"
```

Each revision increments the revision number (0, 1, 2, ...). The `--version` flag is required when revising -- it should reflect the new state of the data (e.g. a semantic version, date, or commit SHA). You can also optionally update the `mountFolder`:

Bash

```
resim assets revise \
    --project "my-project" \
    --asset "Simulation World" \
    --locations "s3://my-assets-bucket/my-project/assets/sim-world-v2/" \
    --mount-folder "world-v2" \
    --version "2.0.0"
```

You can list all revisions of an asset:

Bash

```
resim assets list-revisions \
    --project "my-project" \
    --asset "Simulation World"
```

## Updating asset metadata

To update an asset's name or description without changing its data:

Bash

```
resim assets update \
    --project "my-project" \
    --asset "Simulation World" \
    --name "Urban Simulation World" \
    --description "HD map and 3D meshes for the urban simulation environment (downtown)"
```

## Associating assets with builds

Assets must be explicitly **linked to a build** before they are available at runtime. This association specifies which asset revision the build should use.

### At build creation time (recommended)

The simplest approach is to attach assets when you create the build. The `resim builds create` command accepts an `--assets` flag with a comma-separated list of asset references:

Bash

```
resim builds create \
    --image "123456789.dkr.ecr.us-east-1.amazonaws.com/my-sim:abc1234" \
    --version "abc1234" \
    --name "Autonomy Build" \
    --description "Path planning v2.3" \
    --branch "my-branch" \
    --project "my-project" \
    --system "full-stack" \
    --auto-create-branch \
    --assets "Simulation World:2,ML Models:5"
```

This creates the build and links the specified asset revisions in a single step. Each asset will be mounted at its respective `mountFolder` when the build runs.

Each entry in the comma-separated list can take one of four forms where the `uuid` is the revision ID:

| Format          | Example              | Behaviour                     |
| --------------- | -------------------- | ----------------------------- |
| `name`          | `Simulation World`   | Links the **latest** revision |
| `name:revision` | `Simulation World:2` | Links a specific revision     |
| `uuid`          | `a1b2c3d4-...`       | Links the **latest** revision |
| `uuid:revision` | `a1b2c3d4-...:2`     | Links a specific revision     |

When the revision is omitted, the latest revision at the time of build creation is used as the static revision for that build. We recommend pinning explicit revision numbers in CI/CD for reproducibility.

### Adding assets to an existing build

If you need to add assets to a build after it has been created, use `resim builds add-assets`:

Bash

```
resim builds add-assets \
    --project "my-project" \
    --build "<build-name-or-id>" \
    --assets "Simulation World:2"
```

### Listing assets for a build

Bash

```
resim builds list-assets \
    --project "my-project" \
    --build "<build-name-or-id>"
```

### Removing assets from a build

Bash

```
resim builds remove-assets \
    --project "my-project" \
    --build "<build-name-or-id>" \
    --asset "Simulation World"
```

### Querying which builds use an asset

Bash

```
resim assets list-builds \
    --project "my-project" \
    --asset "Simulation World"
```

## Archiving assets

Assets that are no longer needed can be archived. Archived assets are hidden from default list views but are not deleted.

Bash

```
resim assets archive \
    --project "my-project" \
    --asset "Simulation World"
```

To restore an archived asset:

Bash

```
resim assets restore \
    --project "my-project" \
    --asset "Simulation World"
```

To include archived assets in a list:

Bash

```
resim assets list \
    --project "my-project" \
    --archived
```

## Recommended CI/CD workflow

We recommend associating assets with builds as part of your CI/CD pipeline. This ensures that every build is pinned to specific asset revisions, making test results fully reproducible.

A typical workflow:

1. **Create and revise assets independently of your code** - When a map, model, or calibration dataset is updated, create a new asset revision. This can be done manually or in a separate pipeline triggered by changes to your data repository
1. **Pin asset revisions in CI** - When your CI pipeline creates a new build, associate it with the desired asset revisions. Store the asset revision numbers as CI variables or derive them from a configuration file in your repository
1. **Update asset revisions deliberately** - When you want to test against a new map or model, bump the revision number in your CI configuration and let the pipeline pick it up

### GitHub Actions example

Extending the [GitHub Actions workflow](../ci/github/), you can pass asset revisions directly when creating the build using the `--assets` flag:

YAML

```
- name: Create build with assets and launch batch
  env:
    RESIM_CLIENT_ID: ${{ secrets.RESIM_CLIENT_ID }}
    RESIM_CLIENT_SECRET: ${{ secrets.RESIM_CLIENT_SECRET }}
  run: |
    resim builds create \
      --project "my-project" \
      --system "full-stack" \
      --image "${{ steps.docker_meta.outputs.tags }}" \
      --version "${{ github.sha }}" \
      --branch "${{ github.head_ref || github.ref_name }}" \
      --auto-create-branch \
      --assets "Simulation World:${{ vars.SIM_WORLD_REVISION }},ML Models:${{ vars.ML_MODELS_REVISION }}"
```

Store `SIM_WORLD_REVISION` and `ML_MODELS_REVISION` as [GitHub Actions variables](https://docs.github.com/en/actions/learn-github-actions/variables) so they can be updated without changing the workflow file.

Tip

Separating asset revisions from code changes means you can update your simulation environment without rebuilding your Docker image, and vice versa. This significantly speeds up iteration when only data has changed.

## End-to-end example

Here is a complete walkthrough using a simulation world asset shared across many experiences.

### 1. Create the asset

Bash

```
resim assets create \
    --project "my-project" \
    --name "Simulation World" \
    --description "Downtown urban environment: HD map, 3D meshes, traffic light configs" \
    --locations "s3://my-assets-bucket/my-project/assets/sim-world/" \
    --mount-folder "world" \
    --version "1.0.0"
```

### 2. Create a build with the asset attached

Bash

```
resim builds create \
    --image "123456789.dkr.ecr.us-east-1.amazonaws.com/my-sim:abc1234" \
    --version "abc1234" \
    --name "Autonomy Build" \
    --description "Path planning v2.3" \
    --branch "my-branch" \
    --project "my-project" \
    --system "full-stack" \
    --auto-create-branch \
    --assets "Simulation World:0"
```

### 3. Run a batch

Bash

```
resim batches create \
    --project "my-project" \
    --build "Autonomy Build" \
    --test-suite "Nightly Regression"
```

When each test in the batch runs, the simulation world data is automatically mounted at `/tmp/resim/assets/world/`.

### 4. Access asset data in your entrypoint

Python

```
import pathlib

map_path = pathlib.Path("/tmp/resim/assets/world/hd_map.bin")
mesh_dir = pathlib.Path("/tmp/resim/assets/world/meshes/")

map_data = map_path.read_bytes()
meshes = list(mesh_dir.glob("*.glb"))
```

Every experience in the test suite gets the same simulation world without any duplication.
