Runtimemodel.yaml schema

model.yaml schema

model.yaml describes one packaged BioModule: its name and version, how to load it, its input and output ports, its dependencies, and optional ONNX and compatibility details.

Schema

schema_version: "2.0"
title: string
description: string
standard: sbml | neuroml | cellml | nmodl | onnx | other
package: namespace/name
version: 1.2.3
license_type: unknown | mit | apache_2 | cc_by | cc_by_sa | proprietary
authors: [string]
tags: [string]
species: [string]
 
biosim:
  entrypoint: module.path:ClassName
  init_kwargs: object
  setup: object
  communication_step: positive number
  execution_policy: once_before_run | each_window | once_after_run
 
io:
  inputs: [SignalSpec]
  outputs: [SignalSpec]
 
runtime:
  python_version: "3.12"
  dependencies:
    packages: [exact==pins]
    requirements_file: relative/path.txt
    lockfile: relative/lock.file
  remote:
    requirements:
      accelerator: gpu
      gpu_count: positive integer
 
onnx:
  task: string
  model_file: relative/path.onnx
  class_labels: [string]
  inputs: [TensorSpec]
  outputs: [TensorSpec]

Top-level fields

FieldTypeRequiredMeaning
schema_versionstringCurrent packagesManifest shape; current value is "2.0"
titlestringRecommendedHuman-facing model name
descriptionstringRecommendedScope, method, and intended-use summary
standardenumYesPrimary model/artifact family
packagestringFor releasesStable namespace/name identity
versionSemVerFor releasesExact release version, such as 1.0.0
license_type or licenseenum/stringRecommendedDistribution/use license; unknown values normalize to unknown
authorsstring[]NoAuthor names or attributions
tagsstring[]NoSearch and discovery tags
speciesstring[]NoSpecies, for search and discovery. To check compatibility, set species in a port contract instead.
biosimobjectYesHow to load the model’s Python code
ioobjectRecommendedThe model’s input and output ports
runtimeobjectNoPython, dependency, and remote resource requirements
onnxobjectFor ONNXONNX artifact and tensor metadata

Package identity

package is the stable namespace/name identifier and version is the exact SemVer package version, such as 1.0.0. Together they form the package ref namespace/name@x.y.z.

When you build or publish a package, version must be exact SemVer. latest and other non-SemVer values are rejected. This rule is for manifests. CLI commands such as labs pull accept a ref without a version; see Package and publish.

A lab does not reference a model by package. Its models[] entries use a relative path. To add a model source tree to a lab:

biosimulant labs add-model ./models/hh-population --lab ./my-lab --alias hh

add-model writes the relative path and alias into the lab’s lab.yaml.

biosim block

biosim:
  entrypoint: "src.hh_population:HHPopulation"
  init_kwargs:
    n: 100
  setup:
    seed: 1234
  communication_step: 0.001
FieldTypeRequiredBehavior
entrypointstringYesPython symbol in module.path:ClassName form
init_kwargsobjectNoConstructor kwargs merged with lab-level parameter overrides
setupobjectNoDefault setup() config for the module
communication_stepnumber > 0YesDefault coupling step for this packaged model
execution_policyenumNoChecked copy of the Python class’s execution policy; see Execution policy

Model-entry parameters in a lab are constructor overrides. They are merged into biosim.init_kwargs before the entrypoint factory is called. Runtime inputs are separate: declare them under io.inputs and pass values through run-time input payloads.

Execution policy

biosim.execution_policy repeats the execution policy your Python class declares, so tools that can’t import model code (Studio, Desktop and the Hub) can tell when the model runs. It needs biosimulant>=0.0.33.

biosim:
  entrypoint: "src.predictor:Predictor"
  communication_step: 0.01
  execution_policy: once_before_run
ValuePython declaration
once_before_runExecutionPolicy.ONCE_BEFORE_RUN
each_windowExecutionPolicy.EACH_WINDOW
once_after_runExecutionPolicy.ONCE_AFTER_RUN

The Python execution_policy attribute is still the only thing that decides when BioWorld runs the module. The manifest field is a copy that Biosimulant checks against your code:

  • When the model loads, the runtime compares the field with the policy of the constructed module. If they differ, the model doesn’t load, and the error names both values.
  • biosimulant labs validate reads the entrypoint source without importing it. It reports an error when the source clearly resolves to a different policy, and a warning when it can’t verify the value, for example when __init__ sets the policy from a parameter.
  • For a model that doesn’t declare the field, labs validate suggests the value to add when it can read the policy from source.

Declare the policy your module resolves to:

Your classDeclare
Sets execution_policy as a class attributeThat value
Sets self.execution_policy to a fixed value in __init__That value
Implements execute() and sets no policyeach_window. BioWorld warns that the policy is implicit; declaring each_window in model.yaml clears the warning.
Implements advance_window()each_window

Leave the field out when the policy depends on constructor parameters. Tools then treat the model as undeclared.

A lab can’t override a model’s policy. You can mix policies in one lab, as long as the wiring between them is valid. See Execution timing for the wiring rules and for how declared policies change the run settings a lab shows.

Ports (io)

Some tooling still accepts plain lists of port names, but new manifests should use typed ports like these:

io:
  inputs:
    - name: current
      signal_type: scalar
      dtype: float64
      description: External current injection
    - name: spikes
      signal_type: event
      schema:
        ids: list[int]
  outputs:
    - name: membrane_potential
      signal_type: scalar
      dtype: float64
      emitted_unit: mV
    - name: state
      signal_type: record
      schema:
        v: float64
        u: float64

Use the manifest to describe what the module publishes and accepts. The runtime signal classes are still emitted from Python code.

Run-time input payload values are checked and converted against these input declarations before the module receives them. Raw scalar, array, record, and event payloads become typed BioSignal instances when exactly one accepted input profile matches. If a port accepts multiple profiles or units, provide an explicit typed input envelope with value, signal_type, dtype, shape, schema, and/or emitted_unit.

SignalSpec: common port fields

FieldTypeDefaultRules
namestringRequired and unique within its direction
signal_typescalar | array | record | eventStructural signal category
kindstate | eventDerivedEvents require event; all other signals require state
dtypestringnullNumeric or implementation dtype; linear interpolation requires a numeric dtype
shapeinteger/wildcard listnullArrays require shape; scalars, records, and events cannot use an array shape in runtime declarations
schemaobjectnullRecord field schema; records require it
interpolationzoh | linear | nonezohEvents require none; linear is numeric scalar/array only
max_agenumber ≥ 0nullMaximum accepted state age before staleness policy
stale_policyignore | warn | errorwarnRuntime response to an older-than-max_age value
descriptionstringnullHuman port description
value_type or typestring | number | integer | boolean | record | array | filenullInput-form and coercion metadata
formatstringnullFormat hint, such as URI or a domain-specific textual format
requiredbooleannullWhether a user/run input must be supplied
defaultJSON valuenullDefault run-input value
advancedbooleannullMarks advanced authoring/UI controls
examplesJSON[]nullExample values
allowed_valuesJSON[]nullClosed authoring choice list
fileobjectnullFile-picker, media, extension, or size metadata
uiobjectnullUI presentation hints; not runtime semantics
contractobjectnullCompatibility declaration with one exact profile and, when relevant, species and identifier_namespace

All defaults, examples, allowed values, file, ui, and contract values must be JSON-serializable.

Input-only fields

An input can set accepted_units directly when its other structural fields have one representation. Use accepted_profiles only when it genuinely accepts multiple structural representations.

FieldTypeMeaning
accepted_unitsstring[]Units accepted without conversion

accepted_profiles lists alternate structural representations accepted by one input. Each entry supports:

FieldTypeMeaning
signal_typesignal enumAccepted signal category
dtypestringAccepted dtype
shapelistAccepted array shape
schemaobjectAccepted record schema
accepted_unitsstring[]Directly accepted units
formatstringAccepted file or textual format
descriptionstringRepresentation explanation
contractobjectOptional semantic contract for this representation

If accepted_profiles is omitted, the input’s own structural fields form its single accepted profile. An input cannot set emitted_unit.

Output-only fields

emitted_unit is the unit an output sends. Outputs cannot declare accepted_units or accepted_profiles. An output’s contract describes what the output sends.

Lifecycle and staleness example

io:
  inputs:
    - name: concentration
      signal_type: scalar
      kind: state
      dtype: float64
      interpolation: linear
      max_age: 0.5
      stale_policy: error
      accepted_profiles:
        - dtype: float64
          accepted_units: [nM, uM]
  outputs:
    - name: spike
      signal_type: event
      kind: event
      interpolation: none
      schema:
        neuron_id: string
        time: float64

Dependencies

runtime:
  python_version: "3.12"
  dependencies:
    packages:
      - numpy==1.26.4
      - scipy==1.12.0
    requirements_file: requirements.txt
FieldRule
python_versionSupported minor version, currently 3.10–3.14 in the open-source packager
dependencies.packagesEvery installable package uses an exact == pin
dependencies.requirements_fileRelative path to a requirements declaration
dependencies.lockfileRelative path to a dependency lock

Open-source biosimulant labs run only installs exact-pinned package specs into the current Python environment. Runs on the Biosimulant platform use isolated per-lock-hash environments and apply allow/deny dependency policy. Keep manifests portable by pinning dependencies exactly when package installation is expected.

Remote execution requirements

Models that require accelerator-backed remote execution can declare the requirement in runtime.remote.requirements:

runtime:
  remote:
    requirements:
      accelerator: gpu
      gpu_count: 1

accelerator: gpu marks the model as requiring a GPU-backed remote size. In the remote execution catalog, GPU-backed means the size has a non-empty gpu_type. gpu_count is the number of GPUs required. CPU-compatible models omit this block.

Lab authors should not duplicate model resource requirements in lab.yaml; Biosimulant aggregates model requirements into the resolved lab graph at run time.

ONNX metadata

When standard: onnx, include an onnx block describing the model artifact and tensor signatures:

onnx:
  task: classification
  model_file: data/assets/model.onnx
  class_labels: [quiescent, subthreshold, spiking]
  inputs:
    - name: input
      dtype: float32
      shape: [-1, 10]
  outputs:
    - name: probabilities
      dtype: float32
      shape: [-1, 3]
FieldMeaning
taskComputational task, such as classification or regression
model_fileRelative path to the ONNX model file
class_labelsOutput labels, in order
inputs, outputsTensor name, dtype, shape, and description metadata

If io is absent, some ingestion tooling can derive ports from ONNX tensor metadata. New packages should declare io explicitly so every Biosimulant tool sees the same ports.

Compatibility

A contract directly on an input or output tells Biosimulant which versioned profile describes the port. A model with any contract must declare the standard once at the top level.

compatibility:
  standard: biosimulant.model-compatibility
  version: "0"
 
io:
  inputs:
    - name: protein_sequence
      signal_type: scalar
      dtype: str
      format: sequence
      contract:
        profile: protein.sequence/v1
        species: any

profile is required when the contract is present. species and identifier_namespace are optional and only allowed when the profile permits them. Shape, format, value type and units remain normal port fields rather than being repeated in the contract. The v0 compatibility block accepts only standard and version; the model does not copy catalogue or profile digests.

Contracts are optional. If only one side of a wire declares a profile, a structurally valid connection is allowed with a PROFILE_PARTIAL warning. The declared profile still checks live values, but scientific compatibility is not verified. When both ports declare profiles, they must reference the same exact profile and agree on representation and required context. Values are checked again during a run.

See Use compatibility in a model for a complete example and Propose a profile when no existing profile is accurate.

Directory layout

my-model/
  model.yaml
  src/
    my_module.py
  artifacts/
  data/
    assets/
      model.onnx
  tests/
  requirements.txt

Validate and build

Add the model to biosimulant-packages.yaml with type: model, then validate and build:

biosimulant labs release validate biosimulant-packages.yaml
biosimulant labs release build biosimulant-packages.yaml --out dist/biosimulant-packages

Port contracts stay in payload/model.yaml. The package builder does not create a separate compatibility lock file.

See also