Install
$ agentstack add skill-wolframresearch-system-modeler-ai-toolkit-wolfram-language-modelica ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
System Modeling with Wolfram Language
This skill covers how to drive Modelica simulation from Wolfram Language using the built-in SystemModel* family. Use this when the downstream work lives in WL, for example, analysis of simulated data, calibration, optimization, surrogates, custom plots.
For pure command-line simulation / validation with no WL work afterward, prefer the simulate-modelica or validate-modelica skills — they are faster because they avoid kernel startup and WL context.
When to use which
| Goal | Use | |------|-----| | Does this .mo compile? | validate-modelica | | Run a sim, get pass/fail + log | simulate-modelica | | Debug torn systems, stiff init, blocks | diagnose-modelica | | Pull time series into WL for Predict / AnomalyDetection / Fit | this skill | | SystemModelCalibrate, SystemModelParametricSimulate | this skill | | Requirement validation, uncertainty bands, surrogates | this skill | | Live simulation you can pause / poke inputs & parameters mid-run | this skill (WSMRealTimeSimulate) |
Official reference docs (LLM-friendly variant)
Every page of the official Wolfram documentation has an LLM-friendly Markdown variant — append .en.md to the page URL. Fetch these on demand when you need the full signature, all options, or more examples than this skill carries:
- Hub:
https://reference.wolfram.com/language/guide/SystemModelingOverview.en.md - Any
SystemModel*function:https://reference.wolfram.com/language/ref/.en.md
(e.g. SystemModelSimulate.en.md, SystemModelCalibrate.en.md, SystemModelValidate.en.md)
- `
WSMLink`(real-time) functions:https://reference.wolfram.com/system-modeler/WSMLink/ref/.en.md`
The reference pages carry signatures and options but not the operational gotchas in this skill — those are verified against live kernels, and several (silent failures, headless-vs-notebook differences) are documented nowhere else. Where this skill and a doc example conflict in a headless/agent context, trust this skill.
Prerequisites — Wolfram Language + the Wolfram MCP server
Everything in this skill is Wolfram Language code (SystemModelSimulate, SystemModelPlot, SystemModelCalibrate, the requirement language, …). To run it the assistant needs a way to evaluate WL, which means two things:
- Wolfram Language 14.3 or later — Mathematica or Wolfram|One (the
SystemModel* simulation functions are not included in the free Wolfram Engine).
- A C++ compiler.
SystemModelSimulatecompiles each model to a native
executable before running it, so a working compiler toolchain must be available. Check (and fix) from within WL: ``wolfram SystemModel; (* Trigger loading of the system modeling functionality *) SystemModelConfigurationVerifyCompiler[] ( -> True|> when a working compiler is found ) SystemModelConfigurationInstallCompiler[] (* installs / configures a compiler if the check fails *) ``
- The Wolfram MCP server connected to your agent, so the assistant can
evaluate that WL on your machine.
Check before installing. First see whether Wolfram MCP tools (e.g. a WolframLanguageEvaluator) are already available in this session. If they are, skip setup and go straight to the workflow below.
Install — same on Windows, macOS, and Linux. In any Wolfram front end (a Mathematica notebook or wolframscript), evaluate:
PacletInstall["Wolfram/AgentTools"];
Needs["Wolfram`AgentTools`"];
InstallMCPServer["ClaudeCode"] (* or "ClaudeDesktop", "Cursor", … for other clients *)
This writes the server entry into the MCP client's config and runs the kernel locally — no API key, nothing leaves the machine. Then fully restart the client (quit completely; closing the window often just minimizes it to the tray/menu bar).
If anything goes wrong — the paclet won't install, the server doesn't show up in the client after restart, or evaluations fail — point the user to the official setup and troubleshooting page: https://www.wolfram.com/artificial-intelligence/mcp/local/
If the user doesn't have Wolfram Language 14.3 or later (Mathematica or Wolfram|One), this skill can't run — point them to the page above and ask whether they want to install it. Meanwhile, the command-line skills (simulate-modelica, validate-modelica, diagnose-modelica) need only System Modeler, not WL, and can cover compile / run / debug in the interim.
Core workflow
1. Load the package
From a file / package directory:
sm = Import["/abs/path/to/package.mo", "MO"] (* or "C:/..." on Windows *)
(* Returns SystemModel["PackageName", True] *)
From a Modelica source string (useful for inline models, templates, or LLM-generated models):
sm = ImportString[
"model Tiny
Real x(start=0);
equation
der(x) = 1 - x;
end Tiny;",
"MO"
]
(* Returns SystemModel["Tiny", True] *)
Notes:
- For multi-file packages, pass the top-level
package.mo. - The return value is a
SystemModel[...]you can pass directly toSystemModelSimulate,SystemModelPlot, etc. - You can also reference any loaded model by its full Modelica path as a string:
"MyPackage.SubPackage.MyModel". - Modelica source always goes through
Import/ImportString—CreateSystemModelis for building models from WL equations and does not accept raw Modelica source (fails withSystemModel::nvr).
2. Simulate
sim = SystemModelSimulate["MyPackage.MyModel", {tmin, tmax}] (* simulates over the simulation interval {tmin, tmax} *)
sim = SystemModelSimulate["MyPackage.MyModel", {"var1", "var2", "var3"}, {tmin, tmax}] (* store results for specific variables, more efficient when only some results are of interest *)
Note: the list controls exactly what is stored — parameters you don't name in it are dropped too, so sim["ParameterNames"] returns {} unless the list includes them (e.g. {"var1", "k"}). Simulate without a variable list to keep everything.
sim = SystemModelSimulate["MyPackage.MyModel", {"var1", "var2", "var3"}, {tmin, tmax}, spec] (* uses Association spec for initial values, parameters and inputs *)
Allowed spec keys:
| Key | Purpose | Example | |-----|---------|---------| | "ParameterValues" | Override tunable parameters | "ParameterValues" -> {"k" -> 2.5, "m" -> 10} | | "InitialValues" | Override start values | "InitialValues" -> {"x" -> 0.1} | | "Inputs" | Drive top-level inputs | "Inputs" -> {"u" -> (Sin[2 * #] &)} |
sim = SystemModelSimulate["MyPackage.MyModel", {"var1", "var2", "var3"}, {tmin, tmax}, {"k" -> 2.5, "m" -> 10}|>] (* uses the indicated parameter values *)
Pass ProgressReporting -> False — it drops the progress UI, which makes calls faster and keeps output clean. (Other options like Method for solver choice are rarely needed; see the SystemModelSimulate reference page if a model demands a specific solver.)
Parameter sweeps — pass a list for any parameter:
sweep = SystemModelSimulate["MyModel", {0, 10}, {"k" -> {1.0, 2.0, 5.0}}|>]
(* sweep is a list of SystemModelSimulationData objects *)
3. Extract numerical data
SystemModelSimulate returns a SystemModelSimulationData object. Several access patterns:
sim["Properties"] (* list of properties this object supports *)
sim["VariableNames"] (* list all time-dependent variables *)
sim["ParameterNames"] (* list all parameters *)
(* An InterpolatingFunction or a Function over the simulation interval: *)
f = sim["var1"];
f[500.0] (* value of variable at t = 500.0 *)
(* Values at a single time: *)
sim[{"var1", "var2", "var3"}, t] (* list of variable values at t *)
sim[{"var1", "var2", "var3"}, 500.0] (* list of variable values at 500.0 *)
(* Values at a list of times: *)
sim[{"var1", "var2", "var3"}, {500.0, 700.0}] (* list of lists: values at 500.0 and 700.0 for each variable *)
(* Raw time/value pairs (faster than interpolation). Repeated times indicate events: *)
sim["RawData", {"var1", "var2"}]
(* All variables as a rules list, this is time consuming for large number of stored variables *)
sim["VariableValues"]
(* Association of parameter values, initial values and inputs used in the simulation call*)
sim["Configuration"]
4. Plot
SystemModelPlot[sim] (* default plots stored in the model — errors with SystemModelPlot::nov if the model has no stored plots; pass a variable list in that case *)
SystemModelPlot[sim, {"x", "y"}] (* plot specific variables *)
SystemModelPlot[{simA, simB, simC}, {"x"}] (* compare results for several simulations — auto legend *)
SystemModelPlot[model, ...] (* simulate + plot in one shot *)
Useful options: PlotLegends, PlotStyle, Filling, TargetUnits, ScalingFunctions.
For a custom plot with Plot or ParametricPlot:
(* with Plot *)
Plot[Evaluate[sim[{"x", "y"}, t]], {t, tmin, tmax}, PlotLegends -> {"x", "y"}]
(* with ParametricPlot *)
ParametricPlot[Evaluate[sim[{"x", "y"}, t]], {t, tmin, tmax}]
(Note: using Evaluate is important so sim[...] is resolved once, not at every plot point.)
5. Resample onto a uniform grid (common for ML)
vars = {"var1", "var2", "var3"};
ts = Range[tmin, tmax, dt];
mat = Transpose[sim[vars, ts]];
(* mat has Dimensions {Length[ts], Length[vars]} — ready for AnomalyDetection etc. *)
Canonical end-to-end example
(* 1. Load *)
Import["/path/to/pkg/package.mo", "MO"]; (* use the OS-appropriate absolute path *)
(* 2. Simulate three scenarios *)
scenarios = {"pkg.Baseline", "pkg.Scenario1", "pkg.Scenario2"};
sims = SystemModelSimulate[#, {0, 1000}, ProgressReporting -> False] & /@ scenarios;
(* 3. Inspect what's in there *)
Take[First[sims]["VariableNames"], UpTo[10]]
(* 4. Extract a 3-variable time series from each scenario *)
variables = {"mIn.m_flow", "pTee.p", "mA.m_flow"};
ts = Range[0, 1000, 2.];
series = Through[sims[variables, ts]];
(* series is an array, has Dimensions {Length[scenarios], Length[variables], Length[ts]}, can be indexed with Part *)
(* 5. Compare with SystemModelPlot *)
SystemModelPlot[sims, variables]
(* 6. Downstream: anomaly detection trained on baseline *)
detector = AnomalyDetection[Transpose[series[[1]]]];
anomalyScores = detector[Transpose[series[[2]]], "RarerProbability"];
Gotchas
- Printing
SystemModelSimulationDatainside a List dumps every variable name.
A raw sim object displays compactly, but wrapping it in a List (e.g. evaluating {sim1, sim2} as the output of a cell) strips the compact box form and you get the entire variable-name list printed inline — hundreds of kilobytes of output per simulation. Fix: end the assignment cell with ;, then either pass the list directly into consumers (SystemModelPlot[sims, ...], extractions) without displaying it, or produce a compact summary: ```wolfram KeyTake[sim1["Summary"], {"ModelName", "SimulationInterval", "VariableValues"}] ( single simulation sim1 )
"NumberOfSimulations" -> Length[sims] ( list of simulations sims ) ```
AnomalyDetection[...]has no"AnomalyProbability"property. The continuous
score is called "RarerProbability", and its polarity is the opposite of what the name "anomaly probability" suggests: it is high (→ 1) for typical samples and low (→ 0) for anomalies. For an intuitive "higher = more anomalous" score, compute 1 - detector[x, "RarerProbability"]. For a hard yes/no, detector[x] (or "Decision") is already polarity-correct.
SystemModelValidationData[...]["FirstFailureTime"]and other properties return a Dataset, not a number.
On passing scenarios it is an empty Dataset; on failing scenarios it wraps the scalar in a row that also includes an empty Configuration column. Extract cleanly before displaying: ``wolfram prop = "FirstFailureTime"; d = SystemModelValidationData[...][prop]; With[{n = Normal[d, Dataset]}, If[n === {}, "\[LongDash]", First[n][prop]] (* "FirstFailureTime" for the first failure configuration, if there is one *) ]; ``
- Variable name mismatches. Modelica uses dots:
pipe1.port_a.p. Protected / mangled names can appear. Always runsim["VariableNames"]when in doubt instead of guessing. .matfiles from a kernel simulation aren't readable viasim[...]directly. Those come from the WSM kernel simulation. To read them in WL, load viaSystemModelSimulationData[path]— and even then, the file path must still exist. Prefer going throughSystemModelSimulateend-to-end when you need data in WL.- Load `
WSMLink`` in its own evaluation, before any code that uses it.
WL binds symbols at parse time, so a single evaluation containing both `Needs["WSMLink"]` and WSMRealTimeSimulate[...] creates GlobalWSMRealTimeSimulate` *before* the package loads, and the call returns unevaluated (Symbol::undefined). Evaluate the Needs on its own first, then the code. If loading itself emits messages (e.g. Set::write: Tag ... is Protected`), the load went wrong — don't dismiss it; restart the kernel and load cleanly, and report it if it persists.
- Unit annotations.
SystemModelPlotrespects Modelicaunitannotations; variables without units show raw numbers.
Requirements and validation
For anomaly detection, fault diagnosis, or safety-case work, Wolfram ships a requirement language plus SystemModelValidate that expresses assertions directly over the simulated trajectory — no scaffolding needed.
The requirement language
Temporal operators that wrap a predicate over a free time variable t:
| Operator | Meaning | |----------|---------| | SystemModelAlways[t, texpr] | texpr holds for every t in the validation interval | | SystemModelAlways[t, cond, texpr] | texpr holds whenever cond[t] is true (scoped "always") | | SystemModelEventually[t, texpr] | texpr holds at some t | | SystemModelUntil[...] | Hold until another condition fires | | SystemModelSustain[...] | Hold continuously for at least a given duration | | SystemModelDelay[...] | Shift a condition in time |
Predicates compose with `, >=, ==, &&, ||, !, etc., and reference any variable from the model by bracket syntax var[t], or parameter as par`.
Calling SystemModelValidate
(* Against a live model *)
val = SystemModelValidate[model, req]
val = SystemModelValidate[model, req, spec]
(* Against an already-computed SystemModelSimulationData *)
val = SystemModelValidate[sim, req]
(* Direct property extraction *)
SystemModelValidate[sys, req, "FailureIntervals"]
Unlike SystemModelSimulate, SystemModelValidate does not accept a bare {tmin, tmax} as a positional argument — a simulation interval must be passed inside spec as "SimulationInterval" -> {tmin, tmax}. Passing {tmin, tmax} positionally leaves the call unevaluated.
Names in "ParameterValues" must match the model's parameters exactly, or the call fails with SystemModelValidate::pvf ("not among the expected ones"). When unsure, list them first with model["ParameterNames"].
Method -> {"InterpolationPoints" -> n} evaluates the requirement on an n-point time grid — reported failure times snap to grid points, and fewer points mean less post-processing on large sweeps.
spec is an Association with any of:
{v1 -> val1, ...},
"ParameterValues" -> {p1 -> val1, ...}, (* accepts lists / intervals / distributions *)
"Inputs" -> {in1 -> fun1, ...},
"SimulationInterval" -> {tmin, tmax
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [WolframResearch](https://github.com/WolframResearch)
- **Source:** [WolframResearch/system-modeler-ai-toolkit](https://github.com/WolframResearch/system-modeler-ai-toolkit)
- **License:** MIT
- **Homepage:** https://www.wolfram.com/system-modeler/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.