Every business-rule change is a code change and a release.
When routing criteria and the allowed answers are compiled into C#, a change in the business waits for a build, a review and a deployment. With IntentSharp they live in an intent file that your code calls by name, the criteria in plain words for the model and the allowed answers as rules checked in your process, and a saved edit applies to the next request while the application runs.
What it costs today
The rules that decide where an order goes rarely stay put. A new queue for large orders, another cut-off for expedited shipping or a seasonal exception comes from the business, and each one becomes a ticket for a developer: find the method, change the condition, add a test, wait for the next release.
The people who know the rule cannot change it, and the people who can change it have to be told what it means. The cost is not the edit. It is the delay between a decision and the code that carries it out, and the risk of a deployment made only to change a number or a word.
How IntentSharp handles it
The routing criteria, the queues and the allowed answers are in Orders.Route.intent.yaml, and the order service calls the intent by name. Version 2 of the file adds a review queue and, in the intent's words, the criterion for it: more than 200 units. It is saved while the program runs, and the same call routes the same email by it.
name: Orders.Routeversion: 1owner: order-deskintent: >- Choose the queue for this order email. expedite: the customer needs it within three days. standard: every other order.shape: textrules: enum: [standard, expedite]name: Orders.Routeversion: 2owner: order-deskintent: >- Choose the queue for this order email. review: over 200 units; expedite: within three days. standard: every other order.shape: textrules: enum: [standard, expedite, review]// Loads the folder's intent files, then watches the folder: a// saved edit reloads while the app runs.using var catalog = new FileIntentCatalog(intentsFolder);var intents = new IntentRuntime(client, catalog); // The order service's one routing call. The file decides the// queues, the criteria and the allowed answers.Task<AIResult<string>> RouteAsync(string email) => email.RunIntentAsync<string>(intents, "Orders.Route");Before the save: Orders.Route version 1, allowed answers: standard, expedite Success: true Value: expedite After the save, the next call: Orders.Route version 2, allowed answers: standard, expedite, review Success: true Value: reviewChanged lines in version 2 are marked. The catalog watches its folder, so nothing in the program reloads it. Compiled and run with every build of this site; the model's answers are scripted, and a pass means the answer met the rules, not that the judgement is right.
What stays in your control
The file holds the rule. Your code keeps the call, the types and what to do with the answer.
- The criteria are judgement. The intent's words, such as over 200 units, tell the model what to apply; only the file's
rulesare checked in your process. A pass means the queue is one the file allows, not that the order met the criterion. A threshold that must hold exactly stays in code, or return the quantity with the queue and check it in a C# check your application registers and the file switches on undervalidators. - The allowed answers. The file's
rulesare checked in your process on every answer, with no model call. Hereenumkeeps the queue to the names the file lists, and an answer outside them fails and goes back to the model with the finding. - When an edit takes effect. The next call after a save uses the new version. A call already running finishes on the version it started with.
- A bad save. While the application runs, a file that fails to load keeps its last good version in force, and the problem is reported with the file and the line in
catalog.Current.Problemsand the warning log. After a restart, a file that still fails to load is reported, and its broken definitions do not load. - Which version answered. Each run is tagged with the intent's name, version and source file. Raise
versionwith every change: versions are reported, not enforced. - What still needs a release. A new .NET result type, a new named code check, and code that calls a new intent by name.
- Who can change it. Anyone who can write to the folder changes how the intent behaves, so keep the files in source control and limit who can write there. Reload is tested on local folders.
Read next
Intent files
Live reload step by step, a bad save, who changes what, and the limits.
Running intents from files
Load a folder, run an intent by name, and what throws before any model call.
Intent file reference
Shapes, the thirteen rules and what each one checks.
More problems and their answers: Solutions.
Move one rule into a file.
dotnet add package IntentSharp --prereleasedotnet add package IntentSharp.Catalog --prerelease