Claude
Skills
Sign in
Back

system-composer

Included with Lifetime
$97 forever

Use this skill when authoring reusable, idempotent MATLAB scripts that build System Composer architecture models via the architecture-modeling API — `systemcomposer.createModel`, `addComponent`, `addPort`, `setInterface`, `connect(srcPort, dstPort)`, interface dictionaries (.sldd) with `addInterface`/`addElement`, profiles/stereotypes with `Profile.createProfile` and `addStereotype`, or `systemcomposer.allocation.createAllocationSet`. Also trigger when debugging these APIs (connections that don't appear, interfaces that don't resolve, profile save errors, `createAllocationSet` signature-mismatch errors). Do NOT trigger for ad-hoc structural edits to an already-built model (adding one SubSystem, rewiring a port) — use `building-simulink-models` with `model_edit` for that.

Ads & Marketing

What this skill does


# MATLAB System Composer — Programmatic Authoring Guide

System Composer lets you model multi-domain architectures in MATLAB. This skill captures the
correct API patterns, common gotchas, and a proven script structure for building models reliably.

---

## When to use this skill vs. `building-simulink-models` (SATK)

Both skills can edit System Composer `.slx` files. They work at **different API layers** — don't mix them in one script.

| Concern | This skill (architecture-modeling API) | `building-simulink-models` with `model_edit` (block-diagram API) |
|---|---|---|
| Component creation | `addComponent(arch, "Name")` — returns `systemcomposer.Component` | `add_block` with `type: "SubSystem"` — returns a `blk_id` |
| Ports | `addPort(arch, "Name", "in", iface)` — typed, interface-aware | Bus Element blocks (`In Bus Element` / `Out Bus Element`) inside the SubSystem |
| Connections | `connect(srcPort, dstPort)` — port objects | `{"op": "connect", "target": "blk_X.y1 -> blk_Y.PortName"}` |
| Interface dictionaries (`.sldd`) | First-class (`createDictionary`, `addInterface`, `setInterface`) | Not addressed |
| Profiles / stereotypes | First-class (`Profile.createProfile`, `addStereotype`, `applyStereotype`) | Not addressed |
| Allocation sets (`.mldatx`) | First-class (`systemcomposer.allocation.createAllocationSet`) | Not addressed |
| Auto-layout | **Call `Simulink.BlockDiagram.arrangeSystem` explicitly** before `save` — programmatic adds all land at (0,0) | `model_edit` runs autolayout automatically; its guardrail forbids manual `arrangeSystem` |

**Use this skill when:**
- Writing an idempotent `buildMyModel.m` / `buildMyArchitecture.m` script that will be re-run from scratch
- The architecture uses interface dictionaries, stereotypes/profiles, or allocation sets — `model_edit` has no primitives for any of these
- Debugging SC-specific API failures (CST `connect` shadow, composite `ArchitecturePort` errors, `dict.save` + re-fetch, `profile.save` path, `createAllocationSet` signature mismatch)

**Defer to `building-simulink-models` with `model_edit` when:**
- Making a one-off structural change to an already-built SC model (add one SubSystem, rewire one port, tweak a parameter)
- The user just wants "add a component called X" and the model has no interface dictionary / profile / allocation set the change needs to stay consistent with
- The MBSE workflow in `mbse-workflow` is not involved

**Do not mix in one script.** `model_edit` adds components via `add_block` with `type: "SubSystem"`; this skill adds them via `addComponent`. The two produce different object types and the architecture-modeling APIs in this skill (`setInterface`, `applyStereotype`, `addPort`) may not work on SubSystem-block-created components. Pick one layer per script.

---

## Recommended Script Structure

Keep profile creation in the same script as the architecture — add it at the end,
after the model and connections are built:

```
buildMySystemModel.m    ← architecture + interface dictionary + profile/stereotypes
```

This keeps both artifacts in sync on every rebuild, and avoids the "profile already
applied" uniqueness error that occurs when a separate profile script re-applies a
profile to an already-profiled model.

The script is idempotent: it deletes and recreates all artifacts on every run.

---

## Phase 1+2: Architecture Model + Interface Dictionary

### Skeleton

See [`code/buildMySystemModel.m`](code/buildMySystemModel.m) for the full parameterized function:

```
buildMySystemModel(modelName, dictFile, archDir)
```

---

## Phase 3: Profile & Stereotypes

See [`code/buildMySystemProfile.m`](code/buildMySystemProfile.m) for the full parameterized function:

```
buildMySystemProfile(profileName, modelName, archDir)
```

---

## Critical API Gotchas

These will silently fail or throw cryptic errors without warning:

| What you want | Correct API | Wrong / common mistake |
|---|---|---|
| Connect two component ports | `connect(srcPort, dstPort)` | `connect(arch, srcPort, dstPort)` — silently fails; dispatches to Control System Toolbox |
| Wire a composite boundary port to a sub-component port | `connect(boundaryArchPort, subComp.getPort("Name"))` — boundary is the saved `ArchitecturePort` ref; sub-component is its `ComponentPort` via `getPort` | Connecting two `ArchitecturePort`s across the boundary, or using the boundary's `ComponentPort` — both throw "incompatible directions" |
| Assign interface to port | `port.setInterface(iface)` | `port.Interface = iface` — read-only property error |
| Add interface element | `addElement(iface, "Name", Type="double")` | `Type="MyValueTypeName"` — value type names resolve to `Simulink.ValueType` objects which the bus compiler cannot use; always use a Simulink base type directly |
| Create model | `systemcomposer.createModel(name)` | `systemcomposer.createModel(name, true)` — invalid 2nd arg |
| Set string stereotype property | `setProperty(comp, path, '"value"')` | `setProperty(comp, path, 'value')` — evaluates as MATLAB variable |
| Set string default in addProperty | `DefaultValue='"standard"'` | `DefaultValue="standard"` — evaluates, throws error |
| Apply stereotype property | `setProperty(comp, ...)` | `setPropertyValue(comp, ...)` — wrong function name |
| Close all profiles | `systemcomposer.profile.Profile.closeAll()` | `...closeAll("-discard")` — too many arguments |
| Create profile | `createProfile(name)` | `createProfile(name, "file.xml")` — invalid 2nd arg |
| Look up a component by path | Keep component vars when adding, or use `resolveComponent(arch, 'Parent/Child')` helper | `arch.lookup('Path', ...)` — does not exist |
| Create allocation set | `createAllocationSet(name, srcModelName, dstModelName)` — model **names** | `createAllocationSet(name, srcModelObj, dstModelObj)` — model objects fail on R2025b with unhelpful AllocationAppCatalog signature error |

---

## Why `connect(srcPort, dstPort)` Must Have No Architecture Argument

`connect` is shadowed by Control System Toolbox's `connect.m`. When you write
`connect(arch, srcPort, dstPort)`, MATLAB dispatches to the CST version (which connects
LTI models) instead of System Composer — it returns an empty 0×0 Connector silently.

The two-argument form `connect(srcPort, dstPort)` dispatches correctly via the port object's
class method. Always use this form for explicit port-to-port connections.

For component-to-component auto-wiring by matching port names, the form
`connect(arch, [srcComp,...], [dstComp,...])` is also safe since `arch` dispatches correctly.

---

## Port Multiplicity: Fan-Out Works, Fan-In Needs Separate Ports

A single **output port** can be connected to any number of input ports — just call
`connect(out, in1); connect(out, in2); ...`. This is clean 1→N fan-out; use it for
broadcast buses (e.g. `Supervisory.Schedule` feeding every production unit).

A single **input port** cannot receive connections from multiple sources. SC is a
structural modelling tool with no merge semantics — attempting to hook two
outputs into one input either errors or silently fails. Give the destination
component **separate named input ports** for each source (e.g.
`Status_Cook`, `Status_Pack`, `Status_Load`) and wire 1:1. This pattern is
verbose but unambiguous and matches how an MBSE diagram will render for review.

---

## Composite Components: Mix ArchitecturePort and ComponentPort for Internal Wiring

When a component has sub-components (a composite), its boundary ports have two views:

| View | Accessed via | Class | Used for |
|---|---|---|---|
| External | `comp.Ports` / `comp.getPort(name)` | `ComponentPort` | Connections in the **parent** arch |
| Internal | return value of `addPort(comp.Architecture, ...)` | `ArchitecturePort` | Connections **inside** the composite, to sub-component ports |

A boundary "in" port acts as a *source* from inside the composite's sub-architecture (it delivers data to the sub-components), but its external `ComponentPort` still reports

Related in Ads & Marketing