Introduction to CALM Patterns
Overviewโ
Learn how CALM Patterns enable you to define reusable architecture templates that can both generate new architectures and validate existing ones.
Learning objectivesโ
By the end of this tutorial, you will:
- Understand the dual superpower of Patterns: generation and validation
- Know how Patterns use JSON Schema keywords (
const,prefixItems,minItems/maxItems,$ref) - Create a Pattern for a 3-tier web application
- Generate a new architecture from your Pattern
- Validate both a passing and a failing architecture against the Pattern
- Understand placeholder warnings in generated architectures
Prerequisitesโ
Complete Generate Operations Documentation first.
Step-by-Step Guideโ
1. Understand What Patterns Areโ
The Problem Patterns Solve:
- Teams keep building similar architectures from scratch
- No easy way to enforce "all web apps must have these components"
- Inconsistent structures across projects
The Solution: CALM Patterns pre-define the required structure of an architecture. They specify which nodes must exist, what relationships must connect them, and what properties they must have.
2. Understand the Dual Superpowerโ
One Pattern = Two Powers:
Power 1 โ Generation:
calm generate -p my-pattern.json -o new-architecture.json
Power 2 โ Validation:
calm validate -p my-pattern.json -a existing-architecture.json
3. Understand How Patterns Workโ
Patterns use JSON Schema keywords to define requirements:
| Keyword | Purpose | Example |
|---|---|---|
const | Requires an exact value | "unique-id": { "const": "api-gateway" } |
prefixItems | Defines exact ordered items in an array | First node must be X, second must be Y |
minItems / maxItems | Enforces array length | Exactly 3 nodes |
$ref | References other schemas | Point to a node or Standards definition |
Example: requiring a specific node
{
"nodes": {
"type": "array",
"prefixItems": [
{
"properties": {
"unique-id": { "const": "api-gateway" },
"node-type": { "const": "service" },
"name": { "const": "API Gateway" }
}
}
],
"minItems": 1
}
}
4. Create Your First Patternโ
Prompt:
Create a CALM pattern at patterns/web-app-pattern.json for a 3-tier web application.
The pattern should:
1. Have a unique $id (https://example.com/patterns/web-app-pattern.json)
2. Have title "Web Application Pattern" and a description
3. Require exactly 3 nodes using prefixItems:
- "web-frontend" (node-type: webclient, name: "Web Frontend")
- "api-service" (node-type: service, name: "API Service")
- "app-database" (node-type: database, name: "Application Database")
4. Require exactly 2 relationships:
- "frontend-to-api": connects web-frontend to api-service
- "api-to-database": connects api-service to app-database
Use const for unique-id, node-type, and name properties.
Set minItems and maxItems to enforce exact counts.
5. Test Generationโ
calm generate -p patterns/web-app-pattern.json -o architectures/generated-webapp.json
Open architectures/generated-webapp.json and verify:
- โ Has exactly 3 nodes with the correct IDs, types, and names
- โ Has exactly 2 relationships connecting them
6. Visualize the Generated Architectureโ
- Open
architectures/generated-webapp.jsonin VSCode - Open preview (
Ctrl+Shift+C/Cmd+Shift+C) - See the 3-tier architecture visualized
7. Test Validation โ Passing Case with Warningsโ
calm validate -p patterns/web-app-pattern.json -a architectures/generated-webapp.json
Should pass โ but show warnings about placeholder strings:
{
"spectralSchemaValidationOutputs": [
{
"code": "architecture-has-no-placeholder-properties-string",
"severity": "warning",
"message": "String placeholder detected in architecture.",
"path": "/nodes/0/description"
}
],
"hasErrors": false,
"hasWarnings": true
}
String placeholders look like "[[ DESCRIPTION ]]". Numeric placeholders use -1. These warn you that the generated architecture needs to be filled in โ they are not errors.
8. Test Validation โ Failing Caseโ
Create a broken architecture to see validation fail:
- Copy
architectures/generated-webapp.jsontoarchitectures/broken-webapp.json - Change the
unique-idof"api-service"to"backend-api"
calm validate -p patterns/web-app-pattern.json -a architectures/broken-webapp.json
Should fail โ โ the pattern catches that "api-service" is missing. You'll also see errors for relationships referencing the now-missing node ID.
9. Enhance the Generated Architectureโ
Prompt:
Update architectures/generated-webapp.json to add:
1. Descriptions for each node explaining their purpose
2. A description for each relationship
3. Interfaces on api-service (host, port for HTTPS)
4. Interfaces on app-database (host, port for PostgreSQL)
Keep the unique-ids, node-types, and names exactly as they are.
10. Validate the Enhanced Architectureโ
calm validate -p patterns/web-app-pattern.json -a architectures/generated-webapp.json
{
"jsonSchemaValidationOutputs": [],
"spectralSchemaValidationOutputs": [],
"hasErrors": false,
"hasWarnings": false
}
No warnings โ โ adding extra properties doesn't break pattern compliance.
Before moving on, use git to capture the state of your work. A descriptive commit message will help future-you understand what changed and why.
Key conceptsโ
Pattern Anatomyโ
| Keyword | Enforces | Allows |
|---|---|---|
const | Exact value | Nothing else |
prefixItems | Specific ordered items | Additional items after them |
minItems + maxItems (equal) | Exact array length | โ |
$ref | Schema from another file | Properties defined there |
Placeholdersโ
Generated architectures use placeholders as signals:
- String:
"[[ DESCRIPTION ]]"โ must be replaced before production - Numeric:
-1for numeric fields like port numbers
Pattern vs Architectureโ
A Pattern defines the shape any matching architecture must have. An architecture that satisfies the Pattern is free to add extra nodes, relationships, interfaces, and metadata โ Patterns only constrain what they explicitly specify.
Resourcesโ
Troubleshootingโ
If your pattern won't generate a valid architecture, use this prompt with the CALM Agent:
My pattern doesn't generate a valid architecture when I run the generate command.
Look at this valid pattern for reference:
https://raw.githubusercontent.com/finos/architecture-as-code/refs/heads/main/conferences/osff-ln-2025/workshop/conference-signup.pattern.json
Identify the problem in my pattern.
Next stepsโ
In the next tutorial, you'll learn how to create organizational Standards โ JSON Schema extensions that define required properties like cost centers, owner fields, and compliance tags!