Prompt the Construct agent
Drive 3D scene editing with OPAL chat
Prompt the Construct agent
When you open the OPAL chat inside Construct, the assistant has direct access to the scene. Good prompts make the difference between a quick edit and a frustrating round trip. This page collects the patterns that work.
What the agent can do
The Construct agent operates through a fixed set of tasks. It cannot run arbitrary code, click UI buttons, or read files outside the scene. Available tasks fall into a few groups:
| Group | Examples | What it does |
|---|---|---|
| Build | construct.scene.build_tree |
Create a whole SDF tree atomically |
| Item editing | construct.item.add, item.rename, item.set_transform, item.duplicate, item.set_parent |
Add, rename, move, duplicate, reparent |
| Selection and grouping | construct.scene.set_selection, scene.get_selection, scene.group_selection, scene.ungroup |
Select items in the tree and the viewport, group them as one undo step, dissolve a group. See selection and grouping tasks |
| Visibility | construct.item.set_tags with the tag hidden |
Hide an item (add the tag) or show it (remove the tag). The same undoable step as a click on the item's icon in the tree |
| SDF parameters | construct.sdf.set_parameter, sdf.set_all_parameters, sdf.set_definition |
Tweak primitive/operator inputs |
| Definitions | construct.definition.add, definition.update, definition.remove, definition.get, definition.publish |
Write a primitive or a transform operator in GLSL for this document, change or remove it, read one, and copy it to your user library. A transform operator can ship an inverse; scene.list_definitions reports whether the editor accepted it. See Write a transform operator |
| Materials | construct.material.add, material.update, material.duplicate, material.list |
Manage the material library |
| Variables | construct.varset.set_variable, varset.add_named, varset.reorder |
Author parametric variable sets |
| Settings | config.get, config.set, config.set-bulk, config.revert, with schema: "construct" |
Read and adjust the settings of the open scene or a camera by id, including the path tracer's budget (ptMaxSamples, ptMaxBounces, ptSecondarySteps, ptSecondaryEpsilon, ptRenderScale, ptTimeBudgetMs, ptStepsPerSubmit, ptMinSamples, ptTargetVariance). See Config OPAL tasks |
| Queries | construct.scene.list_items, scene.get_item, scene.search_items, scene.list_definitions, definition.get, material.list |
Read scene state before acting. definition.get returns a definition's full GLSL source, so the agent can explain how any primitive or operator works. scene.get_item also returns the item's place in the scene (world) and, for a mesh or another non-SDF child of an SDF item or a group, whether Construct could place it (leaf) |
| Bounding volumes | construct.bounds.list, bounds.add, bounds.set, bounds.fit, bounds.activate, bounds.remove, bounds.export |
Frame regions, measure geometry, export meshes |
| Batches | construct.list_batches, construct.undo_batch |
Inspect and undo previous agent batches |
You don't need to memorise these — the agent already knows them. Treat the table as a sanity check when a request feels close to "what tasks does it have?"
Pro Tip
If a request has no matching task, the agent will tell you — it will not pretend. If it ever invents a task name, that's a bug worth reporting.
Patterns that work
1. Describe geometry, not steps
Prefer the goal, not the procedure:
| Less effective | More effective |
|---|---|
| "Add a sphere. Then a box. Then union them." | "Make a soft union of a sphere and a box, smoothness 0.4." |
| "Add 8 spheres in a circle." | "Make a ring of 8 spheres around the Y axis, radius 3, sphere radius 0.5." |
The agent prefers building a whole tree at once via construct.scene.build_tree because that lands as a single undoable batch. Step-by-step prompts force individual ops which are noisier and harder to undo cleanly.
2. Be explicit about parameters
The agent has reasonable defaults but cannot read your mind. Numbers help:
"Smooth subtract a torus (major 2, minor 0.5) from a box (3×1×3) with smoothness 0.3."
Vague phrasing ("a small torus") may produce something that looks wrong. Iterate by quoting the parameter you want to change.
3. Query before you mutate complex scenes
If the scene already has dozens of items, ask the agent to list or search first:
"List all items, then rename the one called 'Ball' to 'Hub'."
The agent will run a query task, see the actual UUIDs/names, and then issue a safe mutation. This avoids referencing items that don't exist.
4. Reference items by name when you can
Names survive across edits; UUIDs don't read well in chat. Either set names when you create things ("name it 'arm_base'") or refer to existing names ("the item called 'cap'"). The agent will resolve names to IDs internally.
5. Iterate, don't retry verbatim
If a result is wrong, describe the difference rather than restating the whole prompt:
"Make the smoothness 0.5 instead of 0.3." "Move the ring up by 0.5 along Y."
The agent keeps conversation context, so deltas are usually all it needs.
6. Use bounding volumes for regions, measurement and export
The construct.bounds.* tasks make regions first-class for the agent:
"Add a bounding volume named 'bed' fitted to the scene, then export it to /tmp/bed.stl."
construct.bounds.list is the discovery call — it returns every volume's
name, extents, parent, flags and stored expressions, so the agent can act
without a second query. bounds.fit measures the real surface (the same
detector the editor's fit buttons run), which makes it the reliable way to ask
"how big is this actually?".
Value fields on bounds.set accept expressions as well as literals —
{"sizeExpression": "[$width, $depth, 20]"} keeps the box parametric, and a
later bounds.list returns the expression verbatim, so set-then-verify round
trips.
What the agent will not do
- It will not invent tasks. If your request requires something Construct doesn't expose (e.g. arbitrary mesh sculpting), the agent will say so. Take that as a real signal, not a hint that you should rephrase.
- It will not silently swallow failures. If a step fails, the response says which steps succeeded and which failed before it proposes a fix.
- It will not click UI for you. OPAL drives the model directly; it does not poke buttons. Anything that lives only in a UI dialog (e.g. exporting a mesh) is currently out of scope.
- It will not read or write files outside the scene unless a specific task is granted that permission.
Undo and the agent
Every agent edit goes through Construct's unified undo stack — the same one Ctrl+Z drives.
- A
build_treecall lands as one undoable batch, no matter how many instances it created. One Ctrl+Z removes the whole tree. - A multi-step plan ("add a box, then a sphere, then union them") lands as multiple steps. You can either Ctrl+Z each, or ask the agent to
undo_batchthe whole thing. - After agent actions, the scene is left in a dirty state, so the title-bar dot appears and Save still works as expected.
See Undo & redo in Construct for details.
Permission modes
The OPAL chat has a permission dropdown that controls how aggressive the agent is allowed to be:
| Mode | Behavior |
|---|---|
| Ask | Every mutating task asks for approval before it runs. |
| Safe auto | Read-only and reversible mutating tasks run automatically; risky ones still ask. |
| All auto | All tasks run without asking. |
Start in Ask until you trust your prompts, then promote to Safe auto for routine work. There's no mode that bypasses Construct's undo stack — agent edits are always reversible.
When something goes wrong
If a task plan fails partway through, the response will list what succeeded and what didn't. Common fixes:
- "Definition 'foo' not found" — ask the agent to
list_definitionsto see what's actually available. - "Cycle detected in children references" — your tree references itself; rename one of the offending instances.
- "Item not found" — the UUID changed (e.g. you reverted a change). Ask the agent to
list_itemsand retry with the new ID. - Plan refused / "Submit exactly ONE task plan per response" — the agent tried to split work across messages. Ask it to combine everything into a single plan and try again.
If you keep hitting the same wall, see Troubleshoot errors for provider-side issues.