| name | create-operator |
| description | MUST READ before calling create_op. Contains required verification, positioning, and error-checking steps. |
Create Operator Workflow
Follow these steps every time you create operators via MCP:
- Choose the correct parent network: NEVER create operators under
/local or /local/*. The /local storage is not for project data. Always place new operators under the project root (e.g., /project1/...) or wherever the user's active network lives. If the user says "create in the current network," use execute_python with result = ui.panes.current.owner.path to find it โ do NOT default to /local.
- Discover the target network:
query_network on the target parent to confirm it exists and see existing operators
- Scan existing layout: Use
get_network_layout on the parent COMP. Note each operator's nodeX, nodeY, nodeWidth, and nodeHeight โ operators vary in size (100โ300+ units wide)
- Plan positions BEFORE creating: Batch-compute grid-aligned positions for ALL operators you intend to create. Signal flow is left-to-right: inputs on the left, outputs on the right. Supporting operators (DATs feeding a TOP, CHOPs feeding parameters) go to the left of or below the operator they feed. Snap all coordinates to the 200-unit grid. See the Positioning Rules section below.
- Create each operator:
create_op with the desired type and name
- Position each operator:
set_op_position to place it at the pre-computed grid position. Auto-placement is NOT acceptable โ it produces messy, unreadable networks. You MUST explicitly position every operator you create.
- Connect:
connect_ops to wire inputs/outputs. Wires must flow left-to-right (positive X). If a wire would go backward, the downstream op is misplaced โ reposition it.
- Set OP-reference parameters with relative paths: If the operator has parameters referencing other operators (Camera, Geometry, Lights, TOP, CHOP, etc.), use sibling names (
cam) or relative paths (../shared/lut) โ NEVER absolute paths (/project1/scene/cam). See parameters.md ยง OP-Reference Parameter Values.
- Verify layout: Call
get_network_layout again. Confirm no overlaps, grid alignment is intact, and signal flows left-to-right.
- Verify errors:
get_op_errors with recurse=true to check for errors and warnings. Fix all errors before considering the task complete
Operator Type Preferences
- Prefer POPs over SOPs for geometry and particle work. POPs (Point Operators) are GPU-accelerated and significantly more performant than SOPs (Surface operators). Only use SOPs when POP equivalents don't exist or when CPU-side geometry manipulation is specifically required.
Positioning Rules
- Every operator MUST be explicitly positioned on the 200-unit grid. Do NOT rely on auto-placement.
- Use actual dimensions, not assumptions. Operators vary in size (100โ300+ units wide). Always base spacing on
nodeWidth/nodeHeight from get_network_layout, never on a fixed offset like "+300 from nodeX".
- Horizontal spacing formula:
next_x = prev_nodeX + prev_nodeWidth + 200 (minimum). Round up to the next multiple of 200.
- Vertical spacing: 400 units between parallel chains.
- Signal flow is left-to-right: Every connected operator must have a higher
nodeX than the operator feeding it. Supporting DATs (pixel shaders, scripts) go to the left of or below the operator they feed into.
- Batch-compute ALL positions before placing anything, using actual operator dimensions from the initial
get_network_layout call.
- After placing, call
get_network_layout to verify no overlaps were introduced.
Key Reminders
- NEVER skip positioning โ auto-placement produces unreadable networks
- NEVER place an operator on top of another operator โ always scan first
- Never rely on
layout() for production networks
- New operators go near related operators, not at origin
- For current network location:
execute_python with result = ui.panes.current.owner.path