How Microsoft's DSC engine is shaping the new adapter model
What if you could ship a new DSC resource without writing a single line of code?
From the early days, Microsoft DSC bridged the gap between the new engine and everything that isn't a native command-based DSC resource. Think about the PowerShell DSC resources that have existed in the DSC community for a long time or WMI classes (the Microsoft.Windows/WMI adapter).
They made the ecosystem usable and, on some level, understandable to each other. But as we learned over time, they carried a lot of internal logic to:
- Discover resources from the subsystem.
- Get the descriptions from each of them.
- Validate the resources that got surfaced.
Yet, with time, a new PR quietly redefined what that bridge is. On the surface, it adds a new registry adapter and a new Microsoft.Windows/Personalization resource. But underneath, it moves the authority over an adapted resource away from the adapter and into the resource's own manifest. And the better part? DSC's engine now does the heavy lifting.
This article looks at what actually changed in more detail, and why it matters for anyone who wants to author resources.
The adapter model until now
To understand the shift, we've to take a step back and look at how the classic adapters work. An adapter is a command resource with kind: adapter in its resource manifest. Its dominant feature is the list operation: when DSC needs to know which adapted resources exist, it runs the adapter, and the adapter enumerates a subsystem at runtime.

For example, PowerShell's adapter walks the $env:PSModulePath looking for modules with DSC resources, whereas the WMI adapter just queries for the available classes on the system.
So, here's the thing. Because historically, adapted resources did not have manifests of their own (they were discovered through the list operation), the adapter is the single source of truth for everything about them. Think about the DSC resource name (and the module), their capabilities (get, set, test, ...), their property schemas, and whether a given configuration is actually even valid.
Validation sort of happens through the adapter, if the validate capability does a thing.
[!NOTE]
Thevalidatecapability was never officially implemented in PowerShell's adapter, nor in the WMI one.validateis a deprecated feature.
As you can see, this design works, but it has a real cost. Discovery means starting that strange runtime just to find what exists. So some of the adapters grew caching layers and lookup tables to stay fast. Validation errors became tough, as they're surfaced directly through the adapter rather than the engine. So they vary in quality from one adapter to the next. And there's no way to know a resource's shape without invoking its adapter first.
The adapter, in short, is a discovery engine. It's powerful, but heavy.
What has been introduced
The earlier-mentioned pull request builds on a newer idea in the DSC codebase: the adapted resource manifest. Instead of only existing once an adapter discovers it at runtime, an adapted resource is now a standalone YAML or JSON file with kind: resource, its own type, version, and capabilities, plus arequireAdapter property naming the adapter that executes it. DSC discovers these manifests through its normal discovery pipeline, exactly like native command resources.
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json",
"type": "DatabricksDsc/AdaptedResource",
"kind": "resource",
"version": "1.0.0",
"capabilities": ["get", "set"],
"requireAdapter": "Microsoft.Windows/WindowsPowerShell",
"content": {
"exampleSetting": "data the adapter knows how to interpret"
},
"schema": {
"embedded": {
"type": "object",
"properties": {
"exampleSetting": { "type": "string" }
}
}
}
}The three engine changes in the PR make this model click into place:
- The engine owns validation: DSC now validates an instance against the JSON Schema embedded in the adapted resource's manifest, instead of calling the adapter's
validatecapability. - Manifests can carry inline content: Alongside the existing
pathproperty, an adapted resource manifest can now definecontent. This is an arbitrary block of structured data that the adapter interprets, meaning that the manifest no longer just points at the resource - it can be the resource. - The adapter receives that content at invocation time: A new
adaptedContentArgargument type lets an adapter's manifest declare how the engine should pass thatcontentalong for the specific adapter. More on this later.
Putting those 3 bullet points in simple words: the adapter stops being a discovery engine and becomes a translation engine.

Registry adapter in practice
To put the proof in the pudding, we can take a look at the Microsoft.Windows/Personalization resource. This resource speaks the words already based on the naming: it's a resource for Windows personalization settings.
It contains light/dark mode, transparency, and accent color. The new Microsoft.Windows.Adapter/Registry is built on top of it, which contains roughly 260 lines of YAML and contains no code at all. Each property in its content block maps one JSON property to one registry value:
type: Microsoft.Windows/Personalization
kind: resource
requireAdapter: Microsoft.Windows.Adapter/Registry
content:
appsUseLightTheme:
keyPath: HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize
valueName: AppsUseLightTheme
valueType: REG_DWORD
jsonType: boolean
defaultValueIfNotFound: 0
mapJsonToRegistry:
'false': 0
'true': 1
schema:
embedded:
# JSON Schema defining appsUseLightTheme as a booleanThe mapping vocabulary is small but expressive:
| Property | What it does |
|---|---|
keyPath |
Locates the registry key that holds the value |
valueName |
Names the specific registry value under that key |
valueType |
Declares the registry data type, such as REG_DWORD |
jsonType |
Declares the user-facing type, such as boolean or stringArray |
mapJsonToRegistry |
Translates each JSON value to its registry equivalent |
defaultValueIfNotFound |
Provides a fallback when the key or value is absent, which often has a well-known meaning in the registry |
That last value, defaultValueIfNotFound matters because an absent registry value has a well-known meaning of its own. Of course, the above scales beyond booleans. For example, the manifest maps the Start menu's folder list, stored as REG_BINARY GUIDs, onto a friendly string array of names like Documents and Downloads.
Here's the nice part about such a model. Users get a typed, discoverable API over raw registry plumbing:
resources:
- name: Dark mode everywhere
type: Microsoft.Windows/Personalization
properties:
appsUseLightTheme: false
systemUsesLightTheme: falseYou declare appsUseLightTheme: false; the adapter writes a REG_DWORD of 0 to the right key. Nobody has to remember that path, and the embedded schema rejects a typo'd property before anything touches the registry.
Comparing the two models
With both models mentioned in this article, it's best to see the differences side by side. The short version: work that used to happen inside the adapter at runtime now happens in the engine, or doesn't need to happen at all.
| Classic adapters (PowerShell, WMI) | New model (registry adapter) | |
|---|---|---|
| Resource discovery | Runtime enumeration via list |
Static manifest, engine discovery |
| Schema & validation | Adapter's validate function |
JSON Schema in the manifest, enforced by the engine |
| Resource definition | Code (PowerShell module, WMI class) | Declarative YAML (content mapping) |
| Invocation | Nested resources array, adapter fans out |
Per instance, content passed via --adapted-resource |
| Performance profile | Caches plus foreign runtime startup | No cache needed; a single binary call |
| Who can author one | Developers | Anyone comfortable writing YAML |
Knowing about the two models, two things are worth stating plainly. Firstly, the classic adapters aren't going anywhere. They remain the right design for surfacing existing subsystems, where the resources live elsewhere (and must be discovered). The new model shines when you're authoring new resources over a generic engine like the registry.
Secondly, the two models share one contract: from a configuration author's point of view, an adapted resource looks and behaves like any other resource. But the change in itself is in who does the work underneath.
Okay, there's a third one on an earlier promise mentioned about adaptedContentArg. Instead of receiving a batch of nested instances to fan out itself, the adapter declares an argument in its manifest, --adapted-resource in the registry adapter's case, and the engine uses it to hand over the manifest's content block together with the instance's desired state, one instance at a time.

Closing thoughts
The registry adapter is deliberately minimal. It implements only the type conversions the Personalization resource needs, with more promised as real use cases appear. But the pattern generalizes, and that's where it gets interesting:
- The same shape can apply to INI, XML, files, to WMI, or to any settings stored with a regular structure.
- One adapter binary can carry an open-ended family of zero-code resources, defined by the community as shareable manifests.
- Because each manifest embeds its schema, tooling such as editors, linters, and documentation generators can understand these resources without executing anything.
If you want to give it a try, grab a recent DSC release and run dsc resource get -r Microsoft.WIndows/Personalization, then read through the Personalization manifest in the repo. It's the best documentation of the model today.