Skip to main content
The NLU: block holds keyword patterns for intent categories and entity definitions for extraction.
In this release the runtime reads only two parts of the NLU: block: categories (keyword patterns) and entities. The other sub-blocks are parsed and compiled, and they raise no warning, but nothing at run time reads them. They are intents, embeddings, glossary, models, languages, language_models, evaluation, and config_file. Do not rely on them to change routing or extraction. See Runtime status of NLU sub-blocks.

Overview

ABL’s NLU configuration supports these active features:
  • Keyword patterns for intent categories, through categories. They act as a fallback when the classifier is unavailable.
  • Entity extraction with typed extractors (enum, pattern, location, date, number, free text).
  • Synonyms for normalizing variant expressions to canonical values.
The block also accepts the sub-blocks below. They compile, and the runtime does not read them:
  • intents with example utterances.
  • embeddings for semantic similarity.
  • languages, language_models, and models for per-language and per-model settings.
  • glossary for domain terminology.
  • evaluation and config_file.

Runtime status of NLU sub-blocks

To improve how the language model classifies a request, write a precise description in the INTENTS: section. See Intent categories.

Intent classification

The intents sub-block is parsed and compiled, and the runtime does not read it. Its PATTERNS, EXAMPLES, EXAMPLES_FILE, and ENTITIES have no effect on routing. To define routing categories, use the INTENTS: section. To add keyword patterns, use categories.
Intents represent categories of user messages. Each intent has a name, keyword patterns, and optional example utterances.

Syntax

Intent properties

Pattern matching

Keyword patterns that the runtime reads come from categories. They match whole words and phrases, without regard to case. They do not match part of a word and they do not stem words, so “cancel order” does not match “cancel orders”. Add each form you need.

Example-based classification

The runtime does not classify with EXAMPLES. The language model classifier reads the category name and the description from the INTENTS: section. Write contrasting examples inside that description.

Intent with external examples file

For intents with many examples, reference an external file:

Categories

The categories: sub-block declares keyword patterns for intent categories. It is the only source of keywords that the runtime reads.
  • The keywords run only as a fallback. They apply when the classifier is off or unavailable, and the LEXICAL_FALLBACK setting of the INTENTS: section allows it. The default is when_unavailable.
  • A keyword match sets intent.category with a fixed confidence of 0.5. That is below the default short-circuit threshold of 0.85.
  • If the category has no description in INTENTS:, the compiler writes one from the patterns, such as “Examples: invoice, refund”.
  • Write the keys in uppercase, and write PATTERNS as a one-line list. A multi-line list is silently empty. A trailing comment on the line corrupts the list, and a comma inside a quoted pattern splits it.
  • The NAME uses letters, digits, and underscores. A name with a hyphen is dropped.

Entity extraction

Entities are structured values extracted from user messages. ABL supports six entity types.

Syntax

Entity types

Entity properties

Synonyms

Synonyms map variant expressions to canonical values. When a synonym is detected, the runtime normalizes it to the canonical form before storing:
If the user says “100 bucks”, the entity extraction yields currency_code: "USD". Write synonyms as a map of canonical values to inline lists. A block list, a flow map, and a key with a hyphen or a space are silently dropped. Quotes around a synonym in the top-level ENTITIES: section stay in the text, so the synonym never matches. The NLU: entities: form strips quotes. A pattern entity extracts a value. It does not enforce the pattern when the value is stored. To reject a wrong format, add a VALIDATE rule to the GATHER field. A pattern searches the whole message, so do not anchor it with ^ and $.

Embeddings-based matching

The embeddings sub-block is parsed and compiled, and the runtime does not read it. It does not turn on semantic matching. To improve routing, write precise descriptions in the INTENTS: section and tune the pipeline thresholds.
The sub-block has this shape:

Embeddings properties

Multi-language support

The language settings are parsed and compiled, and the runtime does not read them.
The sub-block has this shape:

Multi-language properties

Model configuration

The models sub-block is parsed and compiled, and the runtime does not read it. The classifier model comes from the project runtime configuration.
The sub-block has this shape:

Evaluation configuration

The evaluation sub-block is parsed and compiled, and the runtime does not read it.
The sub-block has this shape:

Glossary

The glossary sub-block is parsed and compiled, and the runtime does not read it. Its entries are not added to the model context. A top-level GLOSSARY: section is a compile error, E105.
The sub-block has this shape:
Each glossary entry is a plain string in "term -- definition" format.

External NLU configuration

For complex NLU setups, reference an external configuration file:
The external file is merged with any inline NLU configuration. Inline values take precedence. The runtime reads only categories and entities from the merged result.

Complete example

This example shows every sub-block. Only categories and entities have a runtime effect. The intents, embeddings, glossary, models, and languages parts are shown for completeness.

Named entities (ENTITIES: section)

Separate from the NLU: block, the top-level ENTITIES: section defines reusable semantic entities that are shared by both NLU (for recognition) and GATHER (via entity_ref). Declaring an entity once lets multiple fields in the same agent file reuse the same type, allowed values, synonyms, and validation. Declare the entity in each agent file that uses it.
The parser reads only the properties in the table. An unknown property, such as ALIASES, is dropped without a message. Lowercase keys are accepted with warning W171. An unknown TYPE gives warning W172. Write SENSITIVE as lowercase true or yes. Top-level entities accept the full unified type set: string, text, free_text, number, integer, float, currency, boolean, date, datetime, email, phone, enum, pattern, location.
This is a distinct section from NLU: entities:. Top-level ENTITIES: defaults TYPE to string and supports all 15 types, whereas the NLU: entities: sub-block defaults to enum and supports only 6 types (enum, pattern, location, date, number, free_text). A GATHER field’s entity_ref points at a top-level ENTITIES: entry.

Intent categories (INTENTS: section)

The top-level INTENTS: section declares supervisor routing categories (distinct from NLU: intents:). Each entry is a category name with an optional description, and the block can set a lexical-fallback mode.
The section takes only a category name, an optional quoted description, and LEXICAL_FALLBACK. It has no examples, keywords, patterns, or priority properties. The classifier reads the name and the description. Write the description on one line and in quotes. An unquoted description, a name with a hyphen, a trailing comment, or a block with EXAMPLES: or KEYWORDS: gives warning W463, and the compiler drops the entry. A duplicate category gives warning W462, and the first entry wins. If every entry is invalid, the section becomes an inferred list of the categories in your WHEN conditions.

Multi-intent handling (MULTI_INTENT:)

The top-level MULTI_INTENT: section configures how the agent handles a single user message that contains more than one intent — for example, “Book me a flight to NYC and also cancel my hotel reservation.” The reasoning pipeline classifier, or the routing model in one turn, detects the requests. The strategy controls how they are dispatched. See Detect multiple intents in one user message for how detection works.

Properties

Write MULTI_INTENT keys in snake_case. A camelCase key, an unknown key, or an empty block is ignored without a message. A repeated key keeps the last value.

Multi-intent strategies

With primary_queue, the runtime stores later items as durable pending work. It revalidates a queued item before replay. If the item has no executable target, the runtime asks for confirmation instead of deriving a destination from its label. Queue expiry stops stale work from resurfacing. Authors cannot read or change the queue from ABL.
The user-facing prompts for the disambiguate and primary_queue flows (the “I noticed more than one request…” text) are customizable via the MESSAGES: block (keys such as multi_intent_disambiguate_header and multi_intent_queued_notice).
A specialist with a missing required GATHER field, a pending input/tool confirmation, an authentication step, an escalation, or a still-waiting child keeps the floor regardless of advance_on_primary_response. A request whose tool/model call errored (and the customer was told) counts as finished, so the plan moves on. For a reply given only in prose (no GATHER) — the ambiguous case — the Runtime judges the reply itself: one that still waits on the customer (an unresolved follow-up question) keeps the floor, a finished-sounding one advances, and one the Runtime can’t judge keeps the floor. Set advance_on_primary_response: false to keep the specialist in control regardless of what it replies.In a sequential plan, the last request’s specialist keeps the customer’s next reply when it answers without finishing (no COMPLETE, no return) — the same as after a single routed request — and may hand that reply back with __return_to_parent__ when the supervisor’s handoff to it declared RETURN: true.

Related articles: