Skip to content

Scripting

The plugin exposes a small scripting API on its editor subsystem, PhEditorSubsystem. Use it from editor Python, Editor Utility Blueprints (category Prophouse | Agent), or from any tool that already drives the editor, such as an editor MCP server running Python for an AI agent. The console commands Ph.Import and Ph.AgentStatus wrap the same calls.

Script imports do not need Accept agent imports. That setting only gates imports queued through the Prophouse MCP. Scripts do need the editor to be signed in and, unless legacy direct transfers are on, the desktop app to be installed.

import unreal
ph = unreal.get_editor_subsystem(unreal.PhEditorSubsystem)
Python Blueprint Returns Description
get_agent_bridge_status() Get Agent Bridge Status PhAgentBridgeStatus Whether this editor is ready to import and, if not, what to fix.
import_entries(entry_ids, target_root) Import Entries PhAgentImportResult Imports the given catalog entry ids, with their dependency closure, into this project. Returns immediately.
get_last_agent_import() Get Last Agent Import PhAgentImportResult The latest script or agent import in this editor session. Poll it for progress and results.

import_entries takes a list of entry ids (integers) and a destination root such as "/Game/Kit". Pass an empty string to use the Default Destination Root setting. Duplicate and non-positive ids are ignored.

The import runs through the normal pipeline, one at a time, and every conflict keeps the local file without a dialog. The call returns with state set to creating, or to rejected with a reason if the import cannot start:

error_code Cause
NOT_SIGNED_IN The editor is not signed in to Prophouse.
VALIDATION No positive entry ids were passed.
BUSY Another Prophouse import is running in this editor. Wait for it and try again.
DESKTOP_AGENT_UNAVAILABLE The desktop app is not installed or could not be started.
Field (Python) Type Meaning
job_id int The import job’s id (0 before it is created).
state str none, rejected, creating, waiting, importing, done, failed or cancelled. waiting means the job is queued but held back (for example while the desktop app starts); the editor retries it on its own.
source str script for import_entries, mcp for imports queued by an agent through the MCP.
message str A human-readable status line.
error_code str Error code when state is rejected or failed.
object_paths list of str Object paths now in the project (placed, or already present and identical), such as /Game/Prophouse/Meshes/SM_Crate.SM_Crate. Includes dependencies such as materials and textures.
kept_local list of str Object paths where your local edit was kept and the incoming version was not placed.
failed_items list of str <package>: <error> for each asset that failed to place.
Field (Python) Type Meaning
signed_in bool A server URL and token are configured.
server_url str The Server URL setting.
project_key str The key imports must target to land in this editor.
default_root str The Default Destination Root setting.
accept_agent_imports bool The Accept agent imports setting.
desktop_agent str live, launchable, unavailable, not_required (legacy direct transfers are on) or unknown.
connection str unknown, connected, auth_failed or unreachable.
presence_healthy bool The editor’s last check-in reached the server and was accepted.
last_heartbeat_error str Why the last check-in failed, if it did.
seconds_since_heartbeat int Seconds since the last accepted check-in, or -1 if there has been none.
busy_job_id int The agent or script import running now, or 0.
pending_agent_jobs int Agent imports the server has queued for this editor that have not started.
problems list of str Blocking problem codes, empty when ready: NOT_SIGNED_IN, AUTH_FAILED, SERVER_UNREACHABLE, SERVER_TOO_OLD, AGENT_IMPORTS_DISABLED, DESKTOP_AGENT_UNAVAILABLE.
summary str Ready, or Not ready: followed by what to fix.

AGENT_IMPORTS_DISABLED only blocks imports queued through the MCP. import_entries works without it.

status = ph.get_agent_bridge_status()
print(status.summary)
for code in status.problems:
print("problem:", code)

Imports run asynchronously on the editor’s main thread, so do not wait for them in a loop with time.sleep(): that blocks the editor and the import never advances. Poll from a tick callback instead. This example imports two entries and, once the import is done, spawns every mesh and Blueprint it placed into the current level:

import unreal
ENTRY_IDS = [1234, 5678] # catalog entry ids
TARGET_ROOT = "" # "" = the Default Destination Root setting
ph = unreal.get_editor_subsystem(unreal.PhEditorSubsystem)
actors = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
result = ph.import_entries(ENTRY_IDS, TARGET_ROOT)
if result.state == "rejected":
raise RuntimeError(f"{result.error_code}: {result.message}")
SPAWNABLE = (unreal.StaticMesh, unreal.SkeletalMesh, unreal.Blueprint)
def spawn(paths):
x = 0.0
for path in paths:
asset = unreal.load_asset(path)
if not isinstance(asset, SPAWNABLE):
continue # skip materials, textures and other dependencies
actors.spawn_actor_from_object(asset, unreal.Vector(x, 0.0, 0.0))
x += 300.0
def on_tick(delta_seconds):
last = ph.get_last_agent_import()
if last.state not in ("done", "failed", "cancelled"):
return # creating, waiting or importing
unreal.unregister_slate_post_tick_callback(handle)
if last.state == "done":
spawn(last.object_paths)
unreal.log(last.message)
else:
unreal.log_warning(f"{last.state}: {last.error_code} {last.message}")
handle = unreal.register_slate_post_tick_callback(on_tick)

object_paths contains the whole closure, which is why the example filters by class before spawning.

Type these into the editor’s console. Output goes to the Output Log under LogProphouse.

Command What it does
Ph.Import <entryId> [<entryId>...] [Root=/Game/Path] Calls import_entries with the given ids and optional destination root, then prints the initial state.
Ph.AgentStatus Prints the readiness summary and status fields, then the last import’s job id, source, state, message and object paths.
Ph.Import 1234 5678 Root=/Game/Kit
Ph.AgentStatus