Skip to main content

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 as Basic.EMF vs. MSL 4.x Basic.RotationalEMF)
  • Quantitative verification — reads CSV or Dymola-format .mat results; 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; an Anthropic adapter ships, any provider or local model plugs in
  • 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 omc sessions do not. If models using Modelica.* 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)

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. OMSession talks to any object with sendExpression(); 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 raises OMCSessionException on 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 environment outcomes 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

omagent-0.1.0.tar.gz (34.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

omagent-0.1.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file omagent-0.1.0.tar.gz.

File metadata

  • Download URL: omagent-0.1.0.tar.gz
  • Upload date:
  • Size: 34.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for omagent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1c2024b449b6611f5481469d55ab6d657c5f89ffca6e1734deae00dad57b95e3
MD5 9abebd83b93a5ac882dbce647fa9b40d
BLAKE2b-256 35b5a1d0bfdd7a82b99e9b4c1f234edb5e7c3140fb3c28e9edd39eee7bc45b0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for omagent-0.1.0.tar.gz:

Publisher: publish.yml on MasoudMiM/omagent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file omagent-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: omagent-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for omagent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 653b09c6fbd25fadd8d7ef892397140db6e9f751d1d80fbeda2c3588f17c8982
MD5 7aa925d48d56bc69efd61a9ef506833e
BLAKE2b-256 ecc02397772c440a896f283131a1999551dfa990d486df5fa9bbbec820b36990

See more details on using hashes here.

Provenance

The following attestation bundles were made for omagent-0.1.0-py3-none-any.whl:

Publisher: publish.yml on MasoudMiM/omagent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page