Back to Blog
Automation23 min read

Advanced YANG Data Modeling for Cisco NSO | NHPREP

A
Admin
March 26, 2026
YANG modelingCisco NSOnetwork automationdata modelsservice development

Advanced YANG Data Modeling for Cisco NSO

Introduction

Imagine you are building a network service package in Cisco NSO and need to ensure that operators can only select PE routers from the device list, that VLAN encapsulation tags default intelligently based on related interface values, and that the CLI experience feels as intuitive as native IOS. All of this is possible through advanced YANG modeling techniques that go far beyond basic leaf and container definitions. YANG is the backbone of how Cisco NSO understands, validates, and renders network configuration, and mastering its advanced features is the difference between a fragile service package and a production-grade automation solution.

In this comprehensive guide, we will explore the full range of advanced YANG data modeling capabilities available in Cisco NSO. From XPath path expressions and constraint statements to tailf extensions that shape the CLI experience, every technique covered here is essential for engineers building robust NSO service packages. Whether you are preparing for a DevNet certification or designing real-world automation workflows, this article will give you the deep technical coverage you need.

We will cover path navigation and XPath functions, leaf types including leafref and its variants, container design patterns, list customization, CLI rendering extensions, and practical use cases that tie everything together. Let us begin.

How Does YANG Fit Into Cisco NSO Architecture?

YANG is not just a schema language in Cisco NSO — it is the foundational layer that defines how every piece of data is structured, validated, and exposed across all northbound interfaces. In NSO, YANG models serve two critical purposes: they define the device models that NSO uses to communicate with managed devices, and they define the service models that operators interact with to provision network services.

Every device managed by NSO has its YANG model loaded into the system. When you configure a device through NSO, you are actually writing data into the Configuration Database (CDB) according to that device's YANG schema. Similarly, when you build a service package, you write a YANG model that defines the inputs your service accepts, and NSO uses that model to validate operator input, render the CLI, and generate the Web UI.

Accessing the YANG Path in NSO

One of the first questions engineers ask when working with NSO is: how do I find the YANG path for a specific resource in the CDB? The answer is the display xpath pipe command. For example, to see the XPath for an interface configuration:

admin@ncs# show running-config devices device IOS0 | display xpath
/devices/device[name='IOS0']/config/ios:interface/GigabitEthernet[name='0/0']/ip/address/primary/address 1.1.1.1
/devices/device[name='IOS0']/config/ios:interface/GigabitEthernet[name='0/0']/ip/address/primary/mask 255.255.255.0

This output shows you the full XPath expression for each configuration element, which you can then use in your YANG models for leafref paths, when conditions, and must constraints. Understanding this path structure is essential for writing accurate cross-references between your service model and the device models loaded in NSO.

What Are XPath Path Expressions in YANG Modeling?

XPath is the expression language used throughout YANG for navigating the data tree, defining constraints, and referencing remote nodes. In NSO's YANG models, several key XPath functions and expressions are used extensively.

The path() Expression

XPath uses path expressions to select nodes in the data tree. A path expression can return a single node or a collection of nodes. This is the fundamental mechanism used by leafref to point to values elsewhere in the model:

list interface {
    key "name";
    leaf name {
        type string;
    }
}

leaf mgmt-interface {
    type leafref {
        path "../interface/name";
    }
}

In this example, the mgmt-interface leaf uses a relative path expression to reference the name leaf inside the interface list. The .. notation moves up one level in the tree, just as it would in a filesystem path.

The current() Function

The current() function returns the current node as the starting point for an XPath location path. This is critical when you need to reference sibling nodes from within a type definition or constraint:

leaf phase {
    type enumeration {
        enum Telnet;
        enum SSH;
    }
}

leaf mgmtVLAN {
    when "current()/../phase = 'SSH'";
    type string;
}

Here, current() refers to the mgmtVLAN leaf itself. The expression current()/../phase navigates up to the parent and then to the phase sibling leaf. The mgmtVLAN leaf only appears when the phase is set to SSH.

Pro Tip: The current() function is indispensable when writing when, must, and leafref path expressions. Always remember that current() refers to the node being defined, not the root of the tree.

How Do when and must Constraints Work in YANG Modeling?

Constraints are one of the most powerful features of YANG modeling for building intelligent, self-validating service packages. NSO uses two primary constraint mechanisms: when and must.

The when Statement

The when statement allows you to conditionally expose a node based on the value of another node in the data tree. If the when expression evaluates to false, the node is completely hidden from the CLI and all northbound interfaces:

leaf device {
    type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
    }
}

container ios {
    when "/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:platform/ncs:name = 'ios'";
    leaf device-description {
        tailf:info "device description";
        type string;
    }
}

In this use case, the ios container only appears when the selected device's platform name equals ios. This is an incredibly useful pattern for building multi-vendor service packages where different containers expose vendor-specific parameters based on the device type.

The must Statement

While when controls visibility, must controls validation. The must statement defines an XPath expression that must evaluate to true for the configuration to be accepted. If it evaluates to false, NSO rejects the commit with a custom error message:

leaf device {
    tailf:info "PE Router";
    type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
    }
    must "starts-with(current(), 'PE')" {
        error-message "Only PE devices can be selected.";
    }
}

In this example, the must constraint ensures that only devices whose names start with "PE" can be selected. If an operator tries to select a device named "CE1", they receive the error message "Only PE devices can be selected." This is a powerful mechanism for enforcing naming conventions and business rules directly in the YANG model.

Pro Tip: Use must statements with clear, descriptive error-message strings. Operators troubleshooting failed commits will see these messages, so make them actionable.

What XPath Functions Are Available for YANG Modeling in NSO?

NSO provides a rich library of XPath functions that can be used in when, must, and leafref expressions. Understanding these functions is essential for writing sophisticated constraints and references.

String Functions

The contains() function evaluates whether a referenced leaf value contains a given substring:

leaf port {
    type string;
}

container encapsulation {
    when "contains(current()/../port, '.')" {
        tailf:dependency "../port";
    }
}

This pattern exposes the encapsulation container only when the port name contains a dot character, which typically indicates a subinterface.

The starts-with() function checks whether a value begins with a specific string:

leaf type {
    type enumeration {
        enum test;
        enum isp;
        enum mobile_4G;
        enum mobile_5G;
    }
}

container classifier {
    when "starts-with(current()/../type, 'mobile')";
    presence true;
    leaf name {
        type string;
    }
}

Here, the classifier container only appears when the type leaf starts with "mobile", making it visible for mobile_4G and mobile_5G but hidden for test and isp.

The deref() Function

The deref() function follows the reference defined by a leafref and returns the node it points to. This simplifies complex path expressions by eliminating the need to manually reconstruct the full path through list keys:

leaf my-ip {
    type leafref {
        path "/server/ip";
    }
}

leaf my-port {
    type leafref {
        path "deref(../my-ip)/../port";
    }
}

Without deref(), the equivalent expression would require explicitly specifying the list key predicate:

leaf my-port {
    type leafref {
        path "/server[ip=current()/../my-ip]/port";
    }
}

Both produce the same result, but deref() is cleaner and easier to maintain, especially in deeply nested models.

Evaluating XPath Expressions Interactively in NSO

NSO provides a built-in XPath evaluator that allows you to test expressions directly from the CLI. First, enable developer tools:

admin@ncs# devtools true

Then use the xpath eval command to test expressions:

admin@ncs# config
admin@ncs(config)# xpath eval "/devices/device[contains(name, 'a') or contains(name, 'i')]"
/devices/device[name='ios0']

This is invaluable for debugging complex XPath expressions before embedding them in your YANG models.

String Manipulation Examples

NSO's XPath evaluator supports a wide range of string operations:

admin@ncs(config)# xpath eval translate('test_xyz', '_', '-')
test-xyz

admin@ncs(config)# xpath eval normalize-space('  test')
test

admin@ncs(config)# xpath eval compare('abc', 'abc')
0

admin@ncs(config)# xpath eval string-length('test')
4

Regular expression matching is also supported:

admin@ncs(config)# xpath eval re-match('1.22.333', '\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}')
true

Substring operations provide flexible text extraction:

admin@ncs(config)# xpath eval substring('test_xyz', 2, 2)
es

admin@ncs(config)# xpath eval concat('area', '-SW')
area-SW

admin@ncs(config)# xpath eval substring-before('aa-bb', '-')
aa

admin@ncs(config)# xpath eval substring-after('aa-bb', '-')
bb

Node-Set Functions

Node-set functions operate on collections of nodes and are essential for working with lists:

admin@ncs(config)# xpath eval "devices/device[last()]"
/devices/device[name='JUN0']

admin@ncs(config)# xpath eval count(devices/device)
3

admin@ncs(config)# xpath eval devices/device[position()=2]
/devices/device[name='IOSXR0']

admin@ncs(config)# xpath eval name(devices/device)
ncs:device

These functions let you select the last element in a list, count elements, select by position, and retrieve node names programmatically.

Numeric and Boolean Functions

Numeric functions handle mathematical operations:

admin@ncs(config)# xpath eval ceiling(4.69)
5

admin@ncs(config)# xpath eval floor(4.69)
4

admin@ncs(config)# xpath eval "10 div 5"
2

admin@ncs(config)# xpath eval 2*2
4

Boolean functions evaluate truth values:

admin@ncs(config)# xpath eval not(0)
true

admin@ncs(config)# xpath eval boolean(0)
false

admin@ncs(config)# xpath eval true()
true

admin@ncs(config)# xpath eval false()
false

The Complete XPath Function Library

Beyond the functions demonstrated above, NSO supports a comprehensive set of XPath functions that can be used in YANG models. These include last, position, count, id, local-name, namespace-uri, name, string, concat, starts-with, contains, substring-before, substring-after, substring, string-compare, compare, current, deref, sort-by, enum-value, bit-is-set, min, max, avg, band, bor, bxor, bnot, string-length, normalize-space, translate, boolean, nodeset-as-boolean, false, true, not, number, sum, floor, ceiling, round, and re-match.

This extensive library means that almost any validation logic or dynamic behavior you need can be expressed directly in the YANG model itself, without resorting to custom Java or Python code.

How Does leafref Validation Work in YANG Modeling?

The leafref type is one of the most frequently used features in NSO YANG models. It creates a reference to a leaf that exists elsewhere in the data tree and enforces data validation — the value entered must exist at the referenced path.

Standard leafref with Validation

leaf vrf-name {
    type leafref {
        path "/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:config/iosxr:vrf/iosxr:vrf-list/iosxr:name";
    }
}

When an operator uses this leaf in the CLI, NSO provides tab completion with the valid values and rejects any value that does not exist:

admin@ncs(config)# SERVICE vrf-name ?
Possible completions:
  VRF1
  VRF2

admin@ncs(config)# SERVICE vrf-name VRF3 ?
Possible completions:
  Error: "VRF3" is an invalid value.

This strict validation is essential for production environments where selecting a nonexistent VRF could cause service deployment failures.

tailf:non-strict-leafref Without Validation

Sometimes you need the convenience of tab completion without the strict validation — for example, when configuring a service before the target VRF has been created on the device. The tailf:non-strict-leafref extension provides exactly this:

leaf vrf-name {
    tailf:non-strict-leafref {
        path "/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:config/iosxr:vrf/iosxr:vrf-list/iosxr:name";
    }
    type string;
}

With this extension, YANG will accept values that do not exist under the referenced leaf. The CLI still provides auto-completion hints from existing values, but it does not block values that are not yet present in the CDB:

admin@ncs(config)# SERVICE vrf-name VRF3 ?

This is accepted without error, even though VRF3 does not currently exist on the device.

Featureleafreftailf:non-strict-leafref
Tab completionYesYes
Strict validationYes — rejects invalid valuesNo — accepts any string
Use caseProduction enforcementPre-provisioning scenarios
Type constraintInherits from referenced leafExplicit type (e.g., string)

Pro Tip: Use standard leafref in production service models where data integrity is critical. Reserve tailf:non-strict-leafref for scenarios where services must be configured before all dependencies exist in the CDB.

What Are the Key tailf Extensions for YANG Modeling?

Cisco NSO extends standard YANG with a rich set of tailf extensions that control how data is rendered, stored, and interacted with through the CLI and Web UI. These extensions are essential for creating a polished operator experience.

tailf:default-ref — Dynamic Default Values

The tailf:default-ref extension sets a leaf to the value of another leaf unless it is explicitly overridden by the operator:

leaf BVI {
    type uint16 {
        range 1..4094;
    }
}

container encapsulation {
    choice encapsulation-choice {
        container dot1q {
            presence true;
            leaf tag {
                type uint16 {
                    range 1..4094;
                }
                tailf:default-ref "../../../BVI";
            }
        }
    }
}

In this example, if the operator sets the BVI leaf to 100 but does not explicitly configure the tag leaf, the tag automatically inherits the value 100 from BVI. If the operator later sets tag to 200, the explicit value takes precedence. This reduces redundant input and ensures consistency between related parameters.

tailf:cli-show-with-default — Displaying Default Values

By default, NSO does not display leaves that are set to their default value in the running configuration. The tailf:cli-show-with-default extension overrides this behavior:

leaf mtu-size {
    tailf:cli-show-with-default;
    type uint16;
    default 1500;
}

With this extension, the configuration output always shows the MTU value, even when it is the default:

admin@ncs# show run SERVICE
SERVICE interface GigabitEthernet 0/0
 mtu-size 1500
!

Without the extension, the mtu-size line would be omitted from the output when set to 1500. This is particularly useful for parameters where operators need explicit confirmation of the current value, regardless of whether it was manually set or inherited as a default.

tailf:hidden — Internal Storage Nodes

The tailf:hidden extension hides a node from all northbound interfaces, including the CLI and Web UI:

leaf calculated-lsps {
    tailf:hidden true;
    type string;
}

This creates a leaf that exists in the CDB and can be read and written by service code, but is invisible to operators. This is extremely useful for storing intermediate calculation results, internal state, or derived values that your service logic needs but operators should not directly manipulate. Think of it as internal storage within the YANG model.

tailf:cli-expose-key-name — Showing List Keys

By default, when entering a list element in the NSO CLI, the key name does not appear — operators simply type the key value. The tailf:cli-expose-key-name extension changes this behavior:

list SERVICE {
    key "device";
    leaf device {
        tailf:cli-expose-key-name;
        type string;
    }
}

The difference in CLI behavior is significant:

admin@ncs(config)# SERVICE device IOS1

Without the extension, the syntax would be:

admin@ncs(config)# SERVICE IOS1

Exposing the key name makes the CLI more readable and self-documenting, which is especially valuable when training new operators or working with service models that have multiple key fields.

How Do Containers and Lists Shape YANG Modeling for NSO Services?

Containers and lists are the structural building blocks of YANG models. Advanced use of these elements with tailf extensions dramatically improves the operator experience.

The presence Statement for Optional Containers

The presence statement makes a container optional. Without presence, a container exists implicitly whenever any of its children have values. With presence true, the container must be explicitly created by the operator:

container routing-protocol {
    container bgp {
        presence true;
        // MANDATORY LEAF elements
    }
    container ospf {
        presence true;
        // MANDATORY LEAF elements
    }
}

In this routing protocol example, neither bgp nor ospf containers exist until the operator explicitly enters them. If anything is configured under a container, it evaluates to true; if nothing is configured, the container is absent (false). This pattern is ideal for modeling optional features where the presence of the container itself carries semantic meaning.

tailf:cli-flatten-container — Streamlined Input

The tailf:cli-flatten-container extension allows the CLI to exit the container and continue accepting input from the parent container after all leaf elements in the current container have been set:

container customer {
    tailf:cli-flatten-container;
    leaf name {
        type string;
    }
    leaf address {
        type string;
    }
}

container interface {
    leaf int-type {
        type string;
    }
    leaf int-id {
        type string;
    }
}

With the flattened container, operators can enter all values in a single line:

admin@ncs(config)# SERVICE customer name CLIENT address KRK interface int-type GE int-id 0/1

Without the extension, operators would need to enter the customer container, configure its leaves, exit, and then enter the interface container separately. This dramatically speeds up data entry for service provisioning workflows.

tailf:cli-add-mode — Container as a CLI Mode

The tailf:cli-add-mode extension creates a dedicated CLI mode for a container, similar to how IOS creates configuration modes for interfaces or routing protocols:

container vrf-config {
    tailf:cli-add-mode;
    leaf vrf-name {
        type string;
    }
    leaf local-as-number {
        tailf:info "BGP AS";
        type enumeration {
            enum 12345;
            enum 23456;
        }
    }
}

With this extension, entering the container creates a new CLI mode with its own prompt:

admin@ncs(config)# SERVICE IOS0 vrf-config
admin@ncs(config-vrf-config)# ?
Possible completions:
  local-as-number
  vrf-name

Without the extension, operators would need to specify all parameters on a single line. The mode-based approach is more intuitive for complex containers with many leaves, as it provides tab completion and help text within the container's context.

How Do min-elements, max-elements, and List Syntax Extensions Enhance YANG Modeling?

When working with lists and leaf-lists in YANG, controlling the number of elements and the input syntax is essential for creating usable and correct service models.

min-elements and max-elements

These constraints specify the minimum and maximum number of elements that must occur in a list or leaf-list:

list FastEthernet {
    tailf:info "FastEthernet port";
    key port;
    max-elements 1;
    min-elements 1;
    leaf port {
        type string;
    }
}

In this example, exactly one FastEthernet port must be configured — no more, no less. NSO will reject a commit if the operator tries to add a second entry or if they remove the only entry. This is particularly useful for modeling physical constraints where a specific number of interfaces or resources must be provisioned.

ConstraintEffectValidation Timing
min-elementsRequires at least N entriesCommit validation
max-elementsAllows at most N entriesInput validation
Both equalRequires exactly N entriesBoth

tailf:cli-flat-list-syntax — Bracket-Free Input

By default, leaf-list values in NSO must be entered using bracket notation. The tailf:cli-flat-list-syntax extension removes this requirement:

leaf-list vrf-name {
    tailf:cli-flat-list-syntax;
    type string;
}

With the flat syntax, operators can enter values naturally:

admin@ncs(config)# SERVICE vrf-name VRF1 VRF2

Without the extension, brackets are required:

admin@ncs(config)# SERVICE vrf-name [VRF1 VRF2]

This seemingly small change significantly improves usability, especially for operators accustomed to native IOS/IOS-XR CLI syntax where bracket notation is uncommon.

tailf:cli-compact-syntax — Single-Line Configuration Display

The tailf:cli-compact-syntax extension controls how configuration is displayed in the show running-config output. When applied to a container, all leaf elements within that container are shown on a single line:

container vrf-config {
    tailf:cli-compact-syntax;
    leaf vrf {
        type string;
    }
    leaf local-as-number {
        tailf:info "AS Number";
        type enumeration {
            enum 12345;
            enum 23456;
        }
    }
}

With compact syntax:

admin@ncs# show running-config SERVICE
SERVICE service
 vrf-config vrf vrf1 local-as-number 12345
!

Without compact syntax, each leaf appears on its own line:

admin@ncs# show running-config SERVICE
SERVICE service
 vrf-config
  vrf vrf1
  vrf-config local-as-number 12345
 !

The compact representation is cleaner and more readable, especially for containers with only a few leaves. It also makes configuration diffs easier to review.

Practical Use Cases for Advanced YANG Modeling in NSO

Understanding individual YANG features is important, but the real power emerges when you combine them into cohesive service models. Here are several practical patterns that demonstrate how these techniques work together.

Multi-Vendor Service Model Pattern

Combine leafref, when, and presence to create a service model that adapts its interface based on the selected device's platform:

leaf device {
    type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
    }
}

container ios {
    when "/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:platform/ncs:name = 'ios'";
    presence true;
    leaf device-description {
        tailf:info "device description";
        type string;
    }
}

When an operator selects an IOS device, the ios container automatically appears with its IOS-specific parameters. You can replicate this pattern for IOS-XR, NX-OS, and Junos, creating a single service model that handles all vendor variants.

Validated PE Router Selection Pattern

Use must with starts-with() to enforce naming conventions:

leaf device {
    tailf:info "PE Router";
    type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
    }
    must "starts-with(current(), 'PE')" {
        error-message "Only PE devices can be selected.";
    }
}

This pattern ensures that only devices following the PE naming convention can be selected, preventing accidental misconfiguration.

Dynamic Encapsulation Pattern

Combine contains() with when and tailf:default-ref for intelligent subinterface handling:

leaf port {
    type string;
}

container encapsulation {
    when "contains(current()/../port, '.')" {
        tailf:dependency "../port";
    }
}

leaf BVI {
    type uint16 {
        range 1..4094;
    }
}

container encapsulation {
    choice encapsulation-choice {
        container dot1q {
            presence true;
            leaf tag {
                type uint16 {
                    range 1..4094;
                }
                tailf:default-ref "../../../BVI";
            }
        }
    }
}

The encapsulation container only appears for subinterfaces (ports containing a dot), and the VLAN tag automatically inherits from the BVI value unless explicitly overridden.

Streamlined Operator Input Pattern

Combine tailf:cli-flatten-container, tailf:cli-compact-syntax, and tailf:cli-flat-list-syntax to create a service that feels natural to configure:

container customer {
    tailf:cli-flatten-container;
    leaf name {
        type string;
    }
    leaf address {
        type string;
    }
}

leaf-list vrf-name {
    tailf:cli-flat-list-syntax;
    type string;
}

container vrf-config {
    tailf:cli-compact-syntax;
    leaf vrf {
        type string;
    }
    leaf local-as-number {
        type enumeration {
            enum 12345;
            enum 23456;
        }
    }
}

This combination creates a CLI experience where operators can provision services quickly with minimal keystrokes while the running configuration remains clean and readable.

Best Practices for YANG Modeling in NSO Service Development

Drawing from the techniques covered in this guide, here are consolidated best practices for building production-grade YANG models in NSO.

Validation Strategy:

  • Use leafref for strict validation where data integrity is non-negotiable
  • Use tailf:non-strict-leafref only for pre-provisioning scenarios where referenced data may not yet exist
  • Combine must constraints with clear error-message strings so operators understand why a commit was rejected
  • Use when to hide irrelevant parameters based on device type or configuration state

CLI Experience:

  • Apply tailf:cli-flatten-container to simple containers with two or three leaves to enable single-line input
  • Use tailf:cli-add-mode for complex containers with many leaves where a dedicated CLI mode improves discoverability
  • Enable tailf:cli-expose-key-name when list keys are not self-explanatory
  • Use tailf:cli-compact-syntax to keep running configuration output concise
  • Apply tailf:cli-flat-list-syntax to leaf-lists for natural input without brackets

Data Modeling:

  • Use presence true on containers that represent optional features
  • Apply min-elements and max-elements to enforce cardinality rules on lists
  • Use tailf:hidden true for internal storage nodes that service code needs but operators should not see
  • Leverage tailf:default-ref to reduce redundant input where one value logically derives from another
  • Always use tailf:cli-show-with-default on critical parameters where operators need to see the value regardless of whether it matches the default

Debugging and Testing:

  • Enable devtools true and use xpath eval to test expressions before embedding them in YANG models
  • Use display xpath on running configuration to discover the correct paths for leafref and when expressions
  • Test all must constraints with both valid and invalid inputs to verify error messages

Frequently Asked Questions

What Is the Difference Between leafref and tailf:non-strict-leafref in YANG?

Standard leafref enforces strict data validation — the value entered by the operator must exist at the referenced path in the CDB. If it does not exist, NSO rejects the input with an error. tailf:non-strict-leafref provides the same tab completion hints as leafref but does not enforce validation. It accepts any value, even if it does not exist at the referenced path. Use standard leafref in production for data integrity, and tailf:non-strict-leafref for pre-provisioning workflows.

How Do I Test XPath Expressions in Cisco NSO?

Enable developer tools with devtools true at the NSO CLI, then enter configuration mode and use the xpath eval command followed by your expression. For example, xpath eval count(devices/device) returns the number of devices. This interactive evaluator supports all XPath functions available in NSO, including string operations like translate, substring, and re-match, as well as numeric and boolean functions.

When Should I Use the when Statement vs. the must Statement?

The when statement controls node visibility — if the expression is false, the node is hidden from the CLI and all northbound interfaces entirely. The must statement controls validation — the node is always visible, but NSO rejects any commit where the must expression evaluates to false. Use when when certain parameters are irrelevant based on the current configuration context (for example, hiding IOS-specific options when a Junos device is selected). Use must when you need to enforce business rules while keeping the parameter visible (for example, requiring device names to start with "PE").

What Does tailf:hidden Do in a YANG Model?

The tailf:hidden true statement hides a leaf or container from all northbound interfaces, including the CLI and Web UI. The node still exists in the CDB and can be read and written by service code (Java, Python, or templates). This makes it ideal for storing intermediate values, calculated results, or internal state that your service logic needs but that operators should never directly modify. Think of it as internal storage within your YANG data model.

How Do I Make a Container Optional in YANG?

Add presence true to the container definition. Without the presence statement, a container exists implicitly whenever any of its child nodes have values. With presence true, the container must be explicitly created by the operator, and the container's existence or absence carries semantic meaning. This is useful for modeling optional features like routing protocol selection, where each protocol is represented by a presence container.

Can I Restrict the Number of Elements in a YANG List?

Yes. Use the min-elements and max-elements statements within a list or leaf-list definition. For example, min-elements 1 requires at least one entry, while max-elements 1 restricts the list to a single entry. Combining both with equal values enforces an exact count. NSO validates min-elements at commit time and max-elements at input time, providing immediate feedback to operators.

Conclusion

Advanced YANG data modeling is the foundation of building robust, user-friendly, and production-grade service packages in Cisco NSO. From XPath path expressions and constraint statements like when and must, to tailf extensions that shape the CLI experience, these techniques transform basic YANG schemas into intelligent, self-validating automation tools.

The key takeaways from this guide are:

  1. XPath is your navigation language — master current(), deref(), contains(), and starts-with() for writing precise constraints and references.
  2. Validation is layered — use leafref for strict type references, must for business rules, and when for conditional visibility.
  3. The CLI experience matters — tailf extensions like cli-flatten-container, cli-add-mode, cli-compact-syntax, and cli-flat-list-syntax make the difference between a usable and unusable service package.
  4. Debug interactively — enable devtools true and use xpath eval to validate expressions before committing them to your YANG model.
  5. Design for operators — use tailf:hidden for internal storage, tailf:default-ref for intelligent defaults, and tailf:cli-show-with-default for critical visibility.

As network automation continues to evolve, the ability to write sophisticated YANG models is becoming an essential skill for network engineers. Whether you are building L3VPN services, SD-WAN provisioning workflows, or data center fabric automation, these advanced YANG modeling techniques will help you create NSO service packages that are reliable, maintainable, and a pleasure to operate.

Explore more automation and network programmability content on NHPREP to continue building your skills in network service development and orchestration.