Every tool an agent can call on a default install: 474 tools in 44 domains.
This page is generated from the MCP server source, so it matches the code it ships with.
Startup and discovery 8
Registered at startup.
Return the JSON schema (params, return shape, cost) for a specific HaybaOS command. Call list_tool_categories first to find command names.
Registered at startup.
Check whether the Unreal editor bridge is reachable and report its current identity and status.
No parameters.
Introspect UE reflection: editor-property names+types of a class/struct, member values of an enum, or input/output pin labels of a PCG node (by graph+node) or settings class. Kills trial-and-error API discovery.
Registered at startup.
CALL ANY TOOL BY NAME, whether or not its pack is loaded — the whole catalogue is reachable through here. Pair with hayba_search_tools when you do not know the name. USE_WHEN: any call into an unloaded domain, which is most of them. NOT_WHEN: you are making many calls into one domain — hayba_pack_load gives you native schemas.
Registered at startup.
List the tool packs — domain packs group one subsystem, workflow packs bundle a task across subsystems. Shows tool counts and which are loaded. USE_WHEN: you want the map of what exists. NOT_WHEN: you want a specific capability — hayba_search_tools is faster than reading the map.
No parameters.
Registered at startup.
Register a pack natively so its tools appear in your tool list with full schemas. This is an OPTIMISATION for repeated use, not a prerequisite: hayba_invoke already calls any tool without it. USE_WHEN: you are about to make several calls into one domain. NOT_WHEN: one-off call — just invoke it.
Registered at startup.
FIND A TOOL BY DESCRIBING WHAT YOU WANT, in plain language ("make a menu widget", "why is my landscape flat"). Searches the FULL catalogue, including the tools that are not registered yet — most of them are not, by design. Returns tool names you can pass straight to hayba_invoke without loading anything. USE_WHEN: you do not already know the exact tool name. NOT_WHEN: you know the name — just hayba_invoke it.
Registered at startup.
List all HaybaOS command domains and their commands. Call this first to discover what is available before requesting a specific schema.
No parameters.
Actors 22
Spawn many actors in ONE call from an array of {class_path, location?, rotation?, scale?, label?}. Prefer this over repeated actor_spawn: one round trip and one transaction instead of N.
Transform many actors in one call: each entry sets absolute location/rotation/scale (omitted fields unchanged). Returns per-actor before/after read-back. Undo granularity follows the editor default (one python exec).
Call a BlueprintCallable UFunction on an actor by name, with arguments. The escape hatch for behaviour no dedicated tool exposes — powerful and unvalidated, so it is gated by Plan Mode.
Destroy an actor in the active level.
Copy an existing actor, optionally placing the copy at a new transform. Keeps the source's properties, so it is the cheap way to repeat a configured actor rather than spawning and re-setting everything.
Query level actors by label substring, exact class, tag, and/or a spatial radius around a point. Paginated. Returns {actors[], total, has_more}.
Frame the editor viewport camera on an actor (selects it and aligns the active viewport). For the vision loop before a screenshot.
List an actor's components with their class and name. Use this before object_set_property or actor_call_function, which both need the component name. include_internal also returns engine-created components you normally do not touch.
Reflect every property on an actor with its current value. The discovery step before actor_set_properties — property names must match the UPROPERTY exactly, and this is how you learn them instead of guessing.
Read the current editor actor selection.
No parameters.
Full read-back of a level actor: class, transform, bounds, components, material slots, tags, outliner folder, attach parent. The inspection half of the inspect-then-edit loop.
List what is in the scene: every actor in the active level with its label, class and transform. Start here when you need to know what already exists before changing anything.
Move actors into a world-outliner folder (organisation). Empty folder string moves to the root. Returns per-actor read-back of the applied folder.
Set actor properties from a name to value map. Names must match the UPROPERTY exactly; a name the actor does not have is reported back rather than silently dropped, so read the response instead of assuming it applied.
Replace the editor actor selection with the given actors (by label or path). Returns the resolved selection + any unresolved ids.
Show or hide an actor in the level. This is editor/runtime visibility only — the actor still exists, still ticks and still collides.
Attach an actor to a named socket on another actor, so it follows that socket's transform. The usual way to put a prop in a hand, a light on a fixture, or a decal on a mount point.
Place a new actor in the active level by class — a light, a volume, a blueprint actor, or any registered UClass. To place a StaticMesh or other content asset by its path instead, use actor_spawn_from_asset.
Spawn an actor from a content asset path (StaticMesh or Blueprint) without knowing the actor class. Optional snap_to_floor line-traces down onto geometry. Returns actor_id + final transform read-back. NON-IDEMPOTENT.
Add or remove gameplay tags on an actor in one call. Tagging marks an actor's role so PCG filters and gameplay code can select it by tag rather than by name.
Reposition, rotate, or scale an existing actor.
Asks whether an actor of this class would collide with anything if spawned at this transform, WITHOUT spawning it. Use it before actor_spawn when placing into a populated scene — cheaper than spawning, checking, and deleting. It answers about overlap only: it does not tell you whether the spot makes sense, is on navmesh, or is inside geometry.
Agent memory 7
Delete memory blocks: a single block by id, every block from one agentRole, or (with confirm_all) the entire store. Exactly one of id / agentRole / confirm_all is required.
Dump memory blocks (optionally filtered by scope/agentRole) to a portable JSON file for backup or transfer to another store via memory_import.
Load a memory_export JSON file back into the store. Reports exactly what happened per row: inserted, skipped (malformed), or conflicted (id already existed — left alone under "skip", overwritten under "replace").
List recent memory blocks for a role/scope, most-recent-first, with no keyword filter. Use to browse what has been written, not to search for something specific.
Force retention to run now with an explicit (or default-configured) age/count bound. memory_write already does this automatically after every insert — use this only to prune on demand with a tighter one-off bound.
Search memory blocks by keyword against their intent and content, most recent match first. Use when you remember roughly what a past block was about but not its id.
Write a memory block: an intent, its content, which agent role wrote it, and whether it is private or shared with other agents. Runs bounded retention (age + count) after every write and reports what (if anything) it pruned.
Animation Blueprints 5
Adds a state to an existing state machine in an animation blueprint. It cannot create the state machine itself — that still needs the AnimGraph editor — so on a blueprint with none it answers 'state machine not found', which is a missing prerequisite rather than a bad request. Compile with anim_blueprint_compile afterwards.
Wires one state to another. The transition is created with no rule, which means it is always taken — pair it with anim_blueprint_set_condition unless you actually want an unconditional transition. Pass state_machine_name when two state machines might share a state name.
Compiles an ANIMATION blueprint (ABP) — the animation state-machine asset, not an ordinary class. Reports the compiler errors and warnings. Every anim_blueprint_* write leaves the asset needing this, and an uncompiled ABP keeps running its previously generated class, so state-machine edits look like they did nothing.
Reads an animation blueprint's state machines, their states and transitions, and its variables. Call it before any of the anim_blueprint_* writers: they address a state machine BY NAME, and this is the only way to learn the names — a freshly created anim blueprint has none at all.
Sets the rule on an existing transition, identified either by its id or by the pair of states it joins. A transition with no rule fires immediately, so this is what turns a wired-up state machine into one that behaves. Compile afterwards to find out whether the expression resolved.
Asset search and sources 12
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to describe_assets.
Alias of describe_assets — the agent-friendly name surfaced as the hayba_asset_browse routing tool.
Plugin command. hayba_invoke passes it straight to the editor plugin.
Find assets by path, name substring or class, optionally with thumbnails. The general 'what exists in this project' query — start here when you need an asset path and only know roughly what it is.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to asset_browse.
Wrapped indirectly by the asset-retriever (src/tools/asset-retriever/asset-indexer.ts) which dispatches describe_assets and falls back to list_pcg_assets on unknown_command. Game-thread marshaled.
Download an ambientCG material zip and import into UE.
Search ambientCG for CC0 PBR materials, decals, or 3D models.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Enumerate assets by filter (path/class/tag/source) without semantic ranking. Paginated.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Force a rebuild of the asset index. Use after a batch import outside the MCP-tracked download flow.
No parameters.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Find an asset in the user's UE Content Browser by semantic intent or keyword. Hybrid BM25 + embedding search.
Download a Poly Haven asset (HDRI / texture maps / glTF model) and import into UE.
Search Poly Haven for CC0 HDRIs, textures, or models.
Download a Sketchfab model and import into UE. Requires SKETCHFAB_API_TOKEN env var.
Search Sketchfab for downloadable 3D models. Requires SKETCHFAB_API_TOKEN env var.
Assets and content 23
Create a Content Browser folder (make_directory). Idempotent: a no-op that reports already_existed:true when the folder is already present. Use before authoring/importing assets into a new path.
Permanently delete content assets, verifying on the FILESYSTEM that each file is gone. Pass `paths` to delete a set in one call. READ deleted_count, not requested — it counts .uasset files actually removed. NEVER verify a delete with does_asset_exist or asset_search: the asset registry can report an asset gone while its file is still on disk, and that is exactly how a batch delete reports success for files it never removed. Assets the registry has lost but whose files remain are reported as ORPHANED and must be removed from disk directly.
Copy an asset to a new path. Use this to derive a variant rather than editing the original in place.
Collapse the redirector stubs left behind by renames and moves. USE_WHEN: after a batch of asset_rename / asset_move calls — redirectors that survive into a cook are wasted work and confuse later reference lookups.
What this asset pulls in — everything that must exist for it to load. USE_WHEN: working out why an asset drags in a large cook, or what to migrate alongside it. NOT_WHEN: you want what depends on IT (asset_get_referencers).
Read one asset's metadata (class, path, size, optional thumbnail) by exact path. Use asset_search when you do not yet know the path.
WHAT BREAKS IF I DELETE OR RENAME THIS? Lists every asset that references the given one. USE_WHEN: before asset_delete, asset_rename or asset_move — a reference you did not know about becomes a broken link that surfaces much later. NOT_WHEN: you want what the asset itself needs (asset_get_dependencies).
Both directions of an asset reference graph in one call. Note the lists may be truncated — `capped: true` says so. Prefer the single-direction tools when you need an exact count.
Read an imported asset's reimport source-file path(s) from its AssetImportData — the "where did this come from on disk" question, ahead of a reimport or a broken-source fixup. Probes get_first_filename / extract_filenames / source_data across asset types; returns source_paths:[] when the asset carries no import data (procedural/native assets).
Fail-closed, single-file native import. It pins the fixed connector-cache ancestor/file handles, enforces kind-specific size+magic policy and an exact factory, refuses collisions/overwrite, then discards callback-returned UObject pointers and re-resolves the exact registry path/class/package. Successful imports are normally dirty_in_memory: follow with asset_save on the returned exact path. These checks reduce exposure but do NOT prove crafted files safe for an in-process UE parser; untrusted remote files still require an isolated sanitizer. Future connector continuation additionally requires an opaque single-use grant bound to one enumerated file; directory assertions are not authority.
AssetRegistry metadata for one asset: class, dirty flag, dependency/referencer counts. Read before edit/delete to avoid surprises. Differs from the legacy asset_get_info (C++-backed single-asset info, may see engine-only fields) and from asset_registry_query (bulk discovery/pagination) — use this when you already know the asset path and want its dependency graph. Optional preparation_policy adds evidence and requested/resolved preparation decisions without mutation.
Move an asset to another folder, keeping references working. Leaves a redirector behind; asset_fix_redirectors cleans those up.
Open the asset editor tab(s) for one or more assets (AssetEditorSubsystem.open_editor_for_assets) — pure UI focus, surfaces the asset for the user. Reports which paths were missing.
Inspect and apply supported StaticMesh preparation policies, retaining partial work and unsupported capability results.
Native read-only AssetRegistry query by exact class, asset-name substring, and/or content-path prefix, with deterministic pagination.
Rename an asset in place, fixing up references rather than breaking them. Leaves a redirector behind; asset_fix_redirectors cleans those up. USE_WHEN: the name is wrong. NOT_WHEN: it belongs in another folder (asset_move).
Save dirty packages to disk. With asset_paths: saves each (only if dirty) and reports per-asset success — ok:false when ANY named path fails to save (surfaced in failed[] + warnings[]). Without: flushes ALL dirty map+content packages in one call. The write counterpart to editor_get_state's dirty_packages read. Idempotent (re-saving unchanged bytes is a no-op).
Run the editor data-validation rules over an asset or folder and return the errors and warnings. USE_WHEN: confirming an asset is sound before building on it. NOT_WHEN: checking UI layout — ui_validate is the tool for that.
Reveal + select assets in the Content Browser (UI focus). Probes sync_browser_to_objects then the AssetTools fallback; degrades to a structured error if neither exists.
CHECK PROJECT CONTENT AGAINST MEMORY AND PERFORMANCE BUDGETS: oversized textures, compression that contradicts the asset name, non-power-of-two dimensions, UI textures outside the UI group, meshes with no LODs, excessive material slots, unreferenced meshes. Judged per strictness (relaxed/standard/strict) with every threshold justified in the hint. Reports what it did NOT examine — the audits only cover the heaviest N assets, so a clean result is scoped, never a claim about the whole project. NOT_WHEN: checking a UI screen (ui_validate).
Create and persist a concrete, current UDataAsset subclass after bounded path/name/class preflight. MarkPackageDirty and SaveLoadedAsset are callback boundaries: no raw creation pointer crosses either one, and the target path/class is freshly re-resolved before save and again afterward. Inspect ok, dirty_marked, pre_save_re_resolved, save_attempted, saved (present only when attempted), target_re_resolved, and dirty_known. If any identity, dirty-mark, save, or final readback fact is not trustworthy, nested ok:false plus data_create_unknown_outcome makes the top-level response unknown_outcome; query the exact path before retrying.
Read a bounded property snapshot from a DataAsset. Always inspect reflection_complete, reflection_truncated, properties_omitted_at_least, unsupported_values, and large_integers_as_strings before treating it as complete. Set/map item counts and physical sparse-slot ranges are both capped before iteration, so a small live count cannot hide an unbounded hole scan. Integers outside the exact JSON-number range are decimal strings, never rounded. Soft, weak, lazy, and soft-class wrapper references are reported unsupported/partial instead of falsely serializing an unloaded non-null path as null. Properties with native getters or setters are also unsupported/partial: raw bytes may not be their logical value, and invoking an accessor would execute unaudited code.
Write one bounded scalar property on a DataAsset by name, then inspect copy_completed, ok, verified, target_re_resolved, dirty_marked, dirty_known, dirty (when known), and observed_value or observed_value_omitted. Only exact built-in numeric, enum, bool, string, and name property classes without native getters/setters are accepted and assigned through direct typed setters; JsonValueToUProperty and ImportText are never entered. Fixed arrays, dynamic containers, structs (including user-defined structs), wrapper/object references, interfaces, delegates, optionals, text, field paths, SkipSerialization fields, accessor-backed fields, custom property subclasses, and every other extensible type are refused before staging. Staging and all property pointers end before dirty notification; the command then re-resolves the target/class/property and repeats the accessor/schema gate before fresh bounded readback. It deliberately skips transactions, UObject editor hooks, and persistence. save_requested is always false. If any final identity/verification/dirty fact is untrustworthy, nested ok:false plus stable error makes the top-level response unknown_outcome with mandatory readback; ErrorsOnly cannot hide it.
Audio 15
Inspect live active sounds and physical voice usage from the main audio device, including component ids, asset paths, effective volume/pitch, looping, pause, virtualization/audibility, owner, and managed-component count.
Create an unsaved SoundClass, SoundMix, SoundConcurrency, SoundAttenuation, or SoundSubmix asset at an explicit /Game path. Returns the canonical path and full default readback; call audio_asset_set, then audio_asset_save as the persistence boundary.
Inspect one SoundClass, SoundMix (including class overrides), SoundConcurrency, SoundAttenuation, SoundSubmix, or SoundWave using a stable typed settings vocabulary.
Explicitly save one supported audio settings asset and verify its .uasset exists on disk. Single-target by design so a failure cannot hide partial batch persistence.
Set typed audio asset settings in memory with changed/unchanged key diagnostics and complete typed readback. The actual target class controls which documented keys are legal; incompatible or unknown keys fail before mutation. This command never saves implicitly.
Control a retained AudioComponent: play/stop/pause/resume, fade, set gain/pitch, reset parameters, or set typed MetaSound/SoundCue parameters. Returns live component readback; expired ids fail cleanly.
Play a 2D USoundBase through a retained, non-auto-destroy AudioComponent and return a stable component id plus live play-state readback. Fails if the component never becomes active.
Enumerate USoundBase assets (waves, cues, MetaSound sources) from the asset registry, including subclasses, without loading them. Duration and sample rate come from registry tags, so they are present for most assets but not guaranteed — a missing key means untagged, not zero.
Read linear magnitude, dB magnitude, and phase at explicit frequencies from a previously started master/submix analyzer. Empty or unavailable spectral data is an error, never a zero-filled success claim.
Start Audio Mixer FFT analysis on the master output or one SoundSubmix. Explicit lifecycle: start once, read one or more times, then stop.
Stop a master/submix FFT analyzer that Hayba started. Fails if that target has no tracked analyzer.
Play a sound 2D through a retained AudioComponent. Fails unless the component becomes active and returns component_id plus live play-state/volume/pitch readback. Prefer audio_component_play for the fully typed first-class schema.
Start in-memory Audio Mixer capture of the master output or one SoundSubmix. The matching stop command performs a synchronous, filesystem-verified WAV write.
Stop a tracked master/submix capture and synchronously write a WAV beneath Saved/BouncedWavFiles. Returns the verified absolute path, sample count, channel count, sample rate, and duration; zero samples or an absent file is an error.
Sets the transient primary volume on the main audio device — the master bus, and only that. Use audio_asset_create/set/save with SoundClass and SoundMix assets for category routing. The change is transient and does not persist.
Automation tests 4
Cancels only the tagged UnrealEditor-Cmd child owned by the matching active test_run job. It never enumerates or terminates arbitrary editor processes.
Full entries (errors + warnings) from the last test_run, not just the pass/fail counts. Read this when a test failed and you need the actual assertion text rather than a tally.
No parameters.
Enumerate registered automation tests via FAutomationTestFramework directly (no controller/session-frontend needed). Name-substring filtering: pass filter_pattern (or its alias filter); the response echoes the applied filter so a dropped param is visible.
JOB ENVELOPE (async, non-freezing): unknown project, engine, plugin, and future Hayba tests default to a tagged owned UnrealEditor-Cmd child. Only exact lifecycle-audited pure Hayba contracts use the serving editor's core ticker. Empty or unmatched selections fail closed instead of producing a false green. Poll build_status for structured counts plus execution_mode, child PID/token, exit code, report validity, crash, timeout, cancellation, output-bound, and crash-artifact-count evidence. A crash or never-started child is failed, never skipped. Only one run may be active.
Behavior trees 4
Adds one node to a behavior tree. Build a tree root-first: a composite with no parent_guid becomes the root, then tasks and further composites hang off it by guid. The kind/class mismatch checks are strict on purpose, since a decorator quietly added as a task is the kind of thing you only notice when the AI misbehaves. Marks the asset dirty; asset_save to keep it.
Compiles the tree and reports what the compiler said. Read the warnings, not just ok: a tree with no blackboard asset compiles successfully and then does nothing useful at runtime, and that case is reported as a warning rather than an error.
Re-parents an existing node under a composite. It refuses to connect a node to itself and refuses an edge that would make a cycle, so a tree cannot be wired into one that never terminates. Ordering among siblings is the order children were added, and that order is execution order for a Selector or Sequence.
Reads a behavior tree's whole node graph plus its blackboard keys. Call it first: bt_add_node and bt_connect address nodes by the guids this returns, and those guids come from node object paths rather than being stored, so they stay valid between calls without any bookkeeping on your side.
Blueprints 16
Plugin command. hayba_invoke passes it straight to the editor plugin.
Binds a widget or component event (Button OnClicked, a collision overlap) as an event node — the Details panel's '+' next to an event. Idempotent. Exposed to agents as ui_bind_event; kept agent_callable so hayba_invoke can reach component events too.
Add a component of a given class to a Blueprint's component tree. Changes are staged — blueprint_compile applies them, and nothing takes effect in the level until it does.
Adds a custom event to a blueprint's event graph: a named entry point that timers, other blueprints and the blueprint itself can call. Wire its OutputDelegate pin into a Set Timer by Event node to run it on a timer. Staged until blueprint_compile.
Adds (or returns the existing) override event node such as BeginPlay, Tick, EndPlay, or a widget's Construct/PreConstruct — the entry points a Blueprint starts from. Idempotent: a second call returns the node already there.
Adds a function graph to a blueprint, with an optional signature (inputs, outputs, pure), and recompiles. Every parameter type is checked before the graph is created, so a bad type refuses the whole function rather than leaving a half-built one. Build the body with blueprint_add_node using graph_name = the function name.
Stages a standard event-graph node and returns its GUID plus exact pins. timer_by_function creates K2_SetTimer; set its Object, FunctionName, Time and Looping pins before compile. For entry points use blueprint_add_event (BeginPlay, Construct), blueprint_add_custom_event, or ui_bind_event (widget events).
Add a member variable to a Blueprint and recompile. Object, class and struct references are resolved when added, so a mistyped path is refused with the path in the message instead of compiling into a broken pin. Refuses a name the blueprint already has.
Compile a Blueprint and report errors. Every blueprint_* edit is staged until this runs, so call it before expecting a change to exist — and read `errors`, because a failed compile leaves the old class in place. With save true, a read-only package is refused before compiling with code package_read_only and data.make_writable_hint; nothing changes. Take the file's lock and retry, or pass save:false.
Wires exec or data pins using GUIDs and exact pin names from blueprint_inspect_graph/add_node. The K2 schema rejects invalid type or direction connections.
package_path is the full intended asset path (trailing component = asset name), matching material_create. The handler derives the directory via FPackageName::GetLongPackagePath and re-composes <dir>/<name> so the asset lands at the standard /Game/Dir/Name.Name. A parent of /Script/Engine.BlueprintFunctionLibrary creates a real function library (static functions callable from any blueprint); check blueprint_type in the reply.
Renders a blueprint's EVENT GRAPH as pseudo-English — a fast way to see what a blueprint reacts to without opening it. It covers events only: user-defined function graphs do not appear, so a blueprint documented as three bare events may still have functions. Use blueprint_get_info for structure.
List a Blueprint's components. The read step before blueprint_add_component (to avoid a duplicate name) or object_set_property (which needs the component name).
Read-only exact graph export. Returns stable node GUIDs, pin names/directions/types, every edge, counts, and dirty state. Use this before adding or wiring nodes.
Deletes one node (and its links) from a blueprint graph, for taking back a node placed wrong. Refuses a function's entry or result node, which the function cannot exist without. Staged until blueprint_compile.
Set default property values on a Blueprint's class defaults, so every future instance starts with them. Does NOT change actors already placed in the level.
Sets a literal or object/class reference on an unconnected input pin. Refuses connected pins so values are never silently ignored.
Build and cook 4
JOB ENVELOPE (async, non-freezing): runs UnrealEditor-Cmd -run=cook on a background thread and returns { job_id, status:'running' } IMMEDIATELY. Poll build_status { job_id } for { status:'done', exit_code, output }, or watch hayba_journal_tail.
JOB ENVELOPE (async, non-freezing): runs RunUAT GenerateProjectFiles on a background thread and returns { job_id, status:'running' } IMMEDIATELY. Poll build_status { job_id } for { status:'done', exit_code, output }.
No parameters.
JOB ENVELOPE (async, non-freezing): invokes UnrealBuildTool.exe on a background thread and returns { job_id, status:'running' } IMMEDIATELY — never blocks the editor (the old version blocked the game thread up to 5min). Poll build_status { job_id } for { status:'done', exit_code, output (log tail) }, or watch hayba_journal_tail for live build_job:<id> progress.
Reader for the async job registry shared by build_project / build_cook / build_generate_project_files / test_run. Reads the job entry under its lock by job_id and returns its current status/result. Test jobs expose untruncated scalar pass/fail/skip totals plus a structured test_results object; malformed test results fail closed. Poll this after a build_* / test_run call returns { job_id, status:'running' }.
Editor and PIE 39
Run several editor commands in order under one lease, one step per editor tick, with a fence after each (wait for shaders/asset loads/GC/async loading to settle; gc also collects garbage under an exclusive region/world lease). Returns {job_id} at once; follow it with batch_status. Steps may be wp_region_load {bounds:[minX,minY,maxX,maxY], name?} / wp_region_unload {name?}: the batch owns those World Partition regions and always releases them by the end. Other agents' queued interactive lease requests are served at fences. The batch keeps its own lease alive and runs to the end of its steps even if this server disconnects.
Capture the active editor viewport and return it as an inline image block (plus a small text block with camera/width/height). Set HAYBA_CAPTURE_TO_FILE to also spill the image to a temp file path.
Typed read of a console variable (int/float/bool) via KismetSystemLibrary getters. CAVEAT: UE's typed getters return type-defaults (0/0.0/False) for an unknown or mistyped cvar name, indistinguishable from a real zero value — this tool probes existence via the string getter when available and reports verified:false (plus a note) whenever the value cannot be confirmed real; treat verified:false as "do not trust this value". type defaults to float when omitted, with type_assumed:true in the response. NOT a freeform console runner — use editor_run_console_command for that.
Typed set of a console variable, with a float read-back of the applied value. CAVEAT: the float readback returns 0.0 for a nonexistent cvar, indistinguishable from a real set-to-0 — this tool also probes the string getter (when available on this engine build) and returns ok:false + verified:false + a note when the readback proves the cvar does not exist (mistyped name). When no existence probe is available it stays ok:true with verified:false. Idempotent (retry-safe). NOT a freeform console runner — use editor_run_console_command for arbitrary commands.
Frame an actor in the editor viewport by label — computes camera position from the actor's bounds and aims at its centre, entirely in C++. Roll is always 0 so the view never tilts. This is the correct 'framing tool'; do NOT hand-compute camera angles in python_run.
Read the active editor viewport camera location + rotation. Net-new read counterpart to the legacy editor_set_camera. Rotation is [roll,pitch,yaw] degrees.
No parameters.
Read the editor's output log, filtered by severity or regex and paged with since_line. The first thing to check when a command reported success but nothing happened — UE logs the real reason here.
Editor frame timing: average fps, frame time, and the two thread times. These are whole-editor averages, not a profile of one operation — an idle editor with a compile running reads badly and that is not a scene problem. The thread times are cycle counters converted through FPlatformTime::ToMilliseconds; they were previously emitted RAW under _ms names, so every reading of those two fields used to be wrong by the platform cycle factor.
No parameters.
One-shot consolidated native editor status: current map, who owns PIE (pie: none | user | agent:<owner>) and its phase, selected-actor count, Live Coding / shader / save activity, asset builds in progress, editor health, and the dirty (unsaved) package list (include_dirty:false skips that walk). The master gating probe before any action loop; after a pie_active refusal, poll it until pie is "none".
Triggers a Live Coding compile of the running editor. It is asynchronous: poll the editor log for 'Live coding succeeded' or 'LogLiveCoding: Error', matching on a COUNT of terminal lines rather than presence, because earlier runs are still in the file. Compile ERRORS are not in the editor log at all — they are in UnrealBuildTool\Log.txt. A brand-new handler CLASS still needs a full editor restart; Live Coding cannot register one.
No parameters.
INSPECT ONE LIVE PIE ACTOR without touching editor-world state: transform, bounds, tags, owner and a capped/paginated list of owned components with visibility, collision and component-space evidence. USE_WHEN: understanding a runtime road, controller, pawn or interaction target found by editor_pie_actor_list. Read-only.
WHAT EXISTS IN THE RUNNING WORLD: paginated runtime actors from the selected PIE client/server, with exact path, class and transform. USE_WHEN: finding roads, controllers, interactable actors or spawned state while PIE runs. NOT_WHEN: querying the editor MainMenu world (actor_list). Use the returned actor_path for unambiguous follow-up calls.
Assert a UPROPERTY on a PIE actor holds a value. It is ONE OBSERVATION, not a wait: a command handler runs on the game thread, so it cannot advance the world, and a property it watches can never change while it blocks — an earlier version that pumped the ticker to fake waiting is what crashed the editor. So a false `matched` with `polling:true` means 'not yet', and the caller loops. Read observed_value_last before assuming the property is wrong; it is often the expectation that is.
Send analog input — gamepad sticks and triggers, mouse axes. Applies for the frame it is delivered, so send it again per step for sustained movement rather than expecting it to latch.
Read progress or the final whole-editor timing summary for a PIE capture. Reports aborted status if PIE stops or the selected world changes. If the editor becomes unsafe, the safety gate refuses this command, so an internal abort cannot be retrieved. GPU time, real WP cells, and NPC AI cost remain explicitly unknown.
Start a bounded asynchronous capture of observed editor ticker intervals, whole-editor thread timing, and process physical memory during an already-running PIE session. Returns a capture_id immediately; poll editor_pie_capture_get. Ticker intervals are a whole-editor proxy and the result gives no performance verdict.
CLICK AN EXACT LIVE PIE ACTOR WITHOUT OS INPUT. Reuses the world-projection safety seam, rejects Slate/UMG and Canvas HUD blockers, and repeatedly verifies the canonical local player and first Visibility hit. It dispatches the exact native primitive stage used by APlayerController only after its complete guard state is proven, avoiding InputKey's unchecked re-entrant trace window and all synthetic mouse routes. Hover fails closed because UE exposes no public route that preserves native hover state while guaranteeing zero OS cursor movement. Fails closed for ambiguous clients, absent/hidden/minimized viewports, offscreen/hidden/occluded actors, policy changes and active gestures. USE_WHEN: selecting a road, unit or world actor in background automation with a live visible PIE viewport. NOT_WHEN: hovering, truly headless/NullRHI PIE, or clicking UI controls (editor_pie_click_widget).
CLICK A CONTROL BY WHAT IT SAYS rather than by pixel. Finds the widget whose text, tag or type matches and clicks its centre, preferring an interactive one so matching a label presses the button containing it. Reports how many matched, so an ambiguous choice is visible instead of silent. USE_WHEN: pressing menu buttons. NOT_WHEN: you need an exact position.
Drive the mouse in the running game: move, click, double_click, press, release, drag or scroll. press/release let you hold a button across calls; drag interpolates intermediate positions because widgets that track deltas ignore a single jump. x/y are ABSOLUTE desktop pixels — pass center_x/center_y from editor_pie_widget_tree straight through. Check focused_widget_after: if it says SViewport, the click missed the UI. PREFER editor_pie_click_widget when you know the label.
Press a keyboard or gamepad button in the running game. pressed_and_released schedules the release on a later tick and RETURNS IMMEDIATELY — the key is still down when you read the result, which is what lets the game see the hold at all.
PROJECT A LIVE WORLD TARGET TO A VERIFIED CLICK CANDIDATE. Accepts an actor, owned scene component or [x,y,z]. absolute.available and x/y are present only when the point is on-screen, its PIE window is visible/not minimized, and Slate finds no UMG/modal obstruction. For actor/component clicks require target_click_ready:true too; it combines that Slate proof with the first world Visibility hit. USE_WHEN: diagnosing or clicking a road, unit or world-space target without OS input against a live visible PIE viewport.
Capture the running game. Requests the shot and returns immediately; the engine writes the file a frame or two later, so poll with check_only:true and the same filename rather than assuming it is ready. NOT_WHEN: capturing the editor viewport outside PIE (editor_capture_viewport).
Put a value straight into a text field and tell the game about it. PREFER THIS over editor_pie_type_text when you just need to get past a field — typed characters go wherever focus happens to be, can be eaten by a modal, and are lost if focus moves before the widget commits. Find the field by the text ON it (the placeholder counts, so an empty login box matches "Username"), or omit match to use the focused field. Returns readback+verified, so you know the value is actually in the box. USE_WHEN: filling a login/search/name field. NOT_WHEN: you are testing how the game itself handles keystrokes.
Observe collision sightlines in live PIE. Tests 1-32 explicit eye positions against one target point with one ECC_Visibility trace per sample (maximum 100 m each). Returns clear, blocked with first blocker, or unknown, plus clear/tested ratio. This is a collision sightline proxy, not rendered visibility, walkability, World Partition residency, or performance. Read-only; multiple live PIE worlds require pie_instance.
Type a string into the running game as character input, which is what text fields actually consume. Goes to whatever holds keyboard focus — click the field first. Read characters_accepted_by_ui, NOT characters_sent: the first says the text landed in a widget, the second only says it was sent. USE_WHEN: filling in a name or search box. NOT_WHEN: a single control key like Enter (editor_pie_press_key).
The polling half of a PIE wait: one observation of a property, with `polling:true` when the condition is not met yet, so the caller can loop until it is or until it gives up. It does NOT block for you — the handler occupies the game thread it would need to advance, which is the reason the previous blocking version had to be removed. Same shape as editor_pie_assert; use this name when you intend to loop and that one when you intend a single check.
WHAT IS ON SCREEN RIGHT NOW in the running game: every visible Slate/UMG widget with its type, text and on-screen rectangle. USE_WHEN: before interacting — this is how you find a button instead of guessing coordinates. NOT_WHEN: inspecting a Widget Blueprint asset rather than the live screen (ui_query).
Run an editor console command (stat unit, r.* toggles, LiveCoding.Compile, etc). Arbitrary console access, so it is gated by Plan Mode. Effects are reported by the console, not returned — check editor_get_output_log.
Save every unsaved package, then shut the editor down — in that order. Shutting down with a dirty asset parks the editor on a modal save prompt that nothing can answer, because the MCP port closes first; three editor deaths in one session each cost exactly the assets still unsaved. REFUSES to quit if anything is still dirty after the save pass, and names what is holding it up. Pass quit:false to save everything without shutting down. USE_WHEN: ending a session, or closing the editor to link C++. NOT_WHEN: you only want to save (asset_save).
Position the editor viewport camera for deterministic captures. To AIM it, prefer look_at:[x,y,z] (orientation computed for you, never tilts). Manual rotation is UE FRotator (pitch/yaw/roll), NOT xyz-euler. To simply frame an actor, use editor_focus_actor instead.
Switches the active editor viewport's view mode — wireframe to read geometry density, shader_complexity to find expensive materials, unlit to judge albedo without lighting. This changes what a HUMAN is looking at and does not change back on its own, so put it back to lit when you are done rather than leaving someone else's viewport in wireframe.
Start Play-In-Editor.
Stop the running Play-In-Editor session and return whether one was running. Call it before editor-only operations: many asset and level edits are unsafe or refused while PIE is live.
No parameters.
Tail recent UE log lines (paged via since_line).
Paginated world outliner: level actors with label, class, folder, and attachment parent — the agent's map of the level without dumping the whole world. Folder filters include descendants.
Render a camera view to disk and VERIFY the file landed (magic bytes + dimensions). Accepts either an actor reference or an inline transform. Calls wait_for_idle internally before capture.
Full editor selection probe: selected level actors, content-browser assets, and selected components. Broader than actor_get_selection (adds assets + components) — the context probe for "apply to selection" tools.
No parameters.
Wait for UE subsystems (shaders/assets/gc/pcg/world_tick) to settle before reading back or rendering. Default = shaders+assets+gc+pcg.
Wait for UE shader compilation to settle (or timeout). Thin wrapper around wait_for_idle({subsystems:["shaders"]}).
Foliage 15
Place one foliage instance at an exact transform. USE_WHEN: precise single placement. NOT_WHEN: covering an area — foliage_paint_at scatters at a density instead.
Bulk-add explicit world transforms for a foliage type via EditorFoliageLibrary.add_instances, chunked to avoid a game-thread freeze — the direct authoring verb (fixes the historic silent C++ add stub). NON-IDEMPOTENT (append). UNCERTAIN-API: errors clearly when add_instances is not python-exposed.
Report which UE Python foliage bindings are available (EditorFoliageLibrary + add/get/remove instances, procedural-foliage, HISM, FoliageType_InstancedStaticMesh) plus the engine version and whether a Landscape/StaticMesh collision surface exists — the graceful-degradation gate to call BEFORE any scatter/author op.
No parameters.
Remove ALL instances of a foliage type from the level (destructive, one-undo, requires confirm:true). NON-IDEMPOTENT. UNCERTAIN-API: routes through EditorFoliageLibrary.remove_instances with a null box (all-instances) and errors clearly when unavailable.
Return the number of placed instances of a foliage type across the level — the cheapest read to verify a scatter/add/remove landed. UNCERTAIN-API: degrades to null + a warning when instance introspection is not python-exposed.
List the FoliageType assets in use in the current level, with instance counts. USE_WHEN: before adding or removing foliage, to learn what is already there.
No parameters.
Scatter foliage over a circular area at a density, as the foliage paint brush does. USE_WHEN: dressing terrain. NOT_WHEN: you need one instance at an exact spot.
Remove instances of a foliage type inside an axis-aligned box (center + half-extent) and return the delta count. NON-IDEMPOTENT (delete). UNCERTAIN-API: EditorFoliageLibrary.remove_instances signature/box arg is probed and errors clearly when unavailable.
Remove foliage instances of a type inside a world-space box. Returns how many were removed, so an unexpected zero is visible rather than silent.
Swap the StaticMesh bound to a FoliageType (bulk re-theming — every existing instance re-renders with the new mesh) and read the binding back. Set-to-value (retry-safe).
Enumerate the foliage types used in the level (across all InstancedFoliageActors) with mesh path, density, radius and instance count. Paginated. The read entry point so agents stop guessing foliage type asset paths. UNCERTAIN-API: type enumeration is probed and degrades to [] + a warning.
Deterministic area scatter: ground-trace downward onto landscape/collision inside a circular radius at a target density, with per-instance yaw + uniform-scale jitter and optional align-to-normal, then commit via add_instances. Refuses before UE transport above 10000 candidates; reduce radius/density or split into non-overlapping regions. Same seed to same placement. NON-IDEMPOTENT (append). This is the low-level authoring verb, NOT the PLUMB-validated world_generate flagship. UNCERTAIN-API: needs a collision surface (see foliage_capability_probe.surface_actors) and add_instances exposure.
Create (or reuse if present) a FoliageType_InstancedStaticMesh asset from a StaticMesh with optional initial density — the entry point for all foliage authoring. Reuses an existing asset at the path (retry-safe read-back) but is classified NON-IDEMPOTENT as an asset-create lifecycle op. UNCERTAIN-API: FoliageType factory/class is probed and errors clearly when not python-exposed.
Read every authored param of a single FoliageType (density, radius, scale X/Y/Z intervals, z-offset, align-to-normal, random-yaw, collision, cast-shadow, cull distance) plus mesh path and instance count — the paired read for verify/diff before a foliage_type_set_params write.
Set the core authoring knobs on a FoliageType — density, radius, scale range (X/Y/Z), align-to-normal, random-yaw, world collision, cast-shadow, and cull start/end — then save + read back which keys changed. Set-to-value (retry-safe); omitted fields untouched. UNCERTAIN-API: unknown property spellings land in unchanged_keys[] rather than being silently lost. Returns ok:false (with warnings[]) when NONE of the requested params applied.
Gameplay Ability System 4
Needs the optional HaybaMCPGAS plugin in your project.
Applies a gameplay effect to an actor's ability system component, for checking that an effect does what you think before wiring it into gameplay. Refuses an actor without an ability system component by name. An Instant effect changes attributes and leaves no active handle behind, so an empty handle is not a failure.
Needs the optional HaybaMCPGAS plugin in your project.
Creates a UGameplayAbility blueprint. Lives in the optional HaybaMCPGAS satellite plugin, which auto-disables when the engine's GameplayAbilities plugin is off — so an Unknown command here means the satellite is not installed in this project, not that the command is missing. The ability is created empty; grant it to an actor with gas_grant_ability.
Needs the optional HaybaMCPGAS plugin in your project.
Creates a UGameplayEffect blueprint — the data asset that changes attributes, the unit GAS actually applies. duration_policy decides whether it fires once (Instant), ticks for a while (HasDuration) or persists until removed (Infinite). Part of the optional HaybaMCPGAS satellite.
Needs the optional HaybaMCPGAS plugin in your project.
Grants an ability to an actor's ability system component. It refuses an actor with no UAbilitySystemComponent rather than silently doing nothing, and refuses an uncompiled ability blueprint (no class default object) — both verified live. Grants made in the editor world are editor state, not gameplay state.
History and journal 4
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Re-run stale (dirty) artifacts. Optionally restrict to the subtree under a target URI.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Record a mutation Hayba did not instrument (editor-side edits, manual writes) so the DAG stays accurate.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Show the dependency graph of generated artifacts and which are stale (dirty).
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Return the most recent mutation operations from the journal.
In-editor chat 8
Cheap health snapshot for the copilot stack: sidecar chat routes registered, UE bridge reachable, tool registry size, and the active provider.
Clear the stored BYOK API key for a provider. Destructive — plan-gated when Plan Mode is on.
Set the BYOK API key for a provider. The key is NEVER echoed back or logged — the response contains only a masked last-4. Stored in-memory (TODO Task 6: swaps to the C++ DPAPI vault).
Report, per provider, whether a BYOK key is configured (masked last-4 only, no network call).
Read the configured provider model catalog without model inference. Returns live-listed IDs and capability metadata when available; manual model IDs remain allowed.
List the BYOK provider catalog, flagging which provider is active and whether a key is configured for it (masked last-4 only).
Set the active BYOK provider (and optional model/base URL) for a copilot session.
Preflight-check a BYOK provider: fails clean with {ok:false, reason:"no_key"} (no network call) if a key is required but absent; otherwise runs a minimal completion probe and reports latency.
Instanced meshes 4
Add ONE instance to an InstancedStaticMesh actor. For more than a handful use ism_add_instances instead — a per-instance round trip is the slow way to build a forest.
Plugin command. hayba_invoke passes it straight to the editor plugin.
Add up to 1000 instances to an InstancedStaticMesh actor in one call. This is how you place large repeated geometry (trees, rocks, crowd props) without one actor per item.
Remove every instance from an InstancedStaticMesh actor, keeping the actor and its mesh. Use before re-scattering rather than deleting and respawning the actor.
Plugin command. hayba_invoke passes it straight to the editor plugin.
Spawn an actor whose root is an InstancedStaticMesh component named "ISM". This is the container ism_add_instances fills — create it once, then add instances in bulk rather than spawning an actor per item.
Landscape 10
Create (or reuse if present) a LandscapeLayerInfoObject asset for a named paint layer — the prerequisite for any painting. Reuses an existing asset at the path (retry-safe read-back), but is classified NON-IDEMPOTENT as an asset-create lifecycle op. UNCERTAIN-API: binding into the landscape material slot may require an editor rebuild.
Read the assigned landscape material and hole material asset paths.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to import_landscape.
Alias of import_landscape — the name discoverable in list_tool_categories under the 'pcg' domain. Wrapped by hayba_import_landscape (src/tools/index.ts uses this exact name as the dispatch target). See PR #229 for the game-thread marshal fix.
Deep brief of one landscape: component/subsection layout, XYZ scale, world bounds, material + hole material, paint layers with LayerInfo binding, streaming proxies, and a warnings[] list (missing layout/LayerInfo). The paired read for every landscape write op.
List the paint layers on a landscape with their LayerInfo asset and whether a weightmap is bound — the read tool that exposes painting state before a paint/add-layer write. Includes a warnings[] list when both probes (get_target_layers/editor_layer_settings) return empty.
Enumerate all landscape actors + streaming proxies in the level with component layout, scale, material, world bounds and paint-layer count. Paginated. The read entry point so agents stop guessing landscape actor names.
List the LandscapeSplinesComponents on a landscape with control-point and segment counts — read tool for spline-driven roads/rivers before editing.
Set landscape LOD distribution and/or scalability bias (set-to-value, retry-safe). Omitted fields are left unchanged. Returns the applied values + read-back.
Assign/swap the landscape material asset and read it back. Set-to-value (retry-safe). NOTE: after a material change with new layer slots, layer painting may need a rebuild; use landscape_inspect to check LayerInfo bindings.
Toggle the landscape enable_nanite property (set-to-value, retry-safe). Does NOT trigger the Nanite data rebuild (returns rebuild_needed:true). UNCERTAIN-API: the property exists in 5.x but the apply-build path is C++/pipeline.
Leases and batches 6
Progress or result of an editor_batch job: status running|succeeded|failed, phase, the step it is on, what a fence is waiting for, per-step results, loaded regions, yields to other agents. wait_s polls until done.
Reserve part of the editor (world, World Partition region, asset, actor, PIE, or everything) so other agents do not change it mid-sequence. Never blocks: returns {status:"granted", lease_id} or {status:"queued", ticket, position, holder_owner, eta_s, poll_after_s}; poll by calling again with ticket. Granted leases are renewed automatically until lease_release.
Make this connection act as the owner of a live lease: later commands that name no owner run as that owner, and the owner's orphaned connection-bound leases re-bind here. Needs lease_id and its owner. Connection adoption ends on close; repeat after reconnect. A confirmed adoption also switches this server's process-wide envelope owner and manual lease_id, which remain set across reconnects and unknown-id replies until explicitly changed. It does not start auto-renew or transfer existing renewal timers; renew or release the adopted lease yourself.
Release a lease (lease_id), withdraw a queued ticket (ticket), or release everything you hold (all:true). Send exactly one. Other agents waiting on it can then be granted.
Extend leases you hold. With lease_id, that lease; with nothing, every lease you hold, which also revives leases the editor orphaned when this server's connection dropped. Rarely needed: leases granted by lease_acquire are renewed in the background.
Who holds or waits for which editor resources, the enforcement mode (off / advisory / enforced_for_writes / enforced), the identified agents the editor sees as connected (active_owners), and which of your leases this server is renewing.
No parameters.
Levels and World Partition 9
Create a new empty level asset. Does not open it — follow with level_load to switch the editor to it.
Name and actor count of the level currently open. The cheapest way to confirm which level you are actually editing before making changes.
No parameters.
Moves the editor viewport to a stored bookmark. This changes what a human is looking at, so it is not a neutral read — prefer editor_set_camera when you just need a viewpoint for a capture. NOT VERIFIED LIVE: described from the handler source.
List every level asset in the project. Use it to find the exact path level_load wants.
No parameters.
Open a level in the editor, replacing the current one. UNSAVED CHANGES IN THE CURRENT LEVEL ARE AT RISK — call level_save first.
Save the current level. Optional path is an expected current-level package guard, not Save As; a mismatch is refused before mutation. A map or external actor package requiring a save, including clean packages requiring transient-reference repair, is refused before mutation when its file is read-only (code package_read_only, data.make_writable_hint). Saving runs unattended and cannot open a modal dialog. Returns saved, path, dirty and verified readback for that package only, not external actor packages. Plan Mode gated; disk persistence is not undoable.
Stores a named camera position in the current level so it can be returned to later. Bookmarks live in the LEVEL, so this dirties the map and persists only if the level is saved — do not use it as scratch state on a map someone else is working in. NOT VERIFIED LIVE: described from the handler source, because verifying it means dirtying a real level.
A spatial summary of where actors are: it bins every actor in the editor world onto a fixed 512m grid and reports per-bin counts and the classes that dominate each. These are NOT the World Partition runtime cells — cell ids and bounds will not match the partition's own, which is why the reply says cell_source. Requires World Partition to be enabled on the map; use it to find the busy regions before deciding where to look.
No parameters.
Answers one question honestly: does the current editor world use World Partition. It previously also reported a hard-coded source_count of 0 — a field named for a measurement that always answers zero reads as "measured, none found", so it now names itself not_enumerated instead of inventing a number.
No parameters.
Lighting and post-process 14
Set cinematic color grading on a PostProcessVolume — white-balance temp/tint and global saturation/contrast/gamma/gain (each a Vector4 with alpha=1) — with the correct bOverride_* flags and the struct written back. Set-to-value (retry-safe). UNCERTAIN-API: Vector4 absence degrades a field to a warning + unchanged_keys[].
Set auto-exposure on a PostProcessVolume — method (manual/histogram/basic), EV bias, min/max EV100 — each with its bOverride_* flag set and the struct written back. The single most-asked PP knob as a focused verb. Set-to-value (retry-safe). UNCERTAIN-API: AutoExposureMethod enum absence degrades to a warning.
Configure an ExponentialHeightFog actor — density, height falloff, start distance, inscattering color, volumetric-fog toggle — on its fog component. Set-to-value (retry-safe); omitted fields untouched. UNCERTAIN-API: component/property spellings are probed and land in unchanged_keys[].
Read all key properties of a single light (intensity, color, temperature, attenuation radius, cast-shadows, mobility) — the paired read for verify/diff before a light_set write.
Enumerate every light actor in the level with its light component class and key properties (intensity, color, temperature, attenuation radius, cast-shadows, mobility). Paginated. The read entry point so agents tune lights from real values, not guesses.
Set core properties on an existing light — intensity, RGB color, color temperature (auto-enables use_temperature), attenuation radius, cast-shadows, mobility — then read back. Set-to-value (retry-safe); omitted fields untouched. UNCERTAIN-API: property spellings are probed and land in unchanged_keys[] rather than being silently lost.
Spawn a directional/point/spot/rect/sky light with optional intensity, color, temperature and mobility in one call — the primary way to lay down scene lighting. NON-IDEMPOTENT (actor-create). UNCERTAIN-API: the light actor class is probed and errors clearly when not python-exposed.
Report which UE Python lighting/post-process bindings are available (light actor classes, SkyAtmosphere, ExponentialHeightFog, PostProcessVolume, Lumen/reflection/auto-exposure enums) plus engine version, light-actor count and PPV count — the graceful-degradation gate to call BEFORE any spawn/set op.
No parameters.
Enable/disable Lumen GI and reflections (false = None) and set final-gather quality + max-trace-distance on a PostProcessVolume, each with its bOverride_* flag and the struct written back — the headline UE5 lighting verb. Set-to-value (retry-safe). UNCERTAIN-API: Lumen enums are probed and their absence degrades to a warning.
Read back PostProcessSettings values AND which bOverride_* flags are active on a PostProcessVolume (a value with its override false is inert) plus the Lumen GI / reflection / auto-exposure methods — the paired read so agents see what is actually overridden before a postprocess_set / lumen_configure / exposure_set write.
Enumerate every PostProcessVolume in the level with unbound/priority/blend-weight/enabled — the read entry point so agents target the right volume (or discover none exists) before a postprocess_set / exposure_set / lumen_configure write.
No parameters.
Set PostProcessSettings on a PostProcessVolume — bloom, vignette, film-grain, chromatic-aberration, motion-blur, ambient-occlusion, depth-of-field f-stop — with the correct bOverride_* flag set alongside each value (a value without its override is a silent no-op) and the whole settings struct written back. Set-to-value (retry-safe); omitted fields untouched. UNCERTAIN-API: a field whose value/override set fails lands in unchanged_keys[].
Spawn a PostProcessVolume (unbound/global by default, or box-bounded) with optional priority and blend-weight — the container every postprocess_set / exposure_set / lumen_configure / color_grading_set tweak targets. NON-IDEMPOTENT (actor-create). UNCERTAIN-API: PostProcessVolume class is probed and errors clearly when not python-exposed.
Spawn a complete daytime sky triad — SkyAtmosphere + SkyLight + a directional-light Sun — with an optional sun angle/intensity and skylight intensity in one call. NON-IDEMPOTENT (spawns three actors; re-running adds duplicates). UNCERTAIN-API: each class is probed and a missing one degrades to a warning while the rest still spawn.
Materials 20
Add a new expression node to a material graph. For a MaterialFunctionCall, pass properties.function (asset path) — the node's inputs/outputs are rebuilt immediately (UpdateFromFunctionResource), so its output pins are wirable right away and are returned in outputs[]. No recompile/refresh dance needed.
Create a named-reroute declaration (source anchor) so a value can be referenced by name instead of long wires.
Create a named-reroute usage bound to a declaration by name (replaces a long wire).
Apply a material to an actor in the level (optionally specifying a material slot).
Finalize a material OR material FUNCTION: write it to disk, apply staged settings, surface translator errors + shader optimization stats (materials). Graph edits DEFER the disk write — call this once the graph is complete. NOTE: material functions no longer auto-save either, so after editing a function call material_compile with function_path to persist it (this avoids a half-built function crashing the editor when it is opened/compiled).
Connect two nodes in a material graph or connect a node output to a material property. IMPORTANT for multi-output sources (esp. MaterialFunctionCall): you MUST pick the output pin with from_output (the pin NAME) or from_output_index — otherwise the call is rejected, because defaulting to the first output silently swaps function outputs (e.g. Albedo and F0). Get the real pin names/order from material_get_info.expressions[].outputs[]. May return clutter-prevention suggestions: use named reroutes when a source fans out to 2+ targets, or a reroute knee node when a wire would run backward/over another node.
Create a new material asset.
Create a new material instance derived from a parent material.
Delete an existing node from a material graph.
Break a connection in a material graph — clear a node input or a material output property.
Create a new material function asset in the project.
Inspect a material, material function, or material instance: properties, parameters, and the full expression graph. Parameter expressions expose their authored parameter_name, parameter_type, typed default_value, and explicit metadata/default availability. For materials, material_outputs[] distinguishes stored property wires from compiler-active terminals (important when Use Material Attributes retains ignored legacy wires). Each expression input includes its source edge (from_node + from_output), each node reports output_consumed + reachable_from_output, and dead_nodes[] lists every node NOT reachable from a compiler-active material output — i.e. provably dead, safe to delete (no delete-recompile-compare needed).
List materials and material instances in the project or a specific path.
Move and/or set properties on an existing node in a material graph.
Set a scalar, vector (rgba), or texture parameter on a material instance.
Stage strict master-material settings with observed readback. Set used_with_spline_meshes:true for spline routes, then call material_compile to compile the required permutation and save.
Statically check a material OR material FUNCTION graph for translator-crash-prone wiring WITHOUT compiling: reroutes/named-reroutes used downstream that resolve to no input, and connections to non-existent output indices — both trigger an uncatchable HLSL-translator assert that kills the editor. material_compile runs these same checks and refuses to compile when any fail, so call this first to fix issues safely.
Niagara 14
Activate (optionally reset) or deactivate a live NiagaraComponent to (re)start/stop the effect — needed because many template systems ship auto_activate=false. SET-SUCCESS: applied:true only when the activate/deactivate call ran; reports the resulting active flag. Idempotent set-to-state.
Deterministically tick a live NiagaraComponent's sim by N seconds at a fixed dt (AdvanceSimulation) so a screenshot is reproducible — the deterministic-preview primitive the vision loop needs (a transient effect is invisible at t=0). Refuses before UE transport above 7200 native ticks; increase tick_dt or advance in bounded chunks. SET-SUCCESS: applied:true only when the advance call ran; arg order probed defensively. NON-IDEMPOTENT: each call advances the sim cumulatively, so a repeat/retry compounds simulated time — re-run from a fresh spawn for a reproducible frame.
Probe whether the Niagara plugin and its python surface are available (NiagaraSystem/Component/FunctionLibrary classes, spawn entry points, and which set_variable_* setters exist). The cheap capability gate to call before any other niagara tool so an agent knows what will work in this editor build.
No parameters.
Read a live NiagaraComponent's runtime state: active/paused flags and the system asset it plays — the read-back/verify tool for runtime control ops (pairs with niagara_activate / niagara_param_set).
The HONEST authoring path: duplicate an existing template NiagaraSystem to a new content path and rename it. Since UE Python cannot build emitter graphs, template-instantiation is the supported creation verb (flagged with the engine-limit note). Non-idempotent (creates an asset); idempotent-by-path (returns created:false if the target exists).
Enumerate Niagara components on placed actors in the editor world (system path + active flag), optionally filtered by system substring or active-only, paginated — the "what VFX is currently in the scene" read tool.
List just the exposed USER parameters of a NiagaraSystem asset (name/type/is_data_interface) — the contract an agent needs before niagara_param_set. Cheaper focused variant of niagara_system_inspect. Exposed-parameter enumeration is UNCERTAIN-API; unresolved reflection is surfaced in warnings[].
Set one USER variable on a live NiagaraComponent (float/int/bool/vec2/vec3/vec4/quat/color/position/object) and mark render state dirty. Named niagara_param_set to avoid colliding with the dormant satellite-plugin C++ niagara_set_param command; broadens value_type coverage. SET-SUCCESS: UE setters return void, so applied:true is reported ONLY when a setter probe ran without raising — otherwise ok:false + applied:false + a warning (never ok:true with an unapplied change).
Place a PERSISTENT NiagaraActor in the level (survives save, undoable, selectable) with a system assigned — for level-dressing VFX an author wants to keep and re-edit, vs the transient niagara_spawn_transient. Non-idempotent. Surfaces asset_assigned as a set-success flag (ok:false if the system asset could not be assigned).
Set the DEFAULT value of an exposed user parameter ON the system asset (persists to the saved asset), not just a live component — the param-pack vehicle for customizing instantiated templates. SET-SUCCESS: applied:true only when a setter ran on the exposed-parameter store; the store is UNCERTAIN-API so failures surface ok:false + applied:false + warnings, never a silent no-op. Optionally saves the asset.
Spawn a TRANSIENT (auto-destroy) Niagara system at a world location/rotation/scale — the workhorse placement verb for one-shot VFX. Non-idempotent (each call spawns a new component). Named niagara_spawn_transient to avoid colliding with the dormant satellite-plugin C++ niagara_spawn command; adds scale, auto_activate and dry_run. For a persistent, savable effect use niagara_place_actor.
Dump a NiagaraSystem asset's structure: emitter handles (name/enabled/sim-target), exposed USER parameters (name/type/is_data_interface), data interfaces, fixed-bounds flag, warmup time and effect type. The inspection-first paired read for the VFX authoring tools. Emitter-handle and exposed-parameter reflection is UNCERTAIN-API in 5.7 — anything unresolved is reported in warnings[] rather than guessed.
List/paginate NiagaraSystem assets (path + name) under a content root via the AssetRegistry — the entry read for VFX discovery. Named niagara_systems to avoid colliding with the dormant satellite-plugin C++ niagara_list command; adds prefix + limit/offset pagination.
PLUMB-style read-only check of a NiagaraSystem: GPU emitters without fixed bounds, missing effect type, no emitters. Returns categorised violations with severity; ok:false only on errors. Emitter reflection is UNCERTAIN-API — gaps are reported as info-level violations rather than false positives. (autofix not implemented this wave — fixed:[] always.)
Objects and reflection 6
Existence probe: does an asset path, object path, or level-actor label resolve? Returns {exists, kind}. Cheap guard before a load/edit.
Generic reflection read on any loadable UObject — replaces get_editor_property python_run pokes. Values are UE ExportText strings. PARAMS: `path` (object/asset path) + optional `names` — NOT widget_blueprint_path/widget_name; those belong to the ui_* tools. To reach a widget's slot, pass the slot's full object path as `path`.
Read the property tree of any live UObject by path (asset or object) or by level-actor label, filtered + paginated. The generic read-back primitive (actor_inspect is the richer level-actor variant). Differs from the legacy object_get_property (C++-backed, reads one CPF_Edit property by exact path, no actor-label resolution): use object_inspect to explore/discover an object's shape, object_get_property once you know the exact property path.
Generic reflection write on any loadable UObject (Modify + PostEditChange + MarkPackageDirty) — replaces set_editor_property python_run pokes. PARAMS: `path` (object/asset path) + `properties` (name to value map) — NOT widget_blueprint_path/widget_name/property; those belong to the ui_* tools. For textures prefer texture_set_settings; for material nodes prefer the material_* tools.
Describe a UClass: python superclass chain (MRO) and CDO default-object attribute names, with values included for simple scalar types (str/int/float/bool) — so agents stop guessing class shapes before spawning/editing. (Class flags/interfaces need C++ reflection — not exposed to python.)
Fuzzy-search the UE python type system (classes/structs/enums exposed on the unreal module) by name substring. Turns "what's the class called?" into one call.
PCG 47
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to pcg_create_graph.
Wrapped by hayba_create_pcg_graph (src/tools/create-pcg-graph.ts). Validates before creating; on validation failure returns {created:false, errors:[...]}. A read-only /Game/Hayba/Generated/<name> package is refused before anything is created or replaced (code package_read_only, data.make_writable_hint); the existing graph is kept.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to pcg_execute_graph.
Wrapped by hayba_execute_pcg_graph (src/tools/execute-pcg-graph.ts). Game-thread marshaled. Returning success:true with componentsExecuted>0 is NOT proof that instances were placed — see the 2026-05-23 PCG/landscape postmortem.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to pcg_export_graph.
Wrapped by hayba_export_pcg_graph (src/tools/export-pcg-graph.ts). Game-thread marshaled.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to pcg_get_node_details.
Wrapped by hayba_get_node_details (src/tools/get-node-details.ts) which prefers the cached catalog and falls back to this command.
Extract a repeated node cluster into a reusable subgraph. Transforms the graph object in memory and writes nothing.
Find catalog input pins that accept the type emitted by a specific PCG/PCGEx output pin.
Author a new PCG graph asset from a node and edge description.
Compare a graph description against the asset currently in the project.
Compare a prior PCG node catalog snapshot with the currently loaded catalog and report added, removed, and field-level modified classes.
Run a PCG graph so it generates content in the level.
Export an existing PCG graph as JSON so it can be inspected or transformed.
Render a graph as readable topology text.
Full detail for one PCG/PCGEx node type: its exact input/output pins, properties and defaults.
Return a PCG/PCGEx graph template with read-only catalog preflight. Class and pin checks require live Unreal validation before building or cooking.
Read a PCGExKnowledge node, provider, asset, struct, or concept by exact ID from an optional local bundle. Documentation is a versioned snapshot, not installed UE truth.
List the PCG graph assets that exist in the project.
Suggest the correct pin names for an edge between two nodes.
Promote hard-coded values in a graph to named inputs. Transforms the graph object in memory and writes nothing.
Search local PCGExKnowledge documentation for a node or concept, falling back to the Hayba catalog and registry.
Rebuild the PCGEx node registry from the installed plugin - the SQLite catalog that node search reads.
Find a PCG or PCGEx node by what you want it to DO, searching the node catalog by intent rather than by exact type name.
Rank PCG and PCGEx nodes by fuzzy intent using a CPU-local semantic vector over catalog descriptions, pins, properties, and categories.
Trace attributes through a graph and report where the chain breaks.
Check a PCG graph for disconnected pins, type mismatches and dead branches WITHOUT cooking it.
Prefer hayba_search_node_catalog for ranked search; this is the raw enumeration.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to pcg_list_assets.
Wrapped by hayba_list_pcg_assets (src/tools/list-pcg-assets.ts). Game-thread marshaled.
Add a node of a given PCG settings class to a graph. Returns node_index, settings_class, and node_label — node_label is now the friendly display title (e.g. "Shape : 3D Grid") when the HaybaPCGLibrary C++ helper is available, else it falls back to the settings-class name. For STABLE addressing pass either node_index or settings_class to pcg_wire/pcg_set_prop/pcg_remove_node (class-name and index addressing always work; friendly-title addressing depends on the node having an authored title). New nodes land at (0,0) — run pcg_layout afterward to arrange the graph. To remove a node use pcg_remove_node; to inspect its pins before wiring use pcg_list_pins.
Regenerate an actor's PCGComponent, block on the PCG graph settling (NOT world_tick), and return per-mesh ISM instance counts — all in one call.
[cost=high] [effects=[mutates_scene,gpu_load,wait]] USE_WHEN: after editing a PCG graph, to regenerate an actor AND read back instance counts in ONE call — PCGComponent.generate is async, so a plain generate reads 0 instances in the same call. GROUND TRUTH is result.ism[] ({mesh,count} per ISM) — trust this over pcg_read_node_output (a possibly-stale inspection cache). result.freshness {changed,before,after} proves the counts are from THIS cook, not a prior run. idle.timedOut:["pcg"] is EXPECTED/BENIGN for PCGEx async chains and does NOT mean the cook failed (see idle_note); when result.ism is non-empty the cook succeeded regardless of the pcg idle timeout NOT_WHEN: you only want to read existing instances without regenerating — use pcg_inspect_instances
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to create_graph.
Alias of create_graph (the create-pcg-graph.ts wrapper dispatches the non-aliased form).
Cut a single edge between two PCG nodes: pcg_disconnect(graph, from_node, from_pin, to_node, to_pin). Returns {ok:false, error} if no such edge exists (never a silent no-op). NON-IDEMPOTENT. To delete a whole node and all its wires use pcg_remove_node; to create a wire use pcg_wire.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to execute_graph.
Alias of execute_graph (the execute-pcg-graph.ts wrapper dispatches the non-aliased form).
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to export_graph.
Alias of export_graph (the export-pcg-graph.ts wrapper dispatches the non-aliased form).
Read one PCG node's settings FULLY and UNtruncated: pcg_get_node(graph, node, path?). With `path` ("/"-nested, e.g. "config/fitting/scale_to_fit") returns that single value in full; without it dumps every readable property. Use when hayba_export_pcg_graph truncates a long struct string. Read-only.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to get_node_details.
Alias of get_node_details (the get-node-details.ts wrapper dispatches the non-aliased form).
Read back the Instanced-Static-Mesh instance counts (and a sample transform) produced on an actor by its PCG cook.
Auto-arrange a PCG graph left-to-right by dependency (layered/sugiyama: rank = longest path from a source, nodes y-stacked within a rank). Fixes the "every added node piled at (0,0)" mess. Idempotent. NOTE: node positions may only visibly update after the graph's asset-editor tab is closed and reopened.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to list_pcg_assets.
Alias of list_pcg_assets (the list-pcg-assets.ts wrapper dispatches the non-aliased form).
Alias of list_node_classes.
List a PCG node's input and output pins with their exact labels and allowed types: pcg_list_pins(graph, node) to {inputs:[{label,type}], outputs:[{label,type}]}. Read-only. Use this BEFORE pcg_wire to get the exact pin label (labels are non-obvious, e.g. the graph Input node's output pin is "In", a spline sampler's input is "Spline").
Alias of read_node_output. STALE-READ WARNING: reads a possibly-STALE inspection cache, not live post-cook data — point_count:0 here is NOT ground truth. Use `pcg_cook_and_wait` result.ism[] for authoritative instance counts.
Remove a node from a PCG graph by title (settings-class name, exact/unambiguous-substring) or index. The node AND all its incident edges are deleted. Returns the surviving node list (index+label). NON-IDEMPOTENT: indices shift after removal, so re-fetch via hayba_export_pcg_graph before further edits. This is the destructive counterpart to pcg_add_node.
Scatter a mesh (or weighted mesh set) across a surface in ONE call — build the jittered PCG graph, spawn a bound PCGVolume, generate, and return instance counts. Hard-fails on 0 instances.
[cost=high] [effects=[mutates_scene,gpu_load,wait]] USE_WHEN: to scatter a mesh (or weighted mesh set) across a surface in ONE call — builds the jittered PCG graph, spawns a bound PCGVolume, generates, and returns the instance count. Fails loud on 0 instances. NOT_WHEN: you already have a placed PCGVolume and only want to regenerate/read it back — use pcg_cook_and_wait
Set an editor property on a PCG node's settings. Supports nested struct paths like "distribution_settings/distribution".
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to validate_graph.
Alias of validate_graph (the validate-pcg-graph.ts wrapper dispatches the non-aliased form).
Wire one PCG node's output pin to another node's input pin (by node title or index, and pin label). Pin names are VALIDATED first: if from_pin/to_pin does not exist on the node, no wire is created and the result is {ok:false, error, valid_from_pins, valid_to_pins} — it never silently drops the edge. Use pcg_list_pins to discover exact labels. To cut an existing edge use pcg_disconnect.
STALE-READ WARNING: reads a possibly-STALE inspection CACHE, not live post-cook data. point_count can report 0 (or a prior run's numbers) while the cook actually produced real instances — do NOT treat point_count:0 here as ground truth. GROUND TRUTH for instance counts is `pcg_cook_and_wait` result.ism[] (with result.freshness.changed proving this cook). Returns zero counts if the graph has not been executed. FOLLOW-UP (C++): make this read live post-cook data or return an explicit {stale:true} flag.
Plugin command. hayba_invoke passes it straight to the editor plugin. Also answers to pcg_validate_graph.
Wrapped by hayba_validate_pcg_graph (src/tools/validate-pcg-graph.ts). Pure validation — does not touch UE world state.
Physics 3
Applies an impulse to a primitive component in the editor world and reports the resulting linear velocity. A component that is not simulating physics discards an impulse silently, so that case is REFUSED with a message naming the fix rather than answering applied:true — the old reply was true of the call and false of the world. Turn simulation on with physics_set_simulate first.
Assigns a named collision profile to one primitive component and READS IT BACK. An unrecognised name leaves the component on whatever it had, so a mismatch between requested_profile and profile is returned as an error naming the current setting rather than as a success. Names come from the project Collision settings, e.g. BlockAll, NoCollision, Pawn. This SETS a profile; to find out what is currently intersecting what, use scene_validate_physics.
Turns rigid-body simulation on or off for one primitive component in the EDITOR world. The reply reads the flag back off the component rather than repeating the request, so a component that cannot simulate (no collision, no body instance) is visible as simulating:false with ok:true. Editor-world only: this is not how you drive physics during PIE.
PLUMB constraints 23
Author/upsert a bound constraint: a primitive id + params + a binding (exactly one of {asset, tag}). Validated against the closed primitive set — invalid primitives/params/bindings are rejected.
List the constraint library (optionally filtered to an asset binding).
Draft (does not save) constraints for an asset from its baked profile, using only closed primitives. Review/edit then call plumb_constraint_define.
Remove a constraint from the library by id.
Expand a seed symbol using the stored production rules + the PLUMB constraint store as guards. Returns a PlacementPlan. In dry-run (no UE scene), geometry-dependent constraints self-skip — rejections only reflect TS-evaluable constraints.
Add/update a lesson — the durable [[slug]] knowledge that explains WHY a constraint exists (browsed in the Studio Lessons panel; cited by constraint/validator refs).
List lessons (slug + title + refs).
No parameters.
Remove a lesson by slug.
Add or update a mask (surface = triangle set; volume = translucent shape) on a baked profile. Surface/volume masks are the regions constraints reference.
Remove a mask from a profile by id.
List the COMPLETE closed constraint grammar — the 10 primitives, their gate, hard/soft default, params, and docs. Author constraints by picking one and filling params.
No parameters.
Author/upsert a grammar production rule: an LHS symbol kind (+ optional attribute guards) to an RHS sequence of emit ops (shell/asset/symbol/scatter/decal/fill). Guards are constraint ids that must pass before the production fires.
List all grammar productions in the store.
No parameters.
Remove a grammar production by id.
Layer AI/human qualitative semantics (class, up/front vectors, named affordance regions) onto a baked profile, with optional field locks. Qualitative constraints can only hard-gate on locked fields.
Bake the deterministic geometry/physics half of a Physical Asset Profile. Pass just the asset to auto-fetch bounds from UE (mesh_get_info), or supply origin_cm + extent_cm (+ optional pivot_to_base_cm) explicitly. Persists to the profile store.
Fetch one full Physical Asset Profile by asset path.
List baked profiles (asset_id, archetype, affordance count, locked fields). Feeds the Memory tab.
No parameters.
AI-segment a studied asset: given the study_render color passes, the agent's themed part labels + a box/points per view, runs SAM in the visual sidecar and back-projects to geometry-hugging surface masks (triangles via the world-position pass + a UV display texture), written into the profile. Replaces hand-placed blocky masks.
Add or replace a socket (connection point) on a baked profile. Idempotent on socket id.
AI study entry point: returns the asset's baked profile (if any) + the closed primitive grammar + mask kinds + guidance, so the agent can propose masks (plumb_mask_add) and constraints (plumb_constraint_define).
Drain pending "Study with AI" requests from the Semantic Studio button. Returns the assets to study (then call plumb_study + author masks/constraints for each).
No parameters.
VERIFY PLACEMENT IS ACTUALLY CORRECT: runs the PLUMB constraint library over a set of instances and returns a directional Verdict — per-gate ok, signed value_m (how far off, and which way), and a FixVector telling you exactly how to move each instance to satisfy it. Catches grounding, clearance, alignment, spacing and interpenetration violations the viewport would reveal but you cannot. Hard fails set stopped_at; soft fails accumulate soft_cost. WHY: this is the quantified check that turns "looks placed" into "provably grounded and non-overlapping".
Project 4
Where this project is on disk and which engine built it. Call it before any path-building work rather than guessing a content root, and to resolve the Saved/ directory the editor log lives in. Takes no parameters.
No parameters.
Reads UGeneralProjectSettings — the identity fields shown on the Project Settings > Description page — plus the editor startup map. Read-only; use project_set_settings to change any of them. Fields that were never filled in come back as empty strings, not as missing keys.
No parameters.
Every ENABLED plugin, engine and project alike, with its version and category. This is the reliable way to answer 'is Water/PCG/Niagara available here' before calling a domain that needs one — a capability probe against reality rather than an assumption. Disabled plugins are not listed at all.
No parameters.
Writes project identity settings to the ini files, in two modes: pass section+key+value to write any ini key directly, or pass any of the named fields to write DefaultGame.ini. It flushes to disk immediately — this edits config the whole team shares, so prefer project_get_settings first. Values are strings in both modes.
Sequencer 11
Possess a level actor (by label or path) in the sequence and return its binding GUID — the prerequisite handle for all per-actor tracks. Idempotent by actor label (reuses an existing binding). Probes seq.add_possessable then MovieSceneSequenceExtensions.add_possessable.
Add a camera-cut section binding a camera actor over a time range (seconds) — how a shot gets its camera. Possesses the camera, ensures a master camera-cut track, and sets the section range + camera binding id. Named seq_camera_cut to avoid colliding with the dormant satellite-plugin C++ seq_add_camera_cut command.
Read-back full sequence state: display frame rate, tick resolution, duration (seconds), master tracks, and a paginated list of bindings with per-binding track counts. The inspection-first paired read for the authoring tools (analogue of the C++ seq_get_info, python-only so it works without the satellite plugin).
List/paginate LevelSequence assets under a content root (via the AssetRegistry) with per-sequence master-track and binding counts — discovery before any edit.
Paginated read of a sequence's bindings — GUID, display name, kind and possessed object class — the map an agent needs to find GUIDs for keyframing.
Create a new LevelSequence asset at a content path (the entry point for every cinematic), setting its display frame rate and saving. Idempotent by asset path (returns created:false if it already exists). Named seq_new to avoid colliding with the dormant satellite-plugin C++ seq_create command.
Open a LevelSequence in the Sequencer editor for human review or before render (analogue of the dormant C++ seq_play). Probes LevelSequenceEditorBlueprintLibrary.open_level_sequence then AssetEditorSubsystem.
Set the sequence playback in/out range in seconds (defines what renders and plays). Idempotent set-to-value. Probes set_playback_start_seconds/set_playback_end_seconds then a display-rate frame fallback. Named seq_playback_range to avoid colliding with the dormant satellite-plugin C++ seq_set_playback_range command.
Add a track (transform/float/visibility/camera_cuts/audio/event) to a binding (via binding_guid) or as a master track, returning the track id and class. Named seq_track_add to avoid colliding with the dormant satellite-plugin C++ seq_add_track command.
Keyframe location/rotation/scale on a possessed actor's transform track at a time (seconds), creating the track/section if absent. Closes the C++ gap where the dormant seq_add_keyframe is float-only. Channels resolved by name prefix (Location/Rotation/Scale) + axis suffix; keys authored in tick resolution.
PLUMB-style read-only check of a sequence: dangling bindings (no tracks), empty tracks (no sections), sections out of the playback range, missing/empty camera cut, zero-length playback. Returns categorised issues with severity; ok:false only on errors. (autofix not implemented this wave — fixed:[] always.)
Slivers 4
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Get the full spec (params + determinism + executor) of an installed sliver by id.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Install a sliver from a local file path or an http(s) URL into the user sliver library.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
List installed Slivers (deterministic abstractions). Optional category or namespace filter.
Not callable through hayba_invoke. Load its pack with hayba_pack_load first.
Execute a sliver with concrete parameter values. Returns outputs + declared side_effects + durationMs.
Splines 5
Append a point to a spline, or insert it at `index`. Returns the new point_count, which is the index bound for spline_set_point and spline_remove_point.
Create a spline actor at a location. The spline starts empty — add its shape with spline_add_point. Splines drive roads, rivers, fences, cable runs and PCG spline samplers.
Read a spline's point count, total length and every point's position. The read half of spline editing — call it before set/remove so indices refer to what you think they do.
Delete a spline point by index. Indices of later points SHIFT DOWN afterwards, so remove from the end backwards when deleting several.
Move an existing spline point to a new location, addressed by index. Use spline_get_info first to see the current points — an out-of-range index fails rather than appending.
Static meshes 12
WHICH MESHES ARE COSTING FRAME TIME: static meshes with LOD0 triangle counts, LOD count, material slot count and how many things reference them. USE_WHEN: a scene is heavy and you need to know where the triangles and draw calls actually are.
Read a StaticMesh's local bounds: origin, box extent, sphere radius, and min/max corners (cm). The cheap standalone sizing readback (BoxSphereBounds), distinct from the C++ mesh_get_info bounds used by the physical-asset baker.
Plugin command. hayba_invoke passes it straight to the editor plugin.
Triangle and vertex counts, the LOD chain with its screen sizes, material slots and local bounds for one static mesh. Called from TS by the physical-asset baker and world_generate for bounds, so it is documented here rather than surfaced as its own agent tool: agents should reach for mesh_get_bounds / mesh_get_lods / mesh_get_materials, which split the same information and do not load the asset whole.
Report a StaticMesh's LOD count and per-LOD triangle/vertex counts (StaticMeshEditorSubsystem, falling back to EditorStaticMeshLibrary). Degrades to lod_count with null tri/vert when the per-LOD getters are unavailable on this build.
List a StaticMesh's material slots: slot index, slot name, and the assigned material asset path (from static_materials). The map an agent reads before mesh_set_material_slot.
List a StaticMesh's named sockets with relative transform (location/rotation/scale) — the attachment points an agent needs before snapping child actors onto a mesh. Reads the `sockets` property defensively.
Enumerate static meshes from the asset registry without loading any of them — the cheap way to find something to place or inspect. Always pass path_prefix on a real project unless you actually want engine content in the results. Exact subclasses only, so a mesh subclass is not listed.
Enumerate every UDynamicMeshComponent in the editor level with tri/vert/material counts — replaces the hand-rolled 'loop all actors to DynamicMeshComponent to tris' python_run for inspecting PCG/grammar output. Pair with mesh_topology_stats(actor_label=...) for a full weld/manifold verdict on a specific one.
Sets a LOD's screen size (and optionally its reduction target) on a static mesh, then rebuilds it. Returns ok, path, lod_index, screen_size and reduction_percent_triangles readback. Plan Mode gated and transactional. Editor-only, and it modifies the asset — save it afterwards. It REFUSES a mesh with any zero-UV LOD, because the rebuild would hit an engine assert and take the editor down with it; that refusal is a real limit of the asset, not a bug in this command.
Assign a material/MaterialInstance asset to a StaticMesh material slot by index, saving the mesh and reading back the applied material path. Probes StaticMeshEditorSubsystem.set_material then the static_materials array. Idempotent set-to-value (assigning the same material twice is the same state). Sets the material ASSET on the slot — use material_* tools to edit the graph.
Stats-only alias of mesh_extract (raw geometry arrays forced off). Use to get a fast weld/winding/holes verdict: non_manifold_vertices==0 && degenerate_triangles==0 && connected_components==1 && a small explainable boundary_edges == healthy.
Textures 5
WHICH TEXTURES ARE COSTING MEMORY: every Texture2D ranked by resource size, with dimensions, format, LOD group and compression, and a flag where the name implies a role the compression contradicts. USE_WHEN: chasing memory or load times. NOT_WHEN: inspecting one texture you already know about (texture_get_info).
Inspect a Texture2D: dimensions, source/platform format, mip count, compression settings, LOD group, sRGB, never-stream, address modes.
List Texture2D assets, optionally filtered by path prefix.
Set a texture's compression (TC_*) and optionally LOD group + sRGB. Re-imports the texture resource. For other properties (mip gen, max size, filter, address, ...) use texture_set_settings.
Set any texture properties at once via reflection. Aliases: compression_settings, lod_group, srgb, never_stream, address_x, address_y, mip_gen_settings, max_texture_size, flip_green_channel, filter, virtual_texture_streaming, lod_bias. Any raw UTexture UPROPERTY name also works. Re-imports the resource after applying.
UMG widgets 31
Add a widget (Button/TextBlock/Image/panel/…) to an existing Widget Blueprint tree, optionally under a named panel, with slot layout props. Marks the BP structurally modified + dirty.
Make a widget react to input: bind a widget event (Button OnClicked, OnHovered, OnPressed) to an event node in its Widget Blueprint, then wire the node's "then" pin to what should happen. Idempotent - binding again returns the existing node. Expose the widget with ui_set_variable and compile first.
Bind a widget property (Text, ToolTipText, Visibility, bIsEnabled) to a blueprint variable - the designer Bind dropdown. This is how a reusable pure-Blueprint component gets a settable caption without a C++ base class. Omit variable_name to clear the binding.
Build a whole widget subtree from one nested spec - {class, name?, properties?, slot_props?, children?}. One call instead of one ui_add_element per widget. Depth-first in order; on failure the widgets already created are KEPT and named in the error so you can see exactly how far it got.
Compile a Widget Blueprint asset. Returns compilation status (UpToDate/Error/Dirty), warnings, and errors. Optionally save on successful compilation.
"Make this look like that one" — copies a working widget's brush (draw_as, resource, margin, tint, size) and text style (font, typeface, size, colour) onto another. Copies STYLE ONLY: slot layout and text content stay the target's, so matching a look cannot wreck a layout. Use dry_run to see what would be copied. USE_WHEN: one widget already looks right. NOT_WHEN: you know the values (ui_set_brush / ui_set_text_style) or want the widget itself (ui_duplicate_element).
CREATE A NEW MENU, SCREEN OR HUD as a UMG Widget Blueprint asset — the designer-editable kind an artist can also open. Seeds a root CanvasPanel ready for content. USE_WHEN: starting any new piece of UI. NOT_WHEN: adding to an existing one (ui_add_element / ui_build_tree), or inspecting what a running game is showing (editor_pie_widget_tree).
Duplicate a widget and its entire subtree, cloning properties and slot layout. The copy and every duplicated descendant are registered as designer variables. Use for repeated rows, cards and list entries.
Get detailed info about a Widget Blueprint: full widget tree with properties, variable GUIDs, slot layout, and typed property values per widget.
Resolve the real on-screen geometry of every widget by running a Slate prepass on the compiled widget class, plus per-widget font, measured text width and brush facts. This is the measurement layer ui_validate judges. layout_resolved:false means the blueprint could not be instantiated (usually: compile it first) and geometry is absent rather than zero.
List the Widget Blueprints that exist in the project, with the _C class path needed to use one as a child widget or as a parent class. Reads the asset registry, so no blueprint is loaded.
List UMG widget classes that can be added via ui_add_element or ui_replace_element. Native classes by default; pass include_blueprints to also list your own Widget Blueprint classes, or panels_only to narrow to containers.
Measure a string exactly, through the Slate font measure service, in a widget real font or an explicit one. Returns rendered width/height plus how many characters fit in the box: the actual string, typical mixed-case prose, and the worst case if every glyph were the font widest. Use this to size a label for variable-length runtime text (player names, item names, translations) BEFORE it clips in game.
Reorder a widget among its siblings. Child order is draw order and tab order in box panels. Slot layout is preserved across the move; an out-of-range index is rejected with the valid range.
Return the widget tree of a Widget Blueprint - per-widget name, class, slot, variable GUID and typed properties. Pass name_pattern / class_filter / flatten to get a flat list of matching widgets instead of the whole tree.
Remove a widget from a Widget Blueprint designer tree, together with its whole subtree. Variable GUIDs for every removed descendant are purged, not just the named widget. Removing the root requires an explicit replacement_root.
Rename a designer widget, carrying its variable GUID across so existing bindings keep resolving. The widget name IS the variable name the graph and C++ BindWidget use, so this is an API change.
SEE a Widget Blueprint: draws it to a PNG and returns the image inline, with no PIE session and no editor restart. out_path accepts only an optional clean PNG filename; Hayba writes it without overwrite under Saved/Screenshots/Hayba and returns the resolved absolute path. This is how you check fonts, colours, brushes, spacing and overflow in seconds instead of a rebuild-and-play cycle. Read coverage_percent — 0 means the widget drew nothing and the PNG is blank. USE_WHEN: you want to look at the UI. NOT_WHEN: you want numbers (ui_layout_snapshot) or a verdict (ui_validate).
Move an existing designer widget from its current parent to a new parent panel. Preserves widget instance and GUID. Creates the correct slot class for the new parent.
Replace a designer widget with a different class at the same position. Preserves parent, child index, slot layout, and the complete child subtree by default (preserve_children); optionally preserves the name, variable GUID (preserve_guid), and every property the two classes share by name and type (preserve_properties). Set preserve_children:false only to explicitly delete descendants.
Save a Widget Blueprint package to disk. Optionally compile before save. Returns whether the save succeeded and whether the package is still dirty.
Search within a Widget Blueprint for widgets matching a name pattern or class filter. Returns matching widget paths and properties.
Set the brush on an Image or Border widget in a Widget Blueprint: texture/material resource, tint color, draw style, image size, and 9-slice margins.
Rewrite every text widget still on an engine default font (Roboto) onto a project font, in one call. New TextBlocks always arrive as /Engine/EngineFonts/Roboto "Bold" and ui_set_text_style only changes the fields you pass — so setting size and colour but forgetting font_asset+typeface silently keeps Roboto and still reports success. Use dry_run first to see what would change. USE_WHEN: a blueprint has the default font anywhere. NOT_WHEN: restyling one widget (ui_set_text_style).
Set a single arbitrary property on a designer widget by name and value. Typed wrapper around ui_set_widget_properties for the common case of changing one thing.
Set CanvasPanel slot layout on a designer widget: anchors (as `anchors` [minX,minY,maxX,maxY], or `anchors_min`+`anchors_max` [x,y] pairs), `position`, `size`, `alignment`, `z_order`, `auto_size`; box/grid slots take `padding`, `fill`, alignments, row/column. Anchors + position + alignment are committed to the CanvasPanelSlot atomically (one LayoutData write). Unknown parameter names are REJECTED with a validation error rather than silently dropped. For non-Canvas slots use the slot_props field in ui_set_widget_properties.
Set text styling on a TextBlock widget in a Widget Blueprint: font, typeface, size, letter spacing, color, outline, shadow, justification. All values survive compile+save+restart.
Expose (or hide) a widget as a blueprint variable - the designer Is Variable checkbox. Without it the graph and C++ BindWidget cannot reach the widget at all.
Set the visibility of a designer widget in a Widget Blueprint. Changes survive compile, save, and editor restart.
Generic tool: set named properties and/or slot layout on a designer widget. Operates on the authoritative WidgetTree (not the generated template). Property values may be nested objects for struct properties (Brush, Font). Reports per-key outcomes: succeeded, failed_properties, unknown_slot_props. NOT transacted - these edits deliberately stay out of the editor undo stack, because the transaction buffer can pin PIE references and crash the editor. Prefer the typed tools (ui_set_property, ui_set_text_style, ui_set_slot_layout) for common operations.
CHECK A SCREEN AGAINST GAME-UI STANDARDS: runs the UI rule catalogue over a real Slate layout and reports precise, actionable findings - text that overflows (and the exact character count at which it does), labels with no room for translation growth, content inside TV title/action-safe margins, touch targets below the platform minimum, overlapping siblings, contrast below WCAG, controls gamepad focus cannot reach, and performance traps. Judged per platform (pc/console/handheld/mobile) and per strictness (relaxed/standard/strict). USE_WHEN: after building or editing a Widget Blueprint, and before calling the screen done. NOT_WHEN: you only need the tree (ui_query) or one measurement (ui_measure_text). Rules that need geometry are reported as SKIPPED when the layout cannot be resolved - never as passing.
Unreal docs 4
CHECK A PROPERTY OR FUNCTION EXISTS BEFORE YOU USE IT. Lists the real properties of a class (name, C++ type, category, tooltip, whether it is editable and blueprint-visible) and functions (blueprint-callable, event). USE_WHEN: before setting a property by name or calling a function — a wrong name is otherwise a silent no-op or a failed edit. Pass include_inherited when a member you expected is missing; it is usually declared on a parent.
Inspect a UE class in the running editor: full inheritance chain, class flags, and how many properties and functions it has. USE_WHEN: confirming a class exists and what it derives from before using it as a parent or a cast target.
FIND THE REAL NAME OF A UE CLASS instead of guessing. Substring search over every class loaded in the running editor. USE_WHEN: you are about to write a class name from memory. NOT_WHEN: you already have the exact path.
SEARCH THE INDEXED UE C++ API BEFORE GENERATING CODE. Returns signatures, declaring types, include paths, short source docs and explicit deprecation metadata from the configured versioned Engine/Source database. USE_WHEN: you need source-level intent or want to avoid a deprecated API. NOT_WHEN: you need properties reflected by the currently loaded editor; use docs_lookup_api. Search is deterministic keyword mode; semantic search is reported unavailable until an embedding corpus is installed.
Validator 7
Clear the validator history. Requires { confirm: true } to actually wipe.
Read persisted validator findings (the record of everything validator_run / plumb_validate caught). Filter by limit / since_iso / include_resolved / rule_ids.
Mark a validator finding as resolved (or restore it). Identifies the finding by its ISO timestamp.
List the validator rule catalog — every post-condition check and bound PLUMB constraint that validator_run / plumb_validate will evaluate, with each rule's message, hint, refs, and disabled state.
CATCHES SILENT WRONGNESS YOU CANNOT SEE: runs the validator rules over the current scene and returns concrete post-condition findings — actors floating above ground, interpenetrating meshes, off-grid/mis-scaled placements, missing expected results, and PLUMB constraint violations. Pass scope='all' (default) or { rule_ids: [...] }; findings persist to history and the Validation panel. WHY: you have no viewport — this is how you verify placement actually landed correctly instead of assuming it did.
Enable or disable a validator rule by id. Persists to .scratch/validator-config.json.
Read or set validation strictness. Three modes — relaxed (only what is broken), standard (plus established conventions), strict (plus house-style polish) — set globally or per category (ui, pcg, landscape, material, blueprint, python, asset, general). A rule declares the lowest mode at which it fires, so raising strictness only ever adds findings. Call with no arguments to read the current settings. Persists to .scratch/validator-config.json, the same file the editor Configure panel reads.
Water 11
Deep read-back of one water body: component validity (catches placeholder-stub spawns), wave presence, water/underwater material refs, affects-landscape flag, owning zone and bounds. The paired read for validate-before/after-mutate. Property/material reflection is probed with alternate names; anything unresolved surfaces in warnings[].
Spawn an AWaterBodyLake at a water level with an optional footprint radius and label. Lakes are a core terrain-water feature. NON_IDEMPOTENT; supports dry_run. NOTE: closed-spline shoreline shaping is UNCERTAIN-API and deferred — the body spawns with its default footprint and a warning is surfaced. Degrades cleanly if Water is off.
Paginated introspection of all water bodies in the level: class, label, owning-zone binding (AABB containment), bounds and whether waves are attached. The inspection-first read to call before any water mutate. Degrades cleanly to a plugin-disabled envelope if the Water plugin is off.
Spawn an AWaterBodyOcean at a world location with an optional scale and label, and confirm an optional owning WaterZone (zones bind bodies by overlap). The single most common worldbuilding water op — an outcome verb over raw actor_spawn. NON_IDEMPOTENT (each call spawns a new actor); supports dry_run. Degrades to a plugin-disabled envelope if Water is off.
Spawn an AWaterBodyRiver following a world-space path (>=2 points). Rivers are the hardest water body to author by hand — this hides the spline wiring. NON_IDEMPOTENT; supports dry_run. SET-SUCCESS: surfaces spline_applied (whether the WaterSplineComponent point write actually ran — UNCERTAIN-API); per-point width/depth/velocity metadata is deferred with a warning. Degrades cleanly if Water is off.
THE honest gate for the water pack: probe whether the Water plugin is enabled (WaterBodyOcean/WaterZone classes present), whether its editor subsystem is ready, and report version/enable-list. Returns a STRUCTURED {enabled,...} result and NEVER throws — call this first so an agent gets an actionable enable hint instead of an AttributeError. Plugin version is UNCERTAIN-API (no python reflection) and stays null with a warning.
No parameters.
PLUMB-style quantified check of the water scene: bodies present but no WaterZone, bodies outside every zone (silent render drop), wave steepness out of [0..1], inverted wavelength range, multiple oceans. Returns green/red status + categorised findings with severity + a fix hint; ok:false only on errors. The closed-loop correctness engine for water (the worldbuilding moat). autofix not implemented this wave.
Read a body's wave setup: generator type, num_waves, wavelength range, steepness, seed, wind direction and attached WaterWavesAsset. The paired read for the most-tuned water parameter. Generator + property reflection is UNCERTAIN-API in 5.7 — probed with alternate names; anything unresolved is null with a warning, never guessed.
Configure a body's GerstnerWaterWaveGeneratorSimple (num_waves, wavelength range, steepness, wind direction, seed) — the primary knob for ocean look, with sane-range arg validation. SET-SUCCESS: the generator + every property setter is UNCERTAIN-API and returns void, so applied:true is reported ONLY when the generator resolved AND at least one setter ran without raising; otherwise ok:false + applied:false + a warning (never ok:true with an unapplied change). fields_applied lists exactly which knobs took. Idempotent set-to-value.
Spawn an AWaterZone (optionally sized + render-target resolution) to bound water bodies — bodies do NOT render without a covering zone (5.7 bounded zones). NON_IDEMPOTENT; supports dry_run. SET-SUCCESS: surfaces extent_applied/resolution_applied for the UNCERTAIN-API property writes. Degrades cleanly if Water is off.
Read a WaterZone: bounds, water-info render-target resolution, LOD far distance, which bodies it covers (AABB containment) and which bodies in the level are orphaned (covered by NO zone — the silent "body outside zone" rendering drop). Property reflection is UNCERTAIN-API; probed with alternate names.
World and scene 13
Deprecated for one release; use world_ingest. Import a heightmap (PNG or R16) through the shared staged workflow, preserving partition settings and legacy import-only behavior. Leaves changes unsaved. The heightmap is sampled 0..uint16-max to 0..maxHeightM (m). Spawns one Landscape covering worldSizeKm x worldSizeKm.
Deprecated for one release; use world_ingest. Import a heightmap (PNG or R16) through the shared staged workflow, preserving partition settings and legacy import-only behavior. Leaves changes unsaved. The heightmap is sampled 0..uint16-max to 0..maxHeightM (m). Spawns one Landscape covering worldSizeKm x worldSizeKm.
Export a 3D scene graph for LLM reasoning (flat / relational / hierarchical).
Report one actor's attachment parent, its attached children and its asset references. Answers 'what would move or break if I reparent or delete this' — it is not an inventory, use actor_list for that.
Detect floating / interpenetrating actors in the level.
Read-only structural evidence for currently loaded editor actors or a folder path and descendants aggregated across all loaded Outliner roots. Same-path folders in separate roots are combined. Counts loaded actors, classes, folder paths, and ISM/HISM instances; reports unknown unloaded World Partition/PCG coverage. Optional user targets compare counts for that stated aggregate only. This does not establish runtime memory, streaming, NPC, frame-time, or texel-density fitness.
Compare two caller-supplied loaded-editor world budget snapshots under one declared protocol, with optional paired completed PIE proxy captures. Matching complete scans yield structural deltas and caller-supplied cap headroom; incomplete scans retain observed counts but withhold deltas and verdicts. PIE proxy deltas require compatible captures and full requested samples for each metric. The caller protocol is not independently verified; no production performance or design score is inferred.
Build an environment from a natural-language biome description. Parses the prompt into layers (canopy/rock/undergrowth/groundcover), resolves one of the PROJECT'S OWN StaticMeshes per layer, plans a deterministic seeded scatter across an area actor, then PLUMB-VALIDATES and auto-corrects every instance IN MEMORY (grounded, non-interpenetrating) before spawning — "scatter and prove", not scatter-and-hope. Use dry_run to get the validated plan without spawning.
Inspect, plan, import, prepare, save, and verify world content with explicit capability and partial-failure results.
Inspect the open Unreal world and return normalized capability and readiness facts.
No parameters.
Find loaded Unreal source objects in one exact captured mesh tile by an authored tag, folder, actor class, or mesh asset. Optionally compare each match to one reference source ID or authored fact using a typed candidate relation from sampled point bounds. First use world_tile_capture, then pass its tile_id and capture_id as expected_capture_id here. Returns canonical actor/component/instance provenance, point evidence, and coverage gaps. A partial capture cannot prove absence; this does not infer visual labels, collision, visibility, gameplay quality, or a production budget verdict.
Inspect three separate loaded-world observations: mesh hierarchy and spatial clusters (source=mesh), CPU mesh point-cloud tiles linked to actor/component/instance sources, compact authored semantic groups, and spatial relations (source=mesh_tile), or first-visible editor-camera depth (source=view_depth). Use world_tile_capture to capture a tile on demand. For mesh_tile, pass its tile_id and the capture_id returned by start as expected_capture_id even on the first overview; reuse both for pages and relations. An uncaptured tile reports not_captured; an evicted pinned capture ID is refused so the agent can recapture. No visual-quality or production-performance verdict.
Start, poll, or cancel an asynchronous World tile capture. Start with either canonical tile_id (tile:LOD:X:Y:Z) or position_cm {x,y,z} plus lod (0–2); position coordinates are centimeters and resolve to the containing tile. Samples bounded CPU mesh geometry from loaded editor actors only; it does not load cells, render, or capture during PIE. Start returns tile_id and capture_id immediately. Poll by capture_id until captured or partial, then read source=mesh_tile with world_semantic_snapshot using tile_id and expected_capture_id from start, including on the first overview and all relation/detail pages.
No tools match that filter.