---
title: "Asset to instances model prefab instance authoring chain"
description: "This is the whole path from one base asset to placed content: get a renderable asset, wrap it in a reusable prefab, and instance it once or thousands of times. Read model-authoring-parametric-csg first if you are building the shape itself; read asset-acquisition-strategy first if the catalog might already have it."
engineVersion: v1.0.234
date: 2026-09-28
license: "(c) Gessa, proprietary. Cite with attribution to https://gessa.ai/docs/. Terms: https://gessa.ai/terms/."
canonical: https://gessa.ai/docs/knowledge/playbooks/asset-to-instances/
---

# Asset to instances model prefab instance authoring chain

This is the whole path from one base asset to placed content: get a renderable
asset, wrap it in a reusable prefab, and instance it once or thousands of times.
Read model-authoring-parametric-csg first if you are building the shape itself;
read asset-acquisition-strategy first if the catalog might already have it.

## Step 0: get an asset that actually renders

An entity renders a mesh through a `RenderableComponent` with `shape: "mesh"` and
an `assetId` that points at a `model` asset. The renderer streams that asset's
mesh variant, so the model asset must CARRY a mesh variant. Three ways to get one:

1. **Generate it.** `generation_create_job` (`generation.job.create`) with a model
   capability and `target.importOnSuccess: true` runs the provider and, on
   success, finalizes a project asset that already carries the mesh variant. This
   is the reliable agent path to a fresh custom object. Model, image, texture, and
   audio are the wired modalities; image-to-model capabilities turn a generated
   image into a mesh.
2. **Reuse the catalog.** A published catalog model already carries its variant,
   conditioning, and colliders. Prefer this when a close match exists (see
   asset-acquisition-strategy).
3. **Author it parametrically.** `model_save` (`project.asset.model_document.save`)
   writes a `ModelAuthoringDocument` of primitives plus CSG onto the model asset's
   `rendering.model` slice. IMPORTANT SEAM: `model_save` writes only that authored
   slice and leaves the mesh variant untouched, and there is no agent-callable
   server action that bakes the parametric document into a mesh variant. So a model
   whose only content is a `model_save` document does not render on its own yet; it
   is a durable authoring artifact awaiting a bake. For a shape that must render
   now from the agent surface alone, generate or reuse instead, or use a primitive
   `shape` (`box`, `sphere`, `capsule`, ...) directly on the `RenderableComponent`
   with no mesh asset at all (a cylinder or cone is not a `RenderableComponent`
   shape; it exists only inside a model).

## Step 1: reference the asset from an entity

`project_add_component` a `RenderableComponent`:
`{ "type": "RenderableComponent", "shape": "mesh", "assetId": "<model asset id>",
"visible": true }`. Set a `materialRef` to skin it (see materials-and-looks). For a
plain primitive, use `shape: "box"` (or another primitive) and omit `assetId`.

## Step 2: compose a reusable prefab

A prefab is a named, reusable entity subtree. Author it directly with
`project_create_prefab` (`project.prefab.create`): the request carries the full
`entities` array inline (at least one, a `rootLocalId`, each entity a
`localId`/`name`/`components` record). Put the `RenderableComponent` (and a
`TransformComponent`, scripts, colliders) on the root entity so every instance
inherits them. You do not need live scene entities to make a prefab; the inline
`entities` array IS the prefab body. `project_update_prefab` and
`project_delete_prefab` round it out.

## Step 3a: instance the prefab once

`project_create_entity` (`project.entity.create`) with `prefabId` set (a uuid or
the prefab key) creates one prefab-instance entity in a world. Its effective
components resolve from the prefab, with per-instance `componentOverrides` layered
on top. This is the single-instance path. Note: it places the prefab root as one
instance entity; it does not expand a multi-entity prefab subtree into separate
graph entities, and there is no one-call bulk prefab fan-out on the authoring
surface. For many prefab instances, issue several `project_create_entity` calls.
The instanceSet path below does not draw meshes today (see its note).

## Step 3b: instance one primitive many times (the scale path)

RENDER TRUTH TODAY: the aggregate renderer draws a palette kind with geometry
`box`, `sphere` or `plane` as that primitive, and draws every `cylinder` and every
`mesh` kind (whatever its `meshAssetId`) as a unit box. So an InstanceSet does
NOT place copies of a model yet. For repeated models (trees, rocks, props), place
model entities within the entity budget instead (the renderer batches identical
meshes where eligible); for grass and ground cover on terrain, use a terrain `scatter` (see
terrain-and-heightmaps). Use the InstanceSet aggregate for many copies of a box,
sphere or plane (a voxel field, crates, markers) instead of thousands of entities:

1. Create the resource: `project_create_asset` (`project.asset.create`) with
   `assetKind: "instanceSet"`.
2. `project_apply_instance_set_patch` (`instance_set.patch.apply`) with a
   `configure` op: `layout: "free"` (scattered transforms) or `layout: "grid"`
   (dense voxels), and a `palette` of kinds with `geometry` `box`, `sphere` or
   `plane` (plus optional `materialAssetId`, `tint`). The schema also accepts
   `cylinder`, and `mesh` with a `meshAssetId`, but both render as boxes today.
3. Fill it in the same tool with `populate` (explicit `instances` for free, or
   `cells` for grid), `scatterInstances` (seeded scatter of N over a region), or
   `fill` (a grid box region). One call carries the whole batch; you do not author
   one entity per instance.
4. Place the aggregate: put an `InstanceSetComponent`
   `{ "type": "InstanceSetComponent", "instanceSetAssetId": "<the instanceSet asset
   id>", "enabled": true }` plus a `TransformComponent` on an entity. The renderer
   lowers the whole set to instanced draws per kind and physics to one aggregate
   collider, so the scene stays inside the per-entity complexity budget that
   thousands of real entities would blow.

When mesh kinds do render, the `meshAssetId` in the palette will obey the same
rule as Step 0: a variant-bearing asset (generated or catalog), not a bare
`model_save` document.

## Pitfalls

- A `model_save`-only model has no mesh variant; wiring its id into a
  `RenderableComponent` renders nothing. Generate or reuse for a mesh that must
  show now.
- An instanceSet palette kind with geometry `mesh` or `cylinder` renders as a
  box today, whatever its `meshAssetId`; do not promise a forest or a rock
  field from it.
- `RenderableComponent.shape` must be `mesh` when you pass an `assetId`; leaving a
  primitive shape ignores the mesh.
- `project_create_prefab` needs at least one entity and a `rootLocalId` that names a
  real `localId` in the `entities` array.
- Free layout uses `instances` (transforms); grid layout uses `cells` (integer
  coordinates). Mixing them per op is silently one or the other; match the layout
  you configured.
- Bulk placement of a full behaving prefab (subtree plus scripts) is not one call;
  the instanceSet path multiplies primitive GEOMETRY, not prefab behavior.

## Verify

- `project_get_graph_snapshot` to confirm the model asset, the prefab, the
  instance entity's `prefabId`, or the entity's `InstanceSetComponent`
  (`instanceSetAssetId`, `layout`).
- `qa_capture_renderer_viewport` to confirm the instances actually render (this is
  where a missing mesh variant shows up as an empty capture).
