omagent
LLM-assisted modeling for OpenModelica — an open-source, headless Python agent that turns a natural-language task into a verified Modelica model:
natural language ──> generate ──> compile (omc) ──> simulate ──> verify physics
▲ │
└──── structured error / verifier feedback ──┘
Unlike a plain code assistant, omagent closes the loop on physics, not just compilation: quantitative verifiers check trajectories against expected behavior (final values, settling windows, bounds, overshoot), and every failure — compiler diagnostics or physics complaints — is parsed into structured feedback for the next fix attempt.
Key capabilities:
- Structured omc diagnostics — parses
getErrorString(), simulation logs, and OMPython's exception format into records with severity, source location, and failure kind (syntax / lookup / type / balance / connect / initialization / runtime) - Environment-grounded fix hints — on
Class X not found, omagent asks omc what the parent package actually contains (getClassNames) and puts near-miss suggestions into the fix prompt. This resolves the dominant observed failure mode: stale library knowledge (e.g. MSL 3.2 names such asBasic.EMFvs. MSL 4.xBasic.RotationalEMF) - Quantitative verification — reads CSV or Dymola-format
.matresults; verifier complaints ("final value of x is 1.93, expected 2.0") drive tuning - Benchmark task ladder — 5 escalating, auto-gradable tasks with full transcript capture, in the format the OpenModelica benchmark discussion (OpenModelica#15385) calls for
- LLM-backend-agnostic — the loop depends on a one-method protocol; adapters ship for Anthropic and for any OpenAI-compatible endpoint (Ollama, LM Studio, llama.cpp, vLLM — local open-weight models included)
- Tested — 83 unit tests run without OpenModelica installed; 4 integration tests validate against a live omc
Installation
Requires Python >= 3.10. The core package has zero hard dependencies; features are opt-in extras:
pip install -e . # parsers + loop only (no omc needed)
pip install -e ".[omc]" # + OMPython (talk to a real omc)
pip install -e ".[results]" # + scipy (.mat result files; CSV needs nothing)
pip install -e ".[llm]" # + anthropic adapter
pip install -e ".[all]" # everything, including pytest
To use it against a real compiler you need
OpenModelica (tested with 1.26–1.27) with the
Modelica Standard Library installed for omc:
echo 'installPackage(Modelica); getErrorString();' > /tmp/i.mos && omc /tmp/i.mos
Note: OMEdit installs the MSL for itself automatically; headless
omcsessions do not. If models usingModelica.*fail with "Class ... not found", this is why.
Verify your setup:
pytest -m "not integration" # unit tests, no omc required
pytest -m integration # against your live omc (+MSL, scipy for .mat)
Quick start
from omagent import AgentLoop, OMSession, all_of, expect_bounds, expect_final
from omagent.llm import ClaudeLLM # or any object with .propose(...)
# physics acceptance criteria — complaints feed back into the fix loop
verifier = all_of(
expect_bounds("x", lo=-0.105, hi=0.105),
expect_final("x", 0.0, atol=0.06, rtol=0.0),
)
loop = AgentLoop(
OMSession(), # real omc via OMPython
ClaudeLLM(), # needs ANTHROPIC_API_KEY
max_attempts=4,
simulate_options={"stopTime": 10.0, "outputFormat": "csv"},
verifier=verifier,
)
result = loop.run(
"A mass-spring-damper: m = 1 kg, c = 100 N/m, d = 1 N.s/m, released "
"from x = 0.1 m at rest. Name position x and velocity v.")
print(result.success, result.model_name)
print(result.final_code)
for a in result.attempts:
print(a.n, a.stage, a.complaint)
Local / open-weight models work through any OpenAI-compatible server (Ollama, LM Studio, llama.cpp server, vLLM) with no extra dependencies:
from omagent.llm import OpenAICompatLLM
llm = OpenAICompatLLM(model="qwen2.5-coder:14b") # Ollama default URL
# llm = OpenAICompatLLM(model="...", base_url="http://localhost:1234/v1") # LM Studio
Or bring your own LLM by implementing one method:
class MyLLM:
def propose(self, task, previous_code, error_summary):
# previous_code/error_summary are None on the first (fresh) call;
# on retries they contain the failed model and structured feedback.
return "... complete Modelica model ..."
Run the benchmark ladder
export ANTHROPIC_API_KEY=...
python examples/run_ladder.py # all 5 tiers
python examples/run_ladder.py --max-tier 3 # subset by difficulty
python examples/run_ladder.py --tasks dc_motor --model claude-opus-4-8
Tiers: (1) pure-equation dynamics, (2) MSL component composition, (3) hybrid
events, (4) verifier-driven design — the requirement is given, the parameter
is not, (5) multi-domain electro-mechanical. Per-task JSON transcripts
(attempt history, diagnostics, code, LLM rounds) land in transcripts/,
with summary.json aggregating results.
Use pieces standalone
from omagent import OMSession, parse_error_string, summarize_for_llm, load_result
s = OMSession()
r = s.load_string(my_modelica_code) # honest success verdict + diagnostics
print(summarize_for_llm(r.diagnostics)) # deduplicated digest for any prompt
sim = s.simulate("MyModel", stopTime=5.0, outputFormat="csv")
res = load_result(sim.value["resultFile"])
times, x = res.series("x")
Project layout
omagent/
errors.py # omc diagnostic parsing + classification
session.py # OMSession: testable wrapper over OMPython/omc
loop.py # AgentLoop + lookup-suggestion feedback
results.py # CSV/.mat readers + quantitative verifiers
llm.py # Anthropic adapter (protocol: bring your own)
tasks.py # benchmark task ladder definitions
runner.py # ladder execution + transcript persistence
examples/ # first_run.py, run_ladder.py
tests/ # 83 unit + 4 integration tests
Design notes
- Testable by construction.
OMSessiontalks to any object withsendExpression(); tests replay recorded omc output, so the full agent loop is unit-tested without a compiler or an API key. - Both OMPython contracts. Older OMPython returns and lets you read
getErrorString(); newer OMPython raisesOMCSessionExceptionon error-level messages. Both yield identical structured failures. - Environment failures are not model failures. The ladder runner loads
the MSL when a task requires it and reports load problems as
environmentoutcomes with zero attempts charged to the LLM.
Roadmap
- Warning-level quality gates (e.g. treat "initial conditions over specified" as a verifier complaint)
- Multi-run variance measurement and cross-model comparison in the runner
- Optional MCP tool surface, composing with OMEdit's built-in MCP server
- More ladder tiers targeting thermal/fluid domains and third-party libraries
License
BSD-3-Clause — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file omagent-0.2.0.tar.gz.
File metadata
- Download URL: omagent-0.2.0.tar.gz
- Upload date:
- Size: 35.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7281e63002052d4c9892fe2be1c759c2bd4b9a70f88d6dbb20ee6b3252531e5a
|
|
| MD5 |
3e9f236eb68541d9c8e9d3adea087e90
|
|
| BLAKE2b-256 |
9dc693b61c1652573fcb3b0d1f005a36829ecf57b3edbc5a50b033ae5672187f
|
Provenance
The following attestation bundles were made for omagent-0.2.0.tar.gz:
Publisher:
publish.yml on MasoudMiM/omagent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
omagent-0.2.0.tar.gz -
Subject digest:
7281e63002052d4c9892fe2be1c759c2bd4b9a70f88d6dbb20ee6b3252531e5a - Sigstore transparency entry: 2384059741
- Sigstore integration time:
-
Permalink:
MasoudMiM/omagent@8c827dcc84789aca93a0076e6715159ca3a6a932 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/MasoudMiM
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8c827dcc84789aca93a0076e6715159ca3a6a932 -
Trigger Event:
release
-
Statement type:
File details
Details for the file omagent-0.2.0-py3-none-any.whl.
File metadata
- Download URL: omagent-0.2.0-py3-none-any.whl
- Upload date:
- Size: 24.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6462c160e408d6aedf53e32d1c3e245bf84976a7051a6ca7100632184b04420
|
|
| MD5 |
2c6f1e79552a12b83cc5b6031e67f893
|
|
| BLAKE2b-256 |
abce404799b20a13297960f7dd80a0263e8cba5790f12d0ed35c94ca29c401f0
|
Provenance
The following attestation bundles were made for omagent-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on MasoudMiM/omagent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
omagent-0.2.0-py3-none-any.whl -
Subject digest:
b6462c160e408d6aedf53e32d1c3e245bf84976a7051a6ca7100632184b04420 - Sigstore transparency entry: 2384060487
- Sigstore integration time:
-
Permalink:
MasoudMiM/omagent@8c827dcc84789aca93a0076e6715159ca3a6a932 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/MasoudMiM
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8c827dcc84789aca93a0076e6715159ca3a6a932 -
Trigger Event:
release
-
Statement type: