Skip to content

DES with AI

An AI assistant can do the whole study loop of a discrete event simulation for you. It builds or changes the model, sets up variants, runs repeated experiments in fast-forward and reads the results back with confidence intervals. It can then explain where the bottleneck is and which variant it would choose. You describe the question in plain words and watch the assistant work in the viewer. You can step in at any time.

The assistant does not get a special AI interface. It works through the same commands as the toolbar, the planning window and the experiment manager. Commands are checked by the same rules as in the UI, and a refused command answers with its reason. A DES study made by the AI is therefore a normal study that you can open, check and continue by hand.

The DES core is free in every edition. The experiment manager, which the AI needs for variants with repeated runs, is part of realvirtual Commercial for your own installation and fully usable in the public demo. See Licence.

DES with an AI assistant You ask the AI client in plain words. The AI client calls MCP tools on realvirtual CONNECT at localhost port 5100. CONNECT passes the calls to the viewer in your browser, which runs them as viewer commands on the DES model and the experiment manager. Statistics, KPIs and confidence intervals go back to the AI client as tool results. You question in plain words AI client Claude Code, Codex or the AI window CONNECT MCP endpoint :5100/mcp Viewer web_execute web_query DES model layout, runs Experiments variants, KPIs statistics, KPIs, mean ± 95 % CI
The assistant only sees what the tools return. CONNECT and the viewer run on your PC.
  • MCP (Model Context Protocol) is the standard through which AI assistants call tools. realvirtual CONNECT hosts the MCP endpoint http://localhost:5100/mcp on your PC.
  • The viewer owns the tools. When AI control is switched on, the browser tab offers its web_* tools to CONNECT. Every change to the model or the simulation is a viewer command. The assistant runs it with web_execute or web_batch. It reads with web_query. web_commands lists every command with its arguments.
  • Guides on demand. A good assistant reads the guide for its task before it starts: web_help("des") for runs and diagnosis, web_help("experiments") for the experiment manager, web_help("layout") for building lines and path networks, web_help("kinematize") for preparing raw CAD, web_help("scripting") for DES scripts and web_help("commands") for variants, planning parameters and macros.
  • realvirtual CONNECT running on your PC, registered once for free. The MCP endpoint and its write access are on by default.
  • An AI assistant with MCP. Use Claude Code, the Claude Code desktop app or Codex. You can also use the AI window inside the viewer, which starts Claude Code or Codex for you. Classic Claude Desktop also works, but needs the mcp-remote relay. Setup takes a few minutes and is described in Build a Twin with AI and AI Assistant (Bridge).
  • A viewer with the parts you want the AI to use. For experiments and model building, use the public demo with your local CONNECT, or your commercial deployment. The viewer that CONNECT serves on localhost:5100 runs twins but does not contain the editor, and the experiment manager is only included in the public demo and commercial deployments. See Using the hosted viewer with a local gateway.
  • AI control switched on in the viewer under Settings ▸ AI.

The assistant builds a DES model from the same blocks you would use by hand:

  • Raw CAD. In the Editor, editor.importCad imports a STEP or other CAD file. Following web_help("kinematize"), the assistant names the parts, removes helper geometry and creates axes with drives. Then it checks each axis by moving it. The Editor is part of realvirtual Commercial and usable in the public demo.
  • Conveyor lines from the library. In the Layout Planner, the assistant lists the placeable parts with library.catalogList and places the first one with layout.place. It chains the next ones along their free snap points with layout.snapList and layout.snapAttach, so they are connected and correctly oriented. component.setFields configures behaviour, for example the speed of a conveyor or how many parts a source spawns. layout.list reports positions and bounds for a final check.
  • Routes for vehicles. For AGVs and forklifts, the assistant builds the path network from blocks with layout.path.place and adds junctions with layout.path.junction. layout.path.validate checks for open ends, gaps, kinks and merges that are too short.
  • Run settings. In the DES workspace (workspace.setMode {mode:"des"}), des.setEnd sets the end time and the warm-up (statReset), both as DD:HH:MM:SS. They are stored on the scene and saved with the document.
  • Planning parameters. For models that declare them, such as PalletYard, planning.param.list, planning.param.set and planning.param.apply change parameters such as the fleet size, as in the planning window.

Layout and editor changes are ordinary undo steps. web_document_save saves the result. To keep the build reproducible, ask the assistant to record it as a macro, as described in Record the work as a macro.

The experiment.* commands drive the same matrix as the Experiments window. Writes go through web_execute, reads through web_query. All of them require the DES workspace.

CommandsWhat the assistant does with them
variant.list, variant.create {name}, variant.set {id, path, component, field, value}Lists the variants, creates a variant and changes one property in it. value is passed as text and converted to the field’s type. null removes an override
experiment.sync, experiment.listCreates the missing columns for new variants and reads columns, settings and archived seeds
experiment.column.set {column, enabled, replicationCount, crn}Selects columns and sets the repeated runs per column (1 to 999)
experiment.settings.set {endTime, statResetTime, crn}Sets the run length and warm-up shared by all columns
experiment.kpi.list, experiment.kpi.add, experiment.kpi.removeChooses KPI rows or defines its own KPI, for example a counter per hour or the mean utilization of all Stapler_*
experiment.run {scope}, experiment.run.status, experiment.run.cancelRuns all, selected or one column, follows the progress and cancels the batch
experiment.results {kpis, columns}Reads mean, 95 % confidence interval, number of runs and the difference to Base
experiment.series.list, experiment.series.getReads the recorded curves of one run, sampled to at most 5000 points
experiment.snapshot.list, .save, .load, .deleteLists, saves, resumes or deletes checkpoints
experiment.window {open}Opens or closes the matrix so you can watch

A batch can take a long time. Through MCP, experiment.run therefore returns a jobId straight away. The assistant follows it with web_macro_status and the replication progress with experiment.run.status. While a batch runs, other writes to the model are refused. Cancelling keeps the finished replications and restores the variant that was shown before.

Columns can be addressed by variant name, such as "4 AGVs", by variant id or as Base. The columns and KPIs are explained in Experiments and Runs.

The assistant analyses with the same numbers as the Statistics window and the experiment matrix:

  • Is the run healthy? diagnose gives a summary of run state, problems, faults and vehicle counts. des.status tells whether a run finished or stalled and why.
  • Where is the bottleneck? des.stats returns the state shares per component (working, blocked, empty, failure and more) and the output per hour. des.bottleneck names the limiting component and counts the components blocked upstream and starved downstream. des.components {busyOnly:true} shows the load and wiring of each component, which helps with deadlocks and full zones. des.events lists the next scheduled events.
  • Is a variant really better? experiment.results gives every KPI as mean ± 95 % confidence interval per column, together with the difference to Base and its own interval. With common random numbers (crn, on by default) the difference is computed from pairs of runs with the same seed. Otherwise it uses Welch’s test. A difference whose interval includes zero is not shown to be real. A column with fewer than two valid runs has no interval.
  • How did it behave over time? experiment.series.get returns the curves of a run, for example to check whether the warm-up was long enough.

Ask the assistant to state the confidence intervals with every recommendation. It can only draw conclusions from the runs that were made. If the intervals overlap, the right answer is more replications, not a winner.

The three dialogues below show the prompts, the commands the assistant calls and what comes back. The exact order of calls varies with the assistant, and your numbers depend on the model and the runs.

Switch to the planner and build a straight line of three 2 m roll conveyors with a carton source at the start. Then run it in DES for one hour and tell me the output per hour.

web_help("layout")
web_execute("workspace.setMode", {"mode":"planner"})
web_execute("library.attach", {"projectId":"prj_realvirtual_library"})
web_query("library.catalogList", {"query":"roll"}) → pallethandling-rollconveyor-2m, …
web_execute("layout.place", {"catalogId":"pallethandling-rollconveyor-2m", "x":0, "y":0, "z":0,
"libraryProjectId":"prj_realvirtual_library"}) → id A
web_query("layout.snapList", {"id":"A"}) → free output snap
web_execute("layout.snapAttach", {"targetId":"A", "catalogId":"pallethandling-rollconveyor-2m",
"libraryProjectId":"prj_realvirtual_library"}) → id B
web_execute("layout.snapAttach", {"targetId":"B", "catalogId":"pallethandling-rollconveyor-2m",
"libraryProjectId":"prj_realvirtual_library"})
web_execute("layout.place", {"catalogId":"pallethandling-cartonbox", "onto":"A", "libraryProjectId":"prj_realvirtual_library"})
web_query("layout.list", {}) → three connected conveyors, one source
web_execute("workspace.setMode", {"mode":"des"})
web_execute("des.fastForward", {"untilSimTime":"00:01:00:00"})
web_query("des.status", {}) · web_query("des.stats", {})
web_document_save

The assistant answers with the run state and the output per hour of the line. If the line stalls, it reads des.components to find the component that holds the parts. A real line also needs a sink at the end. The assistant looks for a suitable part in library.catalogList instead of guessing ids.

2. Compare 3, 4 and 5 forklifts on PalletYard

Section titled “2. Compare 3, 4 and 5 forklifts on PalletYard”

Open the PalletYard example in the public demo. It already contains the variants 2 AGVs, 4 AGVs and No downtime. The fleet size is the property VehicleCount of the PalletYard component on PalletYardRoot. In the default yard size, up to 8 forklifts fit.

Compare 3, 4 and 5 forklifts in PalletYard. Use 5 runs of 8 hours per variant and report throughput and forklift utilization.

web_help("experiments")
web_query("variant.list", {}) → Base (3), "2 AGVs", "4 AGVs", "No downtime"
web_execute("variant.create", {"name":"5 AGVs"}) → id
web_execute("variant.set", {"id":"<id>", "path":"PalletYardRoot", "component":"PalletYard", "field":"VehicleCount", "value":"5"})
web_execute("experiment.sync", {})
web_execute("experiment.settings.set", {"endTime":"00:08:00:00"})
web_execute("experiment.column.set", {"column":"2 AGVs", "enabled":false})
web_execute("experiment.column.set", {"column":"No downtime", "enabled":false})
web_execute("experiment.column.set", {"column":"Base", "enabled":true, "replicationCount":5})
web_execute("experiment.column.set", {"column":"4 AGVs", "enabled":true, "replicationCount":5})
web_execute("experiment.column.set", {"column":"5 AGVs", "enabled":true, "replicationCount":5})
web_execute("experiment.kpi.add", {"label":"Forklift utilization", "match":"Stapler_*", "metric":"utilization"})
web_execute("experiment.run", {"scope":"selected"}) → jobId
web_macro_status(jobId) · web_query("experiment.run.status", {})
web_query("experiment.results", {})

experiment.results returns one entry per column and KPI, in this form:

{ "column": "v:…", "kpis": [
{ "id": "throughput", "mean": …, "ci": …, "n": 5,
"delta": { "delta": …, "ci": …, "n": 5, "paired": true } } ] }

Which fleet size would you choose, and why? Check whether the difference is significant and where the forklifts lose their time.

The assistant compares the deltas to Base and their intervals. Then it looks at the state shares of the vehicles with des.stats, or at the time curves with experiment.series.get. In the PalletYard example, the forklift demo shows that a fourth forklift does not raise the throughput, because the vehicles block each other on the one-way loop. A good recommendation states this with the intervals and names the next experiment worth running, for example No downtime against Base or a different path layout. Ask for its reasoning before it changes the model.

In the public demo and in commercial deployments, AI control opens an AI window inside the viewer. CONNECT starts Claude Code or Codex on your PC and connects it to the scene, so no MCP setup is needed. The window passes your current selection along with the prompt, shows tool results and screenshots, and lists recent sessions. The global search offers Ask AI agent for a query.

  • The assistant in the window sees only the realvirtual tools. MCP servers from your own Claude Code or Codex configuration are not available there.
  • It needs Scene access on. Without scene access, it cannot read or change the scene.
  • AI may control SolidCraft under Settings ▸ AI additionally gives it the SolidCraft Live Link. This switch is off by default.
  • The window must be allowed once in the CONNECT tray under Details ▸ MCP server ▸ Allow prompt window. The open-source build does not include it.

Everything on this page also works from the window, for example “Run the prepared experiment and explain the result”. Setup and details are in The built-in AI window. The beta Agent chat runs your own Claude Code session with permission prompts instead.

  • AI control is a switch in the tab. With AI control off under Settings ▸ AI, the viewer offers no tools, and every call answers AI_DISABLED:. This applies to local assistants too. Pause stops new connections without closing anything.
  • Write access is a switch in CONNECT. With MCP server ▸ Allow write access off in the tray, the assistant can still read, but it cannot change the model or start runs. CONNECT sorts every command into a class (read, edit, sim, signal, save, destructive, file), which a chat session can use to ask before risky calls. For example, experiment.run counts as sim and experiment.snapshot.delete as destructive.
  • Local by default. CONNECT and the viewer run on your PC, and MCP clients from other machines are refused unless you configure a key. The model file is not uploaded.
  • The assistant sees what the tools return. Names, values, statistics, results and screenshots go to the AI service of your assistant, like any other request you give it. Keep this in mind for confidential layouts.
  • Undo and review. Layout and editor changes are undo steps. Planning parameters have no undo step, and neither planning nor variant changes are recorded in macros. Remove a variant with variant.delete, or reset its field with variant.set and value: null.
  • No experiment manager in the open-source build. There, experiment.* answers with the error kind commercial-feature. Single runs, statistics, des.* queries and KPI recording still work.
  • Batch runs refuse scene logic they cannot run unattended, such as IK paths, logic that cannot run on events or ST programs that are not DES-ready. The refusal states the reason. See Models with logic steps, PLC programs or IK paths.
  • Seeds are recorded, not chosen. The assistant can read the seed of each run, but it cannot set it. For repeatable comparisons it uses common random numbers (crn).
  • No script editing through commands. The assistant can read what DES scripts publish, but it cannot write script code through MCP. Scripts are edited in the script editor.
  • A long call is still running, not failed. When a call exceeds its time limit, CONNECT answers running: true with a callId. The assistant checks it with web_call_pending and must not send the call again.
  • The AI’s judgement is not a proof. It can only draw conclusions from the runs it made and the numbers it read. Check its recommendation against the experiment matrix before you act on it.