Agents pay to interpret your architecture. Every time.
A diagram was made for humans. Handing it to a model turns every task into a reading exercise.
Parsing a draw.io burns tokens
The file is XML full of coordinates, styles and generated ids. The agent pays to recover a graph that was never stored as one.
Screenshots cost more and guess more
Image tokens, then inference about what an arrow means. Push or poll? Sync or async? The model picks one.
The same diagram, a different design each run
Interpretation is probabilistic. Two sessions read the same picture and build two different systems.
Nothing tells the agent it is wrong
There is no feedback loop for a design. Dangling dependencies and broken contracts surface in production, not in the prompt.
A harness for system design.
Context to read, guardrails to respect, feedback to correct. Validation is a program, not a prompt: free and identical every run.
- 01
Context
The agent reads the architecture as typed data. No decoding, no guessing what an arrow means.
- 02
Guardrails
Your rules are policies the change must satisfy: ownership, allowed dependencies, naming, anything CEL can say.
- 03
Feedback
asl compiles the change and returns a few lines of diagnostics. The agent fixes it, and CI blocks the merge on exit 1.
What counts as an antipattern is up to you.
A shared database is fine in some companies and a mistake in yours. Write that rule once, and every architecture an agent proposes is checked against it, before anyone writes code.
01The agent proposes
billing-service needs to record credit data, and writing straight to credit-db is the fastest way to ship the feature.
apiVersion: asl/v1
kind: Application
metadata:
name: credit-service
spec:
providers:
aws: EKS
language: Go
---
apiVersion: asl/v1
kind: Application
metadata:
name: billing-service
spec:
providers:
aws: EKS
language: Go
---
apiVersion: asl/v1
kind: Database
metadata:
name: credit-db
spec:
providers:
aws: RDSPostgreSQL
---
apiVersion: asl/v1
kind: Relationship
metadata:
name: credit-db-edges
spec:
edges:
- from:
kind: Application
name: credit-service
to:
kind: Database
name: credit-db
type: writes
- from:
kind: Application
name: billing-service
to:
kind: Database
name: credit-db
type: writes
02Your context says no
A CustomPolicy, versioned with the code: a database belongs to a single application.
apiVersion: asl/v1
kind: CustomPolicy
metadata:
name: no-shared-database
namespace: acme
spec:
severity: error
selector:
kind: Database
assertions:
- expression: >-
manifests.filter(m, m.kind == 'Application' &&
to(manifest).exists(e, e.from.kind == 'Application' && e.from.name == m.name)).size() <= 1
message: Database must not be shared between applications; each application owns its data
03The compiler answers
No model call. The agent reads four lines, gives billing-service its own data store and runs it again.
error: Database must not be shared between applications; each application owns its data
--> architecture/credit.asl.yaml:18
policy: acme.no-shared-database
error: could not compile due to 1 previous error (10.2ms)
ASL is not diagram as code.
Don't draw the architecture. Specify it.
One compiler. Use it wherever you work.
The same checks and the same verdict in your pipeline, your tools, your browser and your scripts.
In your pipeline
Run it on every pull request. An architecture that breaks a rule fails the build before it merges.
In your own tools
Build the check into the platform or portal your team already uses, and validate architecture where people work.
In a diagram editor
Power a diagram editor: people draw on a canvas while ASL validates the architecture behind it, live and with no server.
In Python
Run the same checks from your scripts and notebooks, next to your data and AI tooling.
Give your agents a design they can read.
Write the rule once. Every agent proposal is checked against it.