xCloudxCloudDownload
Agents

Agent UI

Build a visual interface for each agent, connect it to live agent state, and preview it inside xCloud.

Agent UI is the visual layer for an agent. Instead of every agent being only a chat thread, an agent can own a small web app that shows its state, tools, workflow, and domain-specific controls.

This is one of the main differences between xCloud and a normal web chat: the agent still runs on OpenClaw, but xCloud gives it a product-like interface.

How It Works

Each agent can have its own UI project.

~/.openclaw/workspace/<agent-id>/
  IDENTITY.md
  SOUL.md
  AGENTS.md
  ui-config.json
  ui/
    package.json
    src/

The ui-config.json file tells xCloud where the UI project lives and which port to use for preview.

For local engines, the UI normally lives on your computer. For remote engines, the UI can be stored on the remote engine and optionally synced from a local source folder.

Create An Agent UI

  1. Open an agent.
  2. Open the right preview panel.
  3. Choose Create UI or connect an existing UI folder.
  4. xCloud creates context files for the UI project.
  5. Build the UI with your preferred editor or coding agent.

xCloud writes helper files such as:

FilePurpose
AGENT-CONTEXT.mdExplains the agent identity, personality, tools, and UI goal
CLAUDE.mdInstructions for Claude Code
.cursorrulesInstructions for Cursor
XCLOUD-UI.mdGuide for the xCloud runtime bridge
xcloud-runtime.jsRuntime injected into the preview
xcloud-ag-ui.jsHelper for AG-UI events

Supported Editors

xCloud can open the UI folder in common local tools:

  • Cursor
  • VS Code
  • Windsurf
  • Claude Code
  • Codex
  • OpenCode
  • Zed
  • Terminal
  • iTerm

The editor is only for building the UI. The actual agent still runs in the active OpenClaw engine.

Preview Rules

The preview expects a normal web project.

For React/Vite/Next projects:

  • Include a package.json.
  • Include a dev or start script.
  • Respect the PORT environment variable.
  • Bind to 127.0.0.1 locally or 0.0.0.0 on remote engines.

For simple HTML projects:

  • Include an index.html.
  • xCloud can serve it with a static HTTP server.

If the project has a dev server, xCloud starts it and embeds the URL in the preview.

Live Agent Bridge

xCloud injects a runtime into the UI. The UI can read live agent state from:

const state = window.xcloud.agent.getState();

Useful state fields:

FieldMeaning
statusidle, running, responding, tool, or error
messagesRecent user and assistant messages
activeToolsTools currently being called
lastEventLast raw AG-UI event
lastToolResultLast finished tool result

Subscribe to changes:

window.xcloud.agent.onStateChange((state) => {
  console.log(state.status, state.messages);
});

UI Tools

The UI can register tools that the agent can call.

window.xcloud.agent.registerTool({
  name: "selectWorkout",
  description: "Select a workout in the UI.",
  parameters: {
    type: "object",
    properties: {
      workoutId: { type: "string" }
    },
    required: ["workoutId"]
  },
  async execute(args) {
    return { selected: args.workoutId };
  }
});

When the agent calls that tool, xCloud forwards the request into the iframe and returns the UI result to OpenClaw.

Remote Engine Notes

When the active engine is a VPS or another PC:

  • The UI project can be copied to the remote engine.
  • xCloud starts the dev server on the remote host.
  • The preview loads from that host and port.
  • If a local source path is configured, xCloud can sync between local files and the remote UI folder.

Remote previews are more sensitive to firewall, host binding, npm install time, and port conflicts.

Common Problems

ProblemFix
Preview stays loadingConfirm the project has package.json with dev or start, or an index.html
Port opens but page is blankCheck the dev server logs and browser console
UI works locally but not on VPSMake sure the remote dev server binds to 0.0.0.0
Runtime state is missingConfirm xcloud-runtime.js was injected or imported
Agent cannot call UI toolKeep the preview open and make sure the tool is registered after load
Imported UI does not appearCheck that the package included a ui/ folder and ui-config.json points to it