In the rainforests of Australia and New Guinea lives one of nature's most remarkable architects: the bowerbird.
Instead of relying on appearance, the bowerbird collects, curates, and arranges objects from its environment into a carefully constructed 3D composition. Every object is chosen. Every placement is intentional.
BowerBot brings that same idea to 3D pipelines.
BowerBot is an AI-assisted OpenUSD scene assembly tool. It helps you go from an empty scene to a structured, usable layout in seconds by:
- finding assets from any connected source (Sketchfab, local disk, company DAM, or any custom provider)
- placing them with spatial awareness
- organizing them into a valid USD stage
It does not try to replace the artist. It accelerates the part that is repetitive, mechanical, and time-consuming.
You stay in control of composition, lighting, and final polish. BowerBot gets you there faster.
BowerBot is:
- A scene bootstrapper for OpenUSD pipelines
- A fast way to go from 0 β structured scene
- A conversational interface for asset search, placement, and layout
- A pipeline assistant that handles technical correctness (units, hierarchy, references)
- A pipeline guardian that catches asset issues before they reach production
BowerBot is NOT:
- A final scene generator
- A replacement for DCC tools like Maya or Omniverse
- A system that produces perfect composition or artistic layouts
Scenes generated by BowerBot are meant to be opened, reviewed, and refined in your DCC.
Think of it as:
"Block out the scene instantly, then refine like a pro."
BowerBot doesn't just place assets β it enforces ASWF USD standards at every step. When an asset doesn't follow production guidelines (wrong root prim type, missing defaultPrim, incorrect metersPerUnit), BowerBot catches it at assembly time and tells you exactly what's wrong and how to fix it.
This means problems that would normally surface weeks later in lighting, rendering, or review β broken references, unit mismatches, non-compliant asset structure β are caught the moment the asset enters the scene. Fix it once at the source, and every downstream department benefits.
"The cheapest bug to fix is the one you catch before it enters the pipeline."
$ bowerbot open coffee_shop
You: Search my Sketchfab for a round bistro table and download it
BowerBot: Found "Round Bistro Table". Downloaded to assets/Round_Bistro_Table.usdz
You: Place it at the center of the room
BowerBot: Placed at /Scene/Furniture/Round_Bistro_Table_01 (5.0, 0.0, 4.0)
You: Find an espresso cup in my local assets and place it on the table surface
BowerBot: Found espresso_cup.usdz. Table surface at Y=0.74.
Placed at /Scene/Products/Espresso_Cup_01 (5.0, 0.74, 4.0)
You: Move the cup to the left side of the table
BowerBot: Moved to (4.7, 0.74, 4.0) β within table bounds.
You: Validate and package
BowerBot: All checks passed. Packaged to scenes/coffee_shop/scene.usdz
Open the .usda in Maya, usdview, Omniverse, or any USD-compatible DCC to refine composition, lighting, and materials.
BowerBot gets you to a clean, structured starting pointβfast. From there, you take it to production quality.
Projects are persistent. Close the session, come back later, and continue where you left off.
- π¦ OpenUSD native : references, defaultPrim, metersPerUnit, upAxis, all correct out of the box
- ποΈ ASWF USD asset folders : automatically assembles assets into ASWF-compliant folder structure (root + geo.usda + mtl.usda). ASWF (Academy Software Foundation) hosts the USD Working Group that defines asset structure standards used across the industry. It works alongside the Alliance for OpenUSD (AOUSD) β the joint effort by Pixar, Apple, NVIDIA, and others driving the core OpenUSD specification.
- π¨ Material binding : apply materials to specific mesh parts, defined inline in asset folder mtl.usda
- π Pluggable skills : connect any asset source (Sketchfab, PolyHaven, company DAM, or build your own)
- π‘ Native USD lighting : create sun, dome, point, area, disk, and tube lights
- π§© Automatic unit handling : assets in cm, mm, or inches are scaled correctly at reference time
- π Geometry-aware placement : uses bounding boxes to place objects on surfaces
- π£οΈ Conversational assembly : guide scene construction through natural language
- π§ Multi-LLM support : OpenAI, Anthropic, and any provider via litellm
- π Project-based workflow : one folder per scene, resumable across sessions
- β Scene validation : ensures technical correctness before reaching your DCC
- π¦ USDZ packaging : export for Apple Vision Pro, Omniverse, or any USD viewer
- ποΈ Onboarding wizard : zero-config setup in 60 seconds
BowerBot is conversational β you tell it what you want and it uses the right tools to build your scene. Behind the scenes, it manages asset discovery, USD composition, materials, lighting, and more.
BowerBot searches for assets across all connected sources, prioritizing what's already available:
-
Local assets first β BowerBot checks your local asset directory (
assets_dirin config.json) for USD files (.usd,.usda,.usdc,.usdz). This includes anything you've exported from Maya, Houdini, Blender, or any DCC tool, as well as assets previously downloaded from cloud providers. -
Cloud providers if needed β If the asset isn't found locally, BowerBot searches connected providers like Sketchfab, and downloads the asset to your local directory. Future skills will add support for PolyHaven, Fab, CGTrader, Objaverse, and custom company DAMs.
-
All downloads are cached locally β Once an asset is downloaded from any source, it lives in your
assets_dirand is available for all future projects without re-downloading.
When you ask BowerBot to place an asset, it handles the USD composition correctly depending on the source:
-
Loose USD geometry (
.usd,.usda,.usdcfrom your DCC exports) β BowerBot wraps it in an ASWF USD Working Group compliant folder structure:asset_name/asset_name.usda(root) +geo.usda. This follows the ASWF asset structure guidelines used by major studios. -
USDZ files (from Sketchfab, DAMs, etc.) β Placed as-is since they're already self-contained packages with geometry and materials bundled.
-
Existing ASWF folders β Copied whole into the project, preserving the folder structure.
When you apply materials to an asset, BowerBot writes them into the asset folder's mtl.usda β not into the scene file. The scene stays clean with only references:
You: Apply wood material to the table top
BowerBot: [searches local assets for "wood" materials]
[discovers mesh parts: table top, legs, frame]
[writes material definition + binding into assets/table/mtl.usda]
Bound /table/mtl/wood_varnished to table top
The result is a production-ready asset folder:
assets/single_table/
single_table.usda <- root (references geo + mtl)
geo.usda <- geometry (untouched from source)
mtl.usda <- materials inline + bindings
The scene file (scene.usda) contains only references and lights β no material data, no geometry copies, no sublayers. Clean and readable:
def Xform "Scene" (kind = "assembly") {
def Xform "Furniture" {
def Xform "Table_01" {
xformOp:translate = (5, 0, 4)
xformOp:scale = (0.01, 0.01, 0.01)
def Xform "asset" (
references = @assets/single_table/single_table.usda@
) { }
}
}
def Xform "Lighting" {
def DistantLight "Sun_01" { ... }
def DomeLight "Environment_01" { ... }
}
}
Open it in Maya, Omniverse, usdview, or any USD-compatible tool to refine.
Requires uv (handles Python automatically).
# Clone
git clone https://github.com/binary-core-llc/bowerbot.git
cd bowerbot
# Install
uv sync
# First-time setup (creates ~/.bowerbot/config.json)
uv run bowerbot onboard
# Create a project and start building
uv run bowerbot new "Coffee Shop"
uv run bowerbot open coffee_shopThe onboard wizard asks for your LLM API key and optional Sketchfab token. Everything is stored in ~/.bowerbot/config.json. One file, one place, no .env.
New to BowerBot? Watch the tutorial playlist on YouTube for setup walkthroughs, scene building demos, and tips for working with USD pipelines.
| Command | Description |
|---|---|
bowerbot new "name" |
Create a new project |
bowerbot open name |
Open a project and start chatting |
bowerbot list |
Show all projects |
bowerbot chat |
Auto-detect project in current directory |
bowerbot build "prompt" |
Single-shot build (auto-creates project) |
bowerbot skills |
List scene builder tools and enabled skills |
bowerbot info |
Show current configuration |
bowerbot onboard |
First-time setup wizard |
BowerBot uses a project-based workflow. Each project is a self-contained folder:
scenes/coffee_shop/
project.json # Metadata: name, created, updated, object count
scene.usda # The USD stage (references only β clean and readable)
scene.usdz # Packaged output (for Apple Vision Pro, Omniverse, etc.)
assets/ # Assets used by this project
single_table/ # ASWF asset folder (auto-created when placing loose geometry)
single_table.usda # Root file (references geo.usda + mtl.usda)
geo.usda # Geometry layer (copied from source)
mtl.usda # Materials defined inline + bindings
CafeTable.usdz # Self-contained asset (from Sketchfab, DAM, etc.)
When you place a loose geometry file from your local assets (.usd, .usda, .usdc), BowerBot automatically wraps it in an ASWF-compliant asset folder. When you apply materials, they're written inline into mtl.usda. USDZ files (from Sketchfab, DAMs, etc.) are placed as-is since they're already self-contained.
Projects are resumable:
$ bowerbot open coffee_shop
# Project: Coffee Shop
# Scene: scene.usda (5 object(s))
You: Show me the scene structure
BowerBot: Scene has 5 objects...
You: Remove Table_03
BowerBot: Removed /Scene/Furniture/Table_03
Skills are pluggable tools the agent uses. Each skill has a Python module for execution and a SKILL.md file that teaches the LLM when and how to use it.
BowerBot's core tools for building USD scenes:
| Tool | Description |
|---|---|
create_stage |
Initialize a new USD scene with standard hierarchy |
place_asset |
Add an asset (auto-creates ASWF folder for loose geometry) |
move_asset |
Reposition an existing object without creating duplicates |
compute_grid_layout |
Calculate evenly spaced positions |
list_scene |
Show current scene with positions and bounding boxes |
rename_prim |
Move/rename objects in the hierarchy |
remove_prim |
Delete objects from the scene |
create_light |
Add native USD lights (sun, dome, point, area, disk, tube) |
update_light |
Modify an existing light's properties |
remove_light |
Delete a light from the scene or asset |
bind_material |
Apply a material to a specific mesh part (writes into asset mtl.usda) |
remove_material |
Clear material binding from a prim |
list_materials |
Show all materials and their bindings |
list_prim_children |
Discover mesh parts inside a referenced asset |
list_project_assets |
Show asset folders with scene usage status |
delete_project_asset |
Remove an asset folder (checks references first) |
delete_project_texture |
Remove a texture file (checks references first) |
validate_scene |
Check for USD errors |
package_scene |
Bundle as .usdz |
Skills extend BowerBot with new asset sources and capabilities. Each skill has a Python module for execution and a SKILL.md file that teaches the LLM when and how to use it.
Local : Searches the asset directory for USD files on disk. Detects ASWF asset folders as single packages and classifies loose files as geometry (geo) or material (mtl).
Sketchfab : Searches and downloads models from your own Sketchfab account in USDZ format. These are your curated assets, not the public marketplace.
Textures : Searches the asset directory for texture files. Finds HDRIs (.hdr, .exr) for dome lights and material maps (.png, .jpg, .tif) for surfaces.
More providers are planned (PolyHaven, Fab, CGTrader, Objaverse), and you can write your own skill for any asset source β see CONTRIBUTING.md.
All settings live in ~/.bowerbot/config.json:
{
"llm": {
"model": "gpt-4.1",
"api_key": "sk-...",
"temperature": 0.1,
"max_tokens": 4096,
"context_window": null,
"summarization_threshold": 0.75,
"num_retries": 3,
"request_timeout": 120.0,
"max_tool_rounds": 25
},
"scene_defaults": {
"meters_per_unit": 1.0,
"up_axis": "Y",
"default_room_bounds": [10.0, 3.0, 8.0]
},
"skills": {
"local": { "enabled": true },
"sketchfab": {
"enabled": true,
"config": { "token": "your-sketchfab-token" }
},
"textures": { "enabled": true }
},
"assets_dir": "./assets",
"projects_dir": "./scenes"
}Switch models by changing one line:
{ "model": "gpt-4.1" }
{ "model": "anthropic/claude-sonnet-4-20250514" }
{ "model": "deepseek/deepseek-chat" }| Model | Tool Calling | Instruction Following | Recommended |
|---|---|---|---|
gpt-4.1 |
Excellent | Excellent | Yes (default) |
gpt-4.1-mini |
Good | Good | Yes (budget) |
gpt-4o |
Poor | Poor | No β skips tool calls, ignores SKILL.md |
anthropic/claude-sonnet-4-20250514 |
Excellent | Excellent | Yes |
BowerBot relies heavily on tool calling and SKILL.md instructions. Models that don't follow tool-calling patterns reliably will produce poor results.
BowerBot automatically manages conversation context to stay within model limits. Two settings control this:
| Setting | Default | Description |
|---|---|---|
context_window |
null |
Context window size in tokens. null = auto-detect from the model. |
summarization_threshold |
0.75 |
Fraction of context budget that triggers history summarization. |
Additional tuning options (usually don't need changing):
| Setting | Default | Description |
|---|---|---|
tool_result_age_threshold |
2 |
User turns before old tool results are compressed. |
min_keep_recent |
6 |
Minimum recent messages always kept verbatim. |
summary_max_tokens |
512 |
Max tokens for the summarization LLM call. |
BowerBot runs a loop where the LLM requests tool calls, BowerBot executes them, and the results are fed back. Complex requests (e.g. binding materials to many mesh parts at once) can require many rounds.
| Setting | Default | Description |
|---|---|---|
max_tool_rounds |
25 |
Maximum LLM β tool exchange rounds per request. Increase if BowerBot stops with "Reached maximum tool-calling rounds" on legitimate workflows. |
BowerBot automatically handles transient API errors:
| Setting | Default | Description |
|---|---|---|
num_retries |
3 |
Retries for rate limits and transient errors (429, 500, 503). |
request_timeout |
120.0 |
Seconds before a request times out. |
- Rate limits and transient errors are retried automatically with exponential backoff.
- Validation errors are fed back to the LLM so it can auto-fix issues and re-validate.
- Permanent errors (bad API key, unknown model) show a clear message without crashing.
src/bowerbot/
agent.py # LLM tool-calling loop and prompt assembly
scene_builder.py # Adapter: translates LLM tool calls into engine operations
cli.py # Click CLI
config.py # Settings from ~/.bowerbot/config.json
project.py # Project management (create/load/resume)
token_manager.py # Context compression and summarization
prompts/ # LLM instructions (markdown files, not code)
core.md # Agent identity and behavior
scene_building.md # Scene building rules and workflows
engine/ # Pure USD operations (no LLM concepts)
stage_writer.py # Scene operations (create, place, light, rename, remove)
asset_assembler.py # ASWF asset folder creation, materials, lights, asset preparation
scene_graph.py # Spatial math (grids, walls, collisions, bounds offsets)
validator.py # USD validation (defaultPrim, metersPerUnit, upAxis, refs)
packager.py # USDZ packaging
dependency_resolver.py # USD file dependency tree walker
skills/ # Extension skills (asset providers, integrations)
base.py # Skill interface and ToolResult
registry.py # Entry point discovery and tool routing
local/ # Local filesystem asset search + SKILL.md
sketchfab/ # Sketchfab API integration + SKILL.md
textures/ # Texture and HDRI search + SKILL.md
schemas/ # Pydantic data models
utils/ # Shared utilities
usd_utils.py # USD introspection (ref paths, asset resolution, reference scanning)
file_utils.py # Filesystem operations (texture copying)
naming.py # Name sanitization for files, prims, and projects
gateway/ # Future: FastAPI + MCP server
Design principles:
- Engine is pure USD : all
pxrcalls live inengine/andutils/usd_utils.py - SceneBuilder is the adapter : translates LLM tool calls into engine operations, wraps results for the agent
- Skills are extensions : asset providers and integrations, discovered via Python entry points
- Prompts are content : stored as
.mdfiles, editable without touching Python - User controls the workflow : the agent follows instructions, not a hardcoded pipeline
- Project-based : one folder per scene, resumable across sessions
- One config file :
~/.bowerbot/config.json, no.env
Every scene BowerBot produces follows OpenUSD best practices and the ASWF USD Working Group asset structure guidelines:
Scene level:
metersPerUnit = 1.0,upAxis = "Y",defaultPrimalways set- Standard hierarchy:
/Scene/Architecture,/Scene/Furniture,/Scene/Products,/Scene/Lighting,/Scene/Props - Scene file contains only references β no material sublayers or inline data
- Wrapper prim pattern: scene-level transforms (position, rotation, scale) are separate from asset-internal transforms
- Validated before packaging (defaultPrim, units, upAxis, references, sublayers, material bindings)
Asset level (ASWF compliant):
- Loose geometry is automatically wrapped in ASWF asset folders on placement
- Folder structure:
asset_name/asset_name.usda(root) +geo.usda+mtl.usda - Root file uses references (not sublayers) per ASWF guidelines for predictable opinion strength
- Materials are defined inline in
mtl.usdaβ no loose material files scattered in the folder - DCC export transforms (Maya pivots, rotations) are preserved untouched inside the reference
- Automatic unit conversion for assets with different
metersPerUnit
What's next for BowerBot β contributions welcome:
- USD Variant Sets β ASWF-compliant variants on asset root prims (materials, geometry, lighting, configurations, and more)
- Scene templates β JSON-driven scene assembly with asset resolution
- DCC exporter β Maya/Houdini tool to export scene layout as BowerBot JSON
- More asset providers β Fab, PolyHaven, Objaverse, CGTrader skills
- MCP Gateway β FastAPI server for web UI and external AI clients
- Web UI β chat panel + live 3D viewport
- BowerHub β community skill registry
BowerBot is open source and welcomes contributions. The best way to start is writing a new skill for an asset provider you use. See skills/sketchfab/ for a complete example.
Read CONTRIBUTING.md for guidelines.
Copyright 2026 Binary Core LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Built with π¦ by Binary Core LLC
"The bowerbird doesn't have the flashiest feathers. It just builds the most compelling world."
