Documentation
Table of Contents

For agents and other programs

An IntentSharp operation keeps its goal, its shape, its rules and its budget in files, and a program can read all of it: the files, the catalog in code, the tools an agent calls, the report of every edit and these docs. This page is for a developer who connects a coding agent, a dashboard or another program to an application built on IntentSharp.

The file formats

Intent files and rule files are YAML or JSON with a fixed set of fields, so a program reads and writes them as data. This intent file holds one operation, with a comment on each field:

# One operation in one file: what it is for, what it returns, what is checked and what it may spend.
name: Orders.ClassifyUrgency    # what code and tools call it; unique in the catalog
version: 1                      # raise it with every change
owner: order-desk               # who answers for it
description: >-                 # for people and listings, and the description of its tool
  Scores how urgent an order email is, from 1 (routine) to 5 (drop everything).
intent: >-                      # the instruction the model receives
  Rate the urgency of this order email from 1 (routine) to 5 (critical).
  A stopped production line is at least 4.
shape: int                      # what comes back: a value, a list, a type of yours or a JSON schema
rules:                          # checked in your process on every reply
  minimum: 1
  maximum: 5
examples:                       # sent with the request, in this order
  - input: "Line 3 is down until the bearings arrive. Ship today."
    output: 5
attempts: 2                     # the budget: attempts,
timeout: PT30S                  # the time for the whole call,
maxOutputTokens: 64             # and the tokens of each reply
tags:                           # kept with each run, and read as tool.tags
  team: orders
  • description is written for people and listings. It is not part of the instruction the model receives with the intent's calls; it does describe the intent's tool to an agent.
  • A field the format does not know is reported as a problem, not ignored, so a misspelled field shows at load.
  • Intent file reference has every field, shape and rule.

A rule file holds one rule set, read at one checkpoint. This one decides which intents an agent is offered as tools:

# Which intents an agent is offered as tools. Checked at the Tool checkpoint, with no model call.
intentsharp: rules/1
set: agent-tools                # the name a client or a call gives to use it
label: order desk tools         # your label for this version; the store numbers the versions
checkpoint: tool
rules:
  - id: orders-only
    subject: tool.intent        # the intent's name
    pattern: '^Orders\.'        # only the order desk's intents
    message: Only the order desk's intents are tools here.   # what a refused caller is told
  • label is your name for this version of the set; the store numbers the versions.
  • A rule's message is what a refused caller is told, an agent's model included, so keep secrets out of it.
  • Guardrails has the rule kinds, the checkpoints and their subjects.

Reading definitions from code

// The catalog as it is now: replaced whole on every load, never changed in place.
IntentCatalogSnapshot snapshot = runtime.Catalog.Current;
Console.WriteLine($"Generation {snapshot.Generation}, loaded {snapshot.LoadedAt:u}");
foreach (IntentDefinition definition in snapshot.Definitions.Values.OrderBy(d => d.Name))
    Console.WriteLine($"{definition.Name} v{definition.Version}, {definition.Owner}: {definition.Description}");
foreach (CatalogProblem problem in snapshot.Problems)
    Console.WriteLine(problem);   // file:line: message

// One definition by name, as a copy that is yours to change.
IntentDefinition urgency = runtime.Describe("Orders.ClassifyUrgency");
Console.WriteLine($"{urgency.Shape.Kind}, {urgency.Attempts} attempts within {urgency.Timeout}");
  • IIntentCatalog.Current is a snapshot: every definition by name, the problems of the latest load, when it loaded, and a Generation that increases with every load, with or without problems. A higher generation does not mean an edit took: check Problems, each of which prints as file:line: message.
  • A snapshot is replaced whole, never changed in place, so treat its definitions as read-only. IntentRuntime.Describe(name) returns a copy you may change; an unknown name throws IntentNotFoundException.
  • GetChangeToken() fires once when the snapshot is replaced (Running intents from files).

Intents as tools

// builder: your providers. The store holds the intent files, the rule file and its manifest.
var client = builder
    .WithDocumentStore(store)
    .WithGuardrailFiles(store, "agent-tools")   // the client's sets, read at every checkpoint
    .Build();
var intents = new IntentRuntime(client, new DocumentIntentCatalog(store, "intents/"));

// One tool per enabled intent that the Tool checkpoint allows; the others are not offered.
IReadOnlyList<AIFunction> tools = intents.AsAIFunctions();
foreach (AIFunction tool in tools)
    Console.WriteLine($"{tool.Name}: {tool.Description}");
  • AsAIFunctions() gives an agent one Microsoft.Extensions.AI tool per enabled intent, named after it and described from its description, its intent and its shape. A tool takes one argument, input, runs the intent with its shape, rules and limits, and answers JSON with success and the value or the error.
  • With rule sets on the client, the Tool checkpoint decides which intents are listed: under the rule file above, an intent outside Orders. is not. A tool created for it by name answers success: false with the rule's message and makes no model call.
  • Each tool call reads the intent's current definition. The list is fixed when you build it: build it again after a reload that adds an intent or changes a description (Microsoft.Extensions.AI).

What an edit reports

EditOutcome outcome = await client.Edits.SubmitAsync(edit);
EditImpact impact = outcome.Impact;   // the validators' assessment, whatever the writer did

Console.WriteLine($"{outcome.Status}; loads cleanly: {impact.LoadsCleanly}");
foreach (SettingChange change in impact.Changes)
    Console.WriteLine($"{change.Name}: {change.Before?.ToJsonString() ?? "none"} to {change.After?.ToJsonString() ?? "none"}");
foreach (DocumentProblem problem in impact.Problems)
    Console.WriteLine(problem);
if (impact.WidensSecurity)
    Console.WriteLine("Widens: " + string.Join(", ", impact.WidenedSubjects));
  • Every outcome carries the validators' EditImpact, whether the edit applied or not: whether the text loads cleanly, its Problems with their lines, each of its Changes by name with the value before and after, and WidensSecurity with WidenedSubjects.
  • An intent file's changes are named intent.<name>, with the version before and after; a changed definition whose version did not rise is listed among the problems. Intent files hold no security item, so editing one never widens.
  • In a rule file, the settings file or the provider file, an edit that allows more is applied by default and flagged; a writer of your own can hold it for a person (Documents and edits).

The docs, for tools

Two plain-text files at the site's root are written for agents and answer engines:

  • /llms.txt, in the llms.txt format: a one-sentence summary and two short paragraphs, then one link per page with its description, in sections (Start here, Concepts, Solutions, Blog, Guides, Licensing, Trust and Reference), and the pages an agent may skip under Optional. The API reference is linked, not included.
  • /llms-full.txt: the same header, then every page under its title and address. The home page, the overview, the quick start, installation, system requirements, the concept pages, the Solutions pages and the case study, the blog, licensing, the trust pages, the roadmap and the changelog are there in full; every other page, each guide among them, is its description.