<!-- Source: https://docs.biosimulant.com/references/library/model-manifest -->

# model.yaml Schema

`model.yaml` declares a packaged BioModule: its entrypoint, communication-step assumptions, typed port metadata, dependencies, and optional ONNX details.

## Schema

```yaml
schema_version: "2.0"
title: string
description: string
standard: sbml | neuroml | cellml | nmodl | onnx | other
package: string
version: string

biosim:
  entrypoint: string
  init_kwargs: object
  setup: object
  communication_step: number

io:
  inputs:
    - name: string
      signal_type: scalar | array | record | event
      dtype: string
      shape: list
      schema: object
      accepted_profiles: list
      description: string
  outputs:
    - name: string
      signal_type: scalar | array | record | event
      dtype: string
      shape: list
      schema: object
      emitted_unit: string
      description: string

runtime:
  python_version: string
  dependencies:
    packages: [string]
    requirements_file: string
    lockfile: string
  remote:
    requirements:
      accelerator: gpu
      gpu_count: number

metadata:
  authors: [string]
  tags: [string]
  species: [string]

onnx:
  task: string
  model_file: string
  class_labels: [string]
  inputs: [...]
  outputs: [...]
```

## Package identity

For Hub-backed packages, `package` is the stable `namespace/name` identifier and `version` is the exact SemVer package version. Together they form the package ref consumed by the CLI and Desktop:

```text
namespace/name@x.y.z
```

For example, a model manifest with `package: biosimulant/hh-population` and `version: 1.0.0` is pulled with:

```bash
biosimulant labs add-model ./my-lab ./models/hh-population --as hh
```

The version is explicit by design. Package resolution rejects missing or invalid versions instead of inferring `latest`.

## `biosim` block

```yaml
biosim:
  entrypoint: "src.hh_population:HHPopulation"
  init_kwargs:
    n: 100
  setup:
    seed: 1234
  communication_step: 0.001
```

`biosim.communication_step` is required and must be positive.

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.

## I/O contract

String-only port lists are still accepted in some tooling, but current-kernel manifests should prefer structured typed ports.

```yaml
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 coerced against this input contract before
`module.set_inputs(...)` runs. 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`.

## Dependencies

```yaml
runtime:
  python_version: "3.12"
  dependencies:
    packages:
      - numpy==1.26.4
      - scipy==1.12.0
    requirements_file: requirements.txt
```

Open-source `biosimulant labs run` only installs exact-pinned package specs into the
current Python environment. Biosimulant platform and Desktop runs 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`:

```yaml
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`.

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:

```yaml
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]
```

## Directory layout

```text
my-model/
  model.yaml
  src/
    my_module.py
  data/
    assets/
      model.onnx
  requirements.txt
```

## See Also

- [How to Write a model.yaml](/how-to/library/write-model-manifest)
- [lab.yaml Schema](/references/library/lab-manifest)
- [How to Add an ONNX Model](/how-to/library/add-onnx-model)
