Skip to content
Guide

Build a scene with an assistant

The chain from the widget list to a rendered image: rules, document, dry run, draft, publish, and preview.

5 min readUpdated Oct 30, 2026As Markdown
For
Anyone who lets an assistant design scenes, and developers who want to understand what it does along the way
Prerequisite
a connected assistant with the area Scenes, see Connect an AI assistant
Where
a conversation with your assistant
On this page

By the end, your assistant has built a scene from widgets, checked it, saved it as a draft, and shown you a rendered image of it. The way from idea to image is a chain of six steps, and every tool description names the next one, so an assistant doesn't have to guess the order.

Steps

  1. View the widgets. list_widgets names the widgets a scene is made of: the core widgets text, image, video, shape, graphic, document, and zone, which are always there, and the widgets of the apps your organization has installed. Each entry shows the identifier, app, name, a sentence, the required fields, and whether the app is installed. A widget of an app that isn't installed can be written into a document but runs on no display.

  2. Get the rules. get_widget_schema returns the complete JSON Schema of a widget's configuration (Draft 2020-12): every field with title and description, the required fields under required, and under examples at least one complete example configuration. Taking an example and swapping the values is the shortest way.

    One value no schema lists: the graphicId of the core widget graphic. It is a fixed identifier from the graphics library. list_graphics lists it with category and keywords, searchable by intent with German words such as "pfeil" (arrow) or "kaffee" (coffee).

  3. Build the document. A scene document has three fields:

    JSON
    {  "canvas": { "width": 1920, "height": 1080, "backgroundColor": "#ffffff" },  "widgets": [    {      "id": "wgi_01K7Z9M4T0W14MCPTEXT000001",      "appId": "core",      "widgetType": "text",      "appVersionPin": "0.0.0",      "frame": { "x": 0, "y": 0, "w": 1920, "h": 1080 },      "zIndex": 0,      "config": { "content": "Welcome" }    }  ],  "transitions": {    "in": { "kind": "fade", "durationMs": 600 },    "out": { "kind": "fade", "durationMs": 600 }  }}

    A scene has no resolution. Every widget sits by its frame in units of the canvas, and the short edge of the canvas always measures 1080: 16:9 is 1920 × 1080, 9:16 is 1080 × 1920. Each display renders as sharply as its device and package allow. A zone is a widget with appId: "core" and widgetType: "zone". It splits the scene, and its config names name, primary, and content: a single item, an own sequence, or a playlist. At most one zone is primary, and that main zone sets how long the scene runs. Zones don't overlap, and a widget inside a zone sits there without a frame of its own. config comes from step 2.

  4. Run a dry run. validate_scene checks the document without saving anything: the structure, the rules of the zones, the referenced media, and every configuration against the schema of its widget. Each finding names the widget and the field:

    JSON
    {  "valid": false,  "findings": [    {      "severity": "BLOCKING",      "type": "ConfigSchemaIncompatible",      "message": "widget 'wgi_…' (text): config/content must NOT have fewer than 1 characters",      "widgetId": "wgi_…",      "field": "/content"    }  ]}

    BLOCKING prevents publishing later, WARNING doesn't. A widget that sticks out past the edge of the canvas is reported and stops nothing.

  5. Create or change the draft. create_scene creates a draft from the document, and update_scene replaces the document of an existing scene. Both run the dry run again and write nothing at all if a finding blocks. Both need confirm: true, and without it they only describe what they would do.

    To change an existing scene, start with get_scene_document. It returns the document of the draft and its version. Change that document, check it with validate_scene, and send it whole to update_scene with expectedVersion from the same answer, so that someone else's change in between isn't overwritten. There is no way to change a single widget, and an assistant that rebuilds the document from scratch loses every setting it didn't know about.

  6. View and refine. render_scene renders a published version and returns the image as a PNG in the answer. A pure draft has no version, so publish it first with publish_scene. That doesn't put it on a display as long as none has it assigned. The image answers what no schema can: whether the text stays in its box, whether something is covered, whether the colors work. If something is off, continue with update_scene and publish again.

Check the result

  • get_scene shows the scene with its widgets and no open issue.
  • The image from render_scene shows what you asked for.
  • What a display actually shows answers get_player_screenshot, with the most recent capture of the device. If there is none yet, send_player_command with command: "screenshot" requests one.

If something goes wrong

Symptom Meaning Solution
create_scene or update_scene returns findings and saves nothing A finding blocks. Fix the fields the findings name and run validate_scene again.
update_scene answers conflict Someone changed the scene in between. Read the document again with get_scene_document and apply the change to the new state.
render_scene says there is no version The scene is still a pure draft. Publish it with publish_scene, then render.
render_scene says no preview is available Your environment has no snapshot service set up. Check the result with get_player_screenshot on a display instead.
A widget appears in the document but not on the display Its app isn't installed in your organization. Install the app, or use a core widget instead.
5 min readUpdated Oct 30, 2026As Markdown

Was this helpful?