Intent file reference
Intent files explains what an intent file is for and what each of its twenty fields means. This page has the details you need while writing one: how files are found, the shapes and the .NET types each one returns, each of the thirteen rules, how to write examples, and the duration format. Loading and running the files from code is in Running intents from files.
Files
- The catalog loads every file named
*.intent.yaml,*.intent.ymlor*.intent.jsonin its folder, and in its subfolders unlessIncludeSubdirectoriesis off. - A file holds one intent, or a list of them. A YAML file can also hold several documents separated by
---. YAML and JSON mean the same. nameandintentare required.versionis 1 when it is left out.- Names are unique across the catalog, ignoring case. When two files define the same name, the one loaded first keeps it and the other is reported as a problem.
- A field the format does not know is reported as a problem, not ignored, so a misspelt field shows up instead of doing nothing.
This file, from the use cases, uses a schema shape and nested rules:
name: Invoice.Extract
version: 1
owner: accounts-payable
intent: Extract the vendor, invoice number, currency and total from this invoice email.
shape:
kind: schema
schema:
type: object
properties:
vendor: { type: string }
invoiceNumber: { type: string }
currency: { type: string }
total: { type: number }
required: [vendor, invoiceNumber, currency, total]
rules:
properties:
currency:
enum: [USD, EUR, GBP]
total:
minimum: 0
Shapes
shape says what comes back. It decides the type you can ask for with RunAsync<T>; any shape can also be run as
JsonNode with RunAsync.
kind |
Also set | You read it as |
|---|---|---|
text |
nothing | string |
primitive |
primitive: string, int, long, double, decimal, bool, date, datetime or guid; add [] for a list |
the matching .NET type (table below) |
clr |
clrType: the name of a .NET type your application registered |
that type, or a type it can be assigned to |
schema |
schema: a JSON schema for the result |
JsonNode |
Two shorter forms:
- a name instead of an object, as the value of
shape:text,intordate[]; - an object with exactly one of
primitive,clrTypeorschemaand nokind: the kind follows from it.
Without a shape, the result is text.
primitive |
T |
|---|---|
string |
string |
int, long, double, decimal, bool |
the same .NET type |
date |
DateOnly or DateTime |
datetime |
DateTimeOffset or DateTime |
guid |
Guid |
any of those with [] |
an array, List<>, IList<>, IReadOnlyList<>, IEnumerable<>, ICollection<> or IReadOnlyCollection<> of an accepted type |
Nullable forms such as int? are accepted, and so is any type the first type in a row can be assigned to, such as
object. A date asked for as DateTime is midnight, with DateTimeKind.Unspecified; a datetime asked for as
DateTime is the same instant in local time. Asking for a type the shape cannot produce throws
IntentShapeMismatchException before any model call.
A clr shape names only a type your application registered (AddIntentType<T>()); why a file cannot load code is
in Intent files. A schema shape is checked against its whole schema on every reply, limits such as minimum and
pattern included; a reply that breaks it is retried with the problem.
Rules
Rules are checks on the result, run in your process with no model call, on every reply. Each failure is sent back
to the model on the next attempt. Rules see the result as JSON, so write property names as they appear in JSON:
deliverBy, not DeliverBy.
| Rule | Applies to | Passes when |
|---|---|---|
minimum, maximum |
numbers | the number is at least minimum and at most maximum |
minLength, maxLength |
text | the length is within the bounds |
pattern |
text | the regular expression matches; anchor it with ^ and $ to match the whole value |
enum |
text, numbers, true or false | the value is one of those listed: text compared ignoring case, numbers by value |
minItems, maxItems |
lists | the number of elements is within the bounds |
uniqueItems |
lists | no two elements are equal |
notEmpty |
text, lists, objects | the value is not empty |
required |
objects | each listed property is present and not null |
properties |
objects | each named property passes its own rules |
items |
lists | every element passes these rules |
Three things to know:
- A null value, or a missing property, passes every rule except
notEmpty. To demand a property, list it inrequired: aminimumontotalalone accepts a nulltotal. - For a text or primitive shape, a rule that cannot apply (
minLengthon anint) is a load problem that names the rules that do apply. For a list,rulestakes list rules andrules.itemsapplies to the elements. Rules onclrandschemashapes are checked when a reply arrives instead: a rule that meets the wrong kind of value is a failed check that names the rule. - Each failure names its place in the result, starting from
value, for examplevalue.lines[2].sku, so the next attempt is told exactly what to fix.
A check that needs code, such as a vendor that must exist in your database, is a named check registered in your
application and listed in validators; it runs after the rules (Running intents from files).
Examples
Each example is an input and the output you expect for it, shown to the model in the order written.
- A string is used as written. Any other value, a number, a list or an object, is read as compact JSON, so an output can be written as YAML.
- For a text shape, and a
primitiveofstring, the output is the answer as it should read. - For every other shape, write the output as the value itself:
5,[a, b]or{vendor: Acme}. Text that is not JSON is read as a string, so2026-11-15works for adate. - Examples steer the format and the judgement. They never replace the checks: a reply that copies an example and breaks a rule still fails.
- Examples do not count toward the input size limit,
MaxInputChars.
Durations
timeout is the time budget for the whole run, every attempt included. Write it as an ISO 8601 duration, PT30S,
or as hh:mm:ss, 00:00:30. It must be greater than zero and at most about 49.7 days; anything else is a load
problem.
Names a file refers to
Three fields name something that is not in the file: validators (checks your application registered),
shape.clrType (types your application registered) and provider (a provider the client has). They are
checked when the intent runs, not when it loads; what throws before any model call
lists the exception for each.