Yaml Model Reference
Yaml Model Reference

Detailed reference for IOModel YAML model structure, syntax, and file-based authoring.

This reference explains how IOModel YAML models are structured in real projects, including the exact file layout used in apps/studio/content/example-saas/models and schema definitions from packages/model-schema/assets.

What this page covers

You will learn: 1) how model files are split, 2) which keys are supported at model/object/link level, 3) how schema-driven types (c4, kubernetes) affect authoring.

File structure (project-level)

IOModel projects use a root index file and per-model files:

# models.yaml
models:
  example-saas: null
# models/example-saas.yaml
title: Multi-Tenant SaaS Platform
type: model
description: Reference architecture for a B2B SaaS product.
objects:
  actors: null
  external_systems: null
  product: null
workflows: {}

And then each object can be split into its own file under:

models/example-saas/objects/<slug>.yaml
models/example-saas/objects/<slug>/<child>.yaml
...

For example:

# models/example-saas/objects/product/application/api_service.yaml
title: API Service
type: microservice:service
description: Tenant-aware REST + WebSocket API.
objects:
  rest_router: null
  tenant_filter: null
  ws_gateway: null
  rate_limiter: null

Core YAML keys

Model root keys (models/<model>.yaml)

KeyTypeRequiredExamplePurpose
titlestringnotitle: Multi-Tenant SaaS PlatformHuman-readable model name
typestringnotype: modelModel category label
descriptionstringnodescription: ...Summary for UI/docs
iconstringnoicon: lucide:boxOptional model icon
objects_schemastringnoobjects_schema: c4Object vocabulary: a built-in id, your own schema, or a schema URL
objectsmapyes (practical)objects: { product: null }Root object tree
workflowsmapnoworkflows: {}Workflow definitions (if used)

Object keys (.../objects/*.yaml)

The parser handles these object keys directly:

KeyTypeExampleNotes
titlestringtitle: Tenant ServiceDisplay title
typestringtype: container:databaseObject type; subtype is base:subtype
descriptionstringdescription: Owns tenant records.Text description
iconstringicon: lucide:serverOptional override icon
group_typestringgroup_type: productGroup/category marker
refstringref: product.application.api_serviceReference pointer
attributesmapattributes: { owner: [a@x.com] }Free-form attributes
tagsarraytags: [domain:billing, env:prod]group:value tags
linksarraylinks: [{ id: api_service }]Outgoing links
link_toarraylink_to: [{ id: product.application }]Belongs-to links
attachmentsmap/arrayattachments: { handbook: { ... } }Attached files (MDX, OpenAPI, ERD, SQL, …)
attachments_view_modemapattachments_view_mode: { overview: [...] }Attachment display order
objectsmapobjects: { router: null }Child object slugs
modelsmapmodels: {}Reserved/advanced
articlestring/maparticle: ...Optional content reference
idstringid: custom-idExplicit id when needed

Any extra top-level keys not listed above are still preserved as custom object properties. This is useful for schema-specific fields such as team_owner, status, tech, etc.

Retired key `artifacts:`

The parser no longer reads artifacts:. Rename it to attachments: (Studio reports retired-yaml-key until you do). Cloud projects can be rewritten with a one-off migrate; on disk, rename the key in YAML.

A link entry can be a short scalar or an object form.

Short form

links:
  - api_service

Extended form

links:
  - id: product.application.api_service
    description: Calls API for tenant operations
    type: sync
    required: true
    tags:
      - flow:request
    attributes:
      protocol: https

Common reference patterns:

  • Relative sibling: api_service
  • Relative parent scope: product.application
  • Absolute path: example-saas.product.application.api_service

If a reference cannot be resolved, parser diagnostics include an unknown-reference error.

Schema-driven modeling

The objects_schema on the model root selects the object vocabulary — which type values exist, which subtypes (encoded in type as base:subtype) are allowed, which property fields appear, and how objects look on the diagram. The default is c4.

objects_schema accepts three forms:

FormExampleUse when
Built-in idobjects_schema: c4Standard C4 or Kubernetes modeling
Custom schemaobjects_schema: my-schemaYou define your own object vocabulary
Schema URLobjects_schema: https://example.com/schemas/my-schema.yamlReuse a shared schema published at an open URL

Bring your own schema

You are not limited to the built-in vocabularies. You can author a custom schema for your own object types and properties, or point objects_schema at a schema published on an open URL to reuse it across projects. See Custom Schemas for the authoring format.

The built-in c4 schema defines:

  • object types such as actor, organization, product, domain, system, subsystem, container, component, microservice, external
  • subtypes such as broker, broker:kafka, broker:rmq, database, storage, library, package, module
  • shared properties like team, owner, status, tech
  • broker objects can own channels; links can name a channel so a message path is visible on Explore

Example C4-style object:

title: Billing Service
type: container:service
description: Handles subscriptions and invoices.
tech:
  - typescript
  - postgresql
status: active

Build a model from files (like example-saas)

Create root index

Start with models.yaml and register your model slug:

models:
  my-product: null

Create model root file

Create models/my-product.yaml with root metadata and first-level objects:

title: My Product
type: model
description: Reference architecture for My Product.
objects_schema: c4
objects:
  actors: null
  product: null
workflows: {}

Split objects into focused files

Create object files under models/my-product/objects/... and keep each file responsible for one object.

Add hierarchy with objects

In each object file, declare child slugs:

objects:
  api_service: null
  worker_service: null

Add relationships with links

Connect objects explicitly:

links:
  - id: api_service
    label: calls

Enrich incrementally

Add schema-aligned fields (status, tech, owners), tags, and attachments as needed.

Practical conventions

  • Keep slugs stable (snake_case or kebab_case) because links depend on them.
  • Prefer one object per file after the first nesting level for cleaner diffs.
  • Use relative link ids inside one subtree, absolute ids for cross-domain links.
  • Set objects_schema early (built-in, custom, or URL) so object types stay consistent.
  • Start minimal (title, type, description, objects) and expand with attributes later.

Last updated on