# Build a scene with an assistant

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.

> **Type:** guide
> **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](/mcp/connect-assistant)
> **Where:** a conversation with your assistant

## 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. |

## Related

- [All tools](/mcp/tools)
- [What can an AI assistant do with Szenera?](/mcp/about-mcp)
- [When the assistant can't connect or a tool fails](/mcp/troubleshooting)
