Stop redeploying to change what your app decides.
Model-backed decisions live in versioned YAML or JSON files. A saved edit applies on the next call, and every run is tagged with the intent name, version and file it used.
One file per decision.
A name the code calls, a version you raise with every change, an owner, the instruction, the result shape, the rules and examples. The same fields work in JSON.
- name
- What the code calls:
RunIntentAsync<int>("Orders.ClassifyUrgency"). - version
- Raise it with every change, so the audit trail can tell versions apart.
- owner
- Who answers for the behaviour, for audit and listings.
- intent
- The instruction the model receives.
- shape
- What comes back: here a whole number; also a registered .NET type or a JSON schema.
- rules
- The limits every answer must pass before your code sees it.
- examples
- Inputs and the outputs you expect, shown to the model.
name: Orders.ClassifyUrgencyversion: 1owner: order-deskintent: Rate the urgency of this order email from 1 (routine) to 5 (critical).shape: intrules: minimum: 1 maximum: 5examples: - input: "Line 3 is down until the bearings arrive. Ship today." output: 5 - input: "Please restock these when convenient, no rush." output: 1The quick start's own intent file, as the site build reads it.
Save, and the next call uses it.
The folder is watched. When a file changes, the catalog reloads it and swaps in the new definitions at once, and calls already running finish on the old one. No rebuild, no restart.
name: Orders.ClassifyUrgencyversion: 2owner: order-deskintent: Rate the urgency of this order email from 1 (routine) to 3 (critical).shape: intrules: minimum: 1 maximum: 3examples: - input: "Line 3 is down until the bearings arrive. Ship today." output: 3 - input: "Please restock these when convenient, no rush." output: 1Scripted model answer: {"value": 3}Success: trueValue: 3Issues: noneintent.name: Orders.ClassifyUrgencyintent.version: 2intent.source: Orders.ClassifyUrgency.intent.yamlA bad save keeps the last good version.
A file that fails to load never takes an intent away from a running application. The last good definition stays in force, and the problem is reported with the file and the line, in the warning log and in catalog.Current.Problems.
Fix the file and the next reload picks it up.
rules:
minimum: 1
maximum: threecatalog.Current.Problems: Orders.ClassifyUrgency.intent.yaml:8: Intent "Orders.ClassifyUrgency": "rules.maximum" must be a number; found "three". Orders.ClassifyUrgency.intent.yaml: Kept the last good definitions from this file (Orders.ClassifyUrgency v2) until it loads cleanly.In force: Orders.ClassifyUrgency version 2Every run says which version decided.
Each run is tagged with the intent's name, version and source file. The tags reach the memory entry the run records, and the one log line written per run names the intent and its version, so a decision can be traced to the wording and the rules that made it.
intent.name: Orders.ClassifyUrgencyintent.version: 2intent.source: Orders.ClassifyUrgency.intent.yamlA file cannot run code.
Intent files hold data only. A rule can name a check or a .NET type, but only one your application registered by name; nothing in a file can load code. Limits on YAML nesting and aliases turn a hostile file into a reported problem.
- Allowed in a file: wording, examples, limits, allowed values, patterns and a JSON schema.
- Only by a registered name: code validators and .NET result types.
- Never: expressions, scripts or type loading.
Treat the folder like production configuration.
Behaviour now changes without a deployment, so the intent folder deserves the care you give the code.
- Keep intent files in source control and review changes as you review code.
- Raise
versionwith every change, so the audit trail can tell versions apart. - Limit who can write to the folder: anyone who can write it changes what the application decides.
- Watch the warning log or
Current.Problemsafter every change. - Switch an intent off with
enabled: falserather than deleting it; callers then get a clearIntentDisabledException.
Limits, stated plainly.
- Versions are reported, not enforced: a change that keeps or lowers the version is logged, not refused, and only against the previous load in the same process.
- Reload is tested on local folders. Network shares, Kubernetes ConfigMaps and editors that save through a temporary file and a rename are not tested yet.