Implement enrichment by using custom or built-in skills for text, images, and layout
AI-103 › Unit 5: Implement information extraction solutions › Build retrieval and grounding pipelines › Implement enrichment by using custom or built-in skills for text, images, and layout
Implement enrichment by using custom or built-in skills for text, images, and layout
A skillset is "a reusable object in Azure AI Search that's attached to an indexer", containing skills that "call built-in AI or external custom processing over raw content". The mechanics are unusual enough to be examinable in their own right: skills read and write an in-memory enrichment tree, addressed by path, whose nodes are immutable, and only what you explicitly map ever reaches the index.
Why This Matters
Skills communicate through a tree, not through variables. Each skill's context, inputs, and outputs are node paths, and getting the path wrong changes how many times a skill runs.
Context controls invocation count. Adding /* means the skill fires once per item in a collection rather than once per document.
Nothing reaches the index by default. "Not all nodes in the enrichment tree need to make it to the index", and outputFieldMappings decide what does.
Prerequisites
- That skillsets attach to indexers and run at indexing time.
- Document cracking and the
/documentroot. - The Split skill's grains from the retrieval objective.
- What a knowledge store is, at a high level.
Learning Objectives
By the end of this lesson you will be able to:
- Describe the enrichment tree and how skills read and write it.
- Set a skill's context to control invocation and output placement.
- Chain skills through inputs and outputs, using
targetName. - Choose between built-in and custom skills.
- Project results with
outputFieldMappingsor a knowledge store.
Building Blocks
What a skillset is. "A reusable object in Azure AI Search that's attached to an indexer. It contains one or more skills that call built-in AI or external custom processing over raw content retrieved from an external data source." It "produces enriched documents that are either consumed during indexing or projected to a knowledge store".
The enrichment tree. "A temporary, tree-like data structure created during skillset execution that collects all of the changes introduced through skills." Enrichments are "represented as a hierarchy of addressable nodes", including "any unenriched fields that are passed in verbatim". It "exists for the duration of skillset execution, but can be cached or sent to a knowledge store".
Immutability. "Enrichments are immutable: once created, nodes can't be edited."
The three skill properties.
| Property | Meaning |
|---|---|
| Context | "The scope of the operation, which could be once per document or once for each item in a collection" |
| Inputs | "Originate from nodes in an enriched document, where a source and name identify a given node" |
| Outputs | "Sent back to the enriched document as a new node"; use targetName for disambiguation or renaming |
What context determines. "The number of times the skill executes"; "output declaration, or where in the enrichment tree the skill outputs are added — outputs are always added to the tree as children of the context node"; and "the shape of the inputs".
Dependencies. "Skills can execute independently and in parallel, or sequentially in a dependent relationship if you feed the output of one skill into another skill."
Notable skills. The Split skill — grains of pages (~5,000 characters) and sentences, "typically first in a skillset". The Shaper skill — "creates data shapes out of nodes in an enrichment tree", added "as a last step" if output includes a knowledge store; it "doesn't add or detract from an enrichment tree", being "similar to creating views out of tables in a database". Merge and Shaper "create new nodes but only use data from existing nodes and don't create net new enrichments".
Debugging. "The best approach for examining the structure and content of an enrichment tree is through a debug session in the Azure portal."
Built-in against custom skills
| Attribute | ||
|---|---|---|
| Provided by | Microsoft | You, hosted externally |
| Covers | OCR, split, language detection, sentiment, key phrases, translation, entity recognition, shaper, merge | Processing logic you host |
| Integration | Declare it in the skillset | An external endpoint the skillset calls |
| Fits | Standard enrichment | Proprietary logic, internal lookups, bespoke models |
| Operational burden | None | Availability, scaling, and latency are yours |
Deep Dive
The tree, and why paths matter
Skills do not pass values to one another. They read from and write to a shared in-memory tree, and everything is addressed by path.
The tree starts as the output of document cracking — for a blob in default mode, /document/content and /document/normalized_images/*; for CSV or JSON, the columns or keys as nodes under /document. "With each skill execution, the enriched document gains structure and substance as each skill writes its output as nodes in the graph."
Three consequences follow.
Chaining is by path. To use a skill's output downstream you name its node — so a Split skill producing pages under /document/reviews_text is referenced as /document/reviews_text/pages/*. If the path is wrong, the downstream skill receives nothing, and the failure is silent rather than an error.
Outputs land under the context node. "Outputs are always added to the tree as children of the context node", so context determines where results appear as well as how often the skill runs.
Nodes are immutable. "Once created, nodes can't be edited." A skill cannot modify an earlier skill's output — it produces a new node. That is why merge and shaper skills exist as separate steps, and it is why an enrichment pipeline grows rather than mutates.
Building a skillset
Know your starting tree
Document cracking gives
/document/contentand/document/normalized_images/*for blobs; keys or columns for JSON and CSV.
Context: the property that decides everything
Context is the most consequential and least intuitive setting, because it controls three things at once.
How many times the skill runs. A context of /document invokes the skill once per document. A context ending in /* — such as /document/reviews_text/pages/* — invokes it once for each item in the collection. So splitting a review into ten pages and setting a sentiment skill's context to the pages collection produces ten sentiment analyses, one per page, rather than one over the whole review.
Where outputs go. Results are attached as children of the context node, so the same skill with a different context produces results in a different place — and downstream paths change accordingly.
The shape of inputs. The documentation gives the case precisely: with countries containing states containing ZIP codes, a context of /document/countries/* yields "a list of all ZIP codes in the country/region" invoked "once per country/region", while /document/countries/*/states/* yields "a list of ZIP codes in the state" invoked "once per combination of country/region and state". Same input path, different context, different shape and count.
That is the mechanism behind a classic symptom: a skill that runs far more often than expected, or produces one aggregated result where per-item results were wanted. The fix is the context, not the input.
Built-in and custom skills
Built-in skills are "the built-in skills from Microsoft" and cover the standard enrichment surface — OCR over images, text splitting, language detection, sentiment, key phrase extraction, translation, entity recognition, plus utility skills like Shaper and Merge. They are declared in the skillset and need no hosting.
Custom skills exist "for processing logic that you host externally". They are the answer when enrichment requires something the built-in set does not provide: a proprietary classifier, a lookup against an internal system, a domain-specific parser, a bespoke model.
The trade is operational. A custom skill is an external endpoint the indexer calls during indexing, so its availability, throughput, and latency become part of your indexing pipeline's reliability. A slow custom skill slows every indexer run; an unavailable one fails it.
Two design notes. The Azure Content Understanding skill is called out as an alternative to the Split skill for chunking, which is worth knowing as a built-in route to a richer representation. And skills "can execute independently and in parallel, or sequentially in a dependent relationship" — dependency comes from one skill consuming another's node, not from declaration order, which is why the documentation's example notes a skill "defined [third] in the skillset" being "the next skill to execute".
Persisting beyond the index
The enrichment tree is temporary — it "exists for the duration of skillset execution" — so anything you want afterwards must be sent somewhere.
The index receives what outputFieldMappings name.
A knowledge store receives projections, and this is where the Shaper skill belongs: added "as a last step", it "creates data shapes out of nodes in an enrichment tree", consolidating "multiple nodes into a single shape" that you "project as a table (nodes become the columns in a table)". Conceptually it is "similar to creating views out of tables in a database", and it "doesn't add or detract from an enrichment tree" — it rearticulates what is already there.
A cache can hold the enriched document, which matters because re-running expensive enrichment over unchanged content is wasteful.
And for inspection, debug sessions in the portal are the documented way to see the tree — worth reaching for early, since path errors are silent and a visual tree makes them obvious.
Worked Examples
Example 1 — sentiment over a whole document instead of per chunk. A Split skill produces pages, but the sentiment skill returns one result per document rather than one per page.
The sentiment skill's context is /document rather than the pages collection. Set it to /document/reviews_text/pages/* so the skill is "invoked once for each of the items in the pages collection", with outputs attached "under the associated page element". The input path alone does not control invocation count — context does.
Example 2 — enrichment with nothing to show for it. A skillset runs without error and the new fields are absent from the index.
Missing outputFieldMappings. The skillset produced nodes in a temporary tree; only mapped nodes are ingested, and "not all nodes in the enrichment tree need to make it to the index". Note the distinction: fieldMappings carry raw source fields, while outputFieldMappings carry enrichment nodes.
Example 3 — a proprietary classifier in the pipeline. Documents must be tagged by an internal model that no built-in skill provides.
A custom skill — "processing logic that you host externally" — called by the indexer during enrichment. Accept the operational consequence: its availability, throughput, and latency become part of every indexer run. Where a built-in skill would do, prefer it; the Azure Content Understanding skill is the documented built-in alternative for richer chunking.
Visual Explanations
How the tree grows:
What context controls:
Common Mistakes
Setting the input path but not the context. Context decides invocation count.
Expecting a skill to modify an earlier output. Nodes are immutable.
Omitting outputFieldMappings. The enrichment evaporates silently.
Confusing fieldMappings with outputFieldMappings. Source fields against enrichment nodes.
Assuming declaration order is execution order. Dependency comes from consuming a node.
Referencing a node by the wrong path. Silent, not an error.
Adding a Shaper skill without a knowledge store. It exists for projections.
Ignoring a custom skill's operational cost. It runs inside every indexer execution.
Debugging by inspection instead of a debug session.
Practice Exercises
- What three things does a skill's context determine?
- Distinguish
fieldMappingsfromoutputFieldMappings. - Why can a skill not edit an earlier skill's output, and what follows?
- When is a custom skill warranted, and what does it cost operationally?
- What is the Shaper skill for, and when is it added?
▶Answers
- The number of times the skill executes — once per document, or once per item where the path ends in
/*. Where outputs are added — "always… as children of the context node". The shape of the inputs — the same input path yields an aggregated list or per-item values depending on context. fieldMappingsmap a source field in the data source to a search field, passing raw content through intact.outputFieldMappingsmap a node in the enriched document — in-memory enrichment output — to a search field.- Because "enrichments are immutable: once created, nodes can't be edited". It follows that skills produce new nodes rather than mutating, the tree only grows, and combining values requires dedicated skills such as Merge and Shaper, which "only use data from existing nodes and don't create net new enrichments".
- When enrichment needs "processing logic that you host externally" — a proprietary classifier, an internal lookup, a bespoke model — that no built-in skill provides. It costs operationally because the endpoint is called during indexing, so its availability, throughput, and latency become part of every indexer run.
- It "creates data shapes out of nodes in an enrichment tree", consolidating multiple nodes into one shape projected "as a table (nodes become the columns)". Add it as a last step when output includes a knowledge store; it "doesn't add or detract from an enrichment tree".
Summary & Concept Map
A skillset is a reusable object attached to an indexer whose skills read and write an in-memory enrichment tree rooted at /document, seeded by document cracking. Each skill has a context, inputs, and outputs, and context is the decisive property — it sets how many times the skill runs (once per document, or once per item where the path ends in /*), where outputs land (as children of the context node), and the shape of the inputs. Nodes are immutable, so skills add rather than modify, and chaining happens by path with targetName for renaming. Built-in skills cover standard enrichment; custom skills host your own logic and put their availability and latency inside every indexer run. Finally, nothing persists by default: outputFieldMappings select what reaches the index, a Shaper skill prepares projections for a knowledge store, and debug sessions are the documented way to inspect the tree.
Sources and freshness
Written against current Microsoft Learn documentation for the AI-103 skills measured (16 April 2026), reviewed 2026-08-20. Microsoft Learn controls every changing product contract — availability, preview status, quotas, limits, regional support, naming, and retirement dates all move independently of this lesson. Where a scenario turns on a specific number or a GA/preview boundary, confirm it against the product's own page before relying on it.