By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
  • Home
  • Products
  • Agents
  • Capital
  • Commerce
Reading: Windows Agent Launcher Tutorial: agent.json End to End
Sign In
  • Join US
Font ResizerAa
  • Home
  • Products
  • Agents
Search
  • Home
  • Products
  • Agents
  • Capital
  • Commerce
Have an existing account? Sign In
Follow US
> Blog > Agent Infrastructure > Windows Agent Launcher Tutorial: agent.json End to End
Windows Agent Launcher registration flow showing agent.json, an App Action, and the package manifest extension
Agent Infrastructure

Windows Agent Launcher Tutorial: agent.json End to End

Surya Koritala
Last updated: June 3, 2026 10:44 pm
By Surya Koritala
28 Min Read
Share
SHARE

A copy-paste, end-to-end walkthrough that takes a working Windows app and registers it as an Agent Launcher: the App Action, agent.json, the package-manifest extension, and odr.

Contents
  • What is a Windows Agent Launcher?
  • The three pieces every Agent Launcher needs
  • Step 1: Wire an App Action with agentName and prompt entities
  • Step 2: Author agent.json (the agent definition manifest)
  • Step 3: Set Build Action = Content and Copy if newer (the buried gotcha)
  • Step 4: Declare the app extension in the package manifest
  • Static vs dynamic: register with odr agent-info add
        • Pros
        • Cons
  • Step 5: Verify it appears with odr agent-info list
    • Ship it: three artifacts, one matching string
  • Builder’s take
  • Frequently asked questions
    • How do I make my app an agent on Windows?
    • What goes in agent.json for a Windows Agent Launcher?
    • Why must an App Action have agentName and prompt entities?
    • How do I register a Windows Agent Launcher dynamically?
    • Why doesn’t my agent show up in odr agent-info list?
    • Do I need a packaged app to build an Agent Launcher?
  • Primary sources

What is a Windows Agent Launcher?

A Windows Agent Launcher is a registered entry point that lets any Windows app expose an AI agent so that other apps and system experiences — Start, search, Copilot surfaces — can discover and invoke it through one standard mechanism instead of custom per-agent integration code. This windows agent launcher tutorial shows you how to take a working app and register it as a launcher end to end, with copy-paste C#, agent.json, and package-manifest XML.

Microsoft frames it cleanly in the overview docs: “An Agent Launcher is a registered entry point for an AI agent on Windows. Without Agent Launchers, each experience would need custom integration code for every agent—whether through Model Context Protocol (MCP), App Actions, or proprietary APIs.” The launcher solves that by giving apps a “unified registration and discovery mechanism where apps register their agents once.”

Agent Launchers sit on top of the App Actions on Windows framework, and they got a much bigger spotlight at Build 2026, where Microsoft positioned Windows itself as an agent platform and open-sourced the Windows Agent Framework under the MIT license. The byteiota recap put it directly: “The Windows Agent Framework — open-sourced under MIT today — is the mechanism.” The Agent Launcher is the on-ramp that gets your existing app into that mechanism.

Every ranking page on this topic right now is either the raw Microsoft Learn reference schema or a Build 2026 news recap. None of them walk a real app from zero to a registered, discoverable launcher and stop at the failure points. That is the gap this tutorial fills.

Windows Agent Launcher registration flow showing agent.json, an App Action, and the package manifest extension
Image.

You need Windows 11 with SDK 10.0.26100.0 or greater, Visual Studio 2022 (17.6+) with the Windows App development workload, and the Microsoft.AI.Actions NuGet package. Critically, your app must have package identity (an MSIX-packaged WinUI 3, WPF, or WinForms app) — App Actions and Agent Launchers cannot register from an unpackaged app.

The three pieces every Agent Launcher needs

An Agent Launcher is exactly three artifacts that have to agree with each other: an App Action that exposes agentName and prompt inputs, an agent.json definition manifest that points at that action, and an app extension declaration in your package manifest that tells Windows where the manifest lives. Get all three aligned and your agent appears in the On-Device Registry; miss one and it silently does not.

The single most important relationship in the whole feature is one string match. As the schema reference states, “The value of the action_id field in the agent definition manifest must match the id field specified in the action definition manifest for an action included in the same app package.” Keep that in mind through every step below.

Here is the full inventory before we build it piece by piece.

PieceFile / locationWhat it doesKey field
App ActionC# class with [ActionProvider]; generates registration.jsonExposes the invocable action with agentName + prompt inputsid (e.g. ZavaAgentAction)
Agent definitionagent.json (e.g. Assets/agentRegistration.json)Declares display metadata and links to the actionaction_id must equal the action’s id
App extensionPackage.appxmanifest uap3:ExtensionRegisters the agent with Windows and points at agent.jsonName = com.microsoft.windows.ai.agentInfo
The three required pieces of a Windows Agent Launcher and how they connect

Step 1: Wire an App Action with agentName and prompt entities

To act as an Agent Launcher, your App Action must expose one TextActionEntity named agentName and one named prompt, and every single input combination must accept both of those entities. This is the rule the reference docs state but never make loud enough, and it is the most common reason a perfectly valid-looking action fails launcher validation.

Start from a packaged WinUI 3 app and add the Microsoft.AI.Actions NuGet package. Then add an action provider class. The Microsoft.AI.Actions source generator reads .NET attributes and auto-generates the underlying IActionProvider implementation plus the action definition JSON at build time, so you write strongly typed C# instead of hand-editing JSON. Here is the action provider, lifted straight from the agent-launcher guidance:

Notice the two [WindowsActionInputCombination] attributes. The first accepts agentName + prompt; the second adds attachedFile but still includes agentName and prompt. That is the rule in practice — you can add optional inputs, but you can never drop the two required ones from any combination. The UsesGenerativeAI = true flag marks the action as agentic.

One more requirement from the overview docs that is easy to miss: “Invoking the App Action should open an application where the user can actively interact with the agent, not just complete work in the background.” Agent Launchers are for interactive, multi-turn agents — not silent automation. If your action just does work headlessly, it is an App Action, not an Agent Launcher.

Every input combination must accept both agentName and prompt TextActionEntity inputs. If you add a combination that omits either one, the action will register as a normal App Action but will not qualify as an Agent Launcher — and you will get no error telling you why.

using Microsoft.AI.Actions.Annotations;
using System.Threading.Tasks;
using Windows.AI.Actions;

namespace ZavaAgentProvider
{
    [ActionProvider]
    public sealed class ZavaAgentActionsProvider
    {
        [WindowsAction(
            Id = "ZavaAgentAction",
            Description = "Start an agent for Zava",
            Icon = "ms-resource://Files/Assets/ZavaLogo.png",
            UsesGenerativeAI = true
        )]
        [WindowsActionInputCombination(
            Inputs = ["agentName", "prompt"],
            Description = "Start Zava Agent with '${agentName.Text}'."
        )]
        [WindowsActionInputCombination(
            Inputs = ["agentName", "prompt", "attachedFile"],
            Description = "Start Zava Agent with '${agentName.Text}' and additional context."
        )]
        public async Task StartZavaAgent(
            [Entity(Name = "agentName")] string agentName,
            [Entity(Name = "prompt")] string prompt,
            [Entity(Name = "attachedFile")] FileActionEntity? attachedFile,
            InvocationContext context)
        {
            // Your agent invocation logic here
            await InvokeAgentAsync(agentName, prompt, attachedFile);
        }

        public async Task InvokeAgentAsync(string agentName, string prompt, FileActionEntity? attachedFile)
        {
            if (attachedFile != null)
            {
                await Task.Run(() => $"Starting agent '{agentName}' with prompt '{prompt}' and file context");
            }
            else
            {
                await Task.Run(() => $"Starting agent '{agentName}' with prompt '{prompt}'");
            }
        }
    }
}

Step 2: Author agent.json (the agent definition manifest)

The agent.json agent definition manifest is a small file with seven properties — manifest_version, version, name, display_name, description, placeholder_text, and icon — plus the all-important action_id that links it to the App Action you just wrote. This is the heart of the agent.json windows schema, and it is shorter than people expect.

Create a JSON file in your project’s Assets folder (the agent-launcher docs name it agentRegistration.json). Every field below is verbatim from the reference example, and action_id is set to “ZavaAgentAction” — exactly matching the Id on the [WindowsAction] attribute from Step 1.

display_name, description, and icon all support localization through the ms-resource:// URI scheme, which resolves to .resw string resources (C#) or .rc resources (C++). placeholder_text is the one optional property — it is the reference query Windows shows the user, for example “What can you help me with?”. Everything else is required.

Here is the full property reference so you can author the manifest without round-tripping to the docs.

{
  "manifest_version": "0.1.0",
  "version": "1.0.0",
  "name": "Zava.ZavaAgent",
  "display_name": "ms-resource://zavaAgentDisplayName",
  "description": "ms-resource://zavaAgentDescription",
  "placeholder_text": "ms-resource://zavaAgentPlaceHolderText",
  "icon": "ms-resource://Files/Assets/ZavaLogo.png",
  "action_id": "ZavaAgentAction"
}
PropertyRequiredLocalizableNotes
manifest_versionYesNoSchema version. Current value is “0.1.0”.
versionYesNoYour agent’s semantic version, e.g. “1.0.0”.
nameYesNoUnique reverse-domain identifier, e.g. “Zava.ZavaAgent”. Not localizable; must be unique in your package.
display_nameYesYesUser-facing name. Use ms-resource:// for localization.
descriptionYesYesUser-facing description of what the agent does.
placeholder_textNoYesReference query shown to the user.
iconYesYesAgent icon; resolves by theme, contrast, scale, and target size.
action_idYesNoMust equal the id of an App Action in the same package.
agent.json property reference (Agent definition JSON schema)

Step 3: Set Build Action = Content and Copy if newer (the buried gotcha)

agent.json must be added to your project with Build Action set to Content and Copy to Output Directory set to Copy if newer — if you skip this, the file never makes it into your package, and static registration finds nothing. The reference page states it in one easy-to-miss sentence: this file “must be included in your project with the Build Action set to ‘Content’ and Copy to Output Directory set to ‘Copy if newer’.”

In a C# project you do this in the file’s Properties pane: right-click agentRegistration.json in Solution Explorer, select Properties, and set Copy to Output Directory to “Copy if newer” (or “Copy always”). For C++ projects, the equivalent goes in the project file:

This is the step that costs people an afternoon. The agent.json is valid, the App Action works, the manifest looks right — but odr agent-info list returns nothing because the JSON never landed in the output directory the package ships. Check this first whenever a statically registered agent fails to appear.

<Content Include="Assets\agentRegistration.json">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

“The agent.json is valid, the App Action works, the manifest looks right — but the registry returns nothing because the JSON never landed in the package.”

The Build Action = Content trap

Step 4: Declare the app extension in the package manifest

To register your app as an agent on Windows statically, add a uap3:Extension to Package.appxmanifest with the AppExtension Name set to com.microsoft.windows.ai.agentInfo, and point its Registration element at the package-relative path of your agent.json. This is the windows agent framework agent.json wiring that ties everything to the OS.

If you followed the App Actions tutorial, your manifest already has one uap3:Extension with Name com.microsoft.windows.ai.actions that registers the action itself (its Registration points at the generated registration.json). For the launcher you add a second, separate extension for the agentInfo. The docs are explicit: “Each statically registered Agent Launcher should have its own AppExtension entry.”

Make sure the uap3 namespace is declared on the root Package element (xmlns:uap3=”http://schemas.microsoft.com/appx/manifest/uap/windows10/3″). The PublicFolder attribute (“Assets”) plus the Registration value (“agentRegistration.json”) together form the package-relative path to your manifest — so PublicFolder must match where the file actually lands after the Copy-if-newer step from Step 3.

Here is the agentInfo extension to add inside your Application element’s Extensions block.

Your final manifest has two uap3:Extension entries: com.microsoft.windows.ai.actions (registers the App Action and its registration.json) and com.microsoft.windows.ai.agentInfo (registers the Agent Launcher and its agentRegistration.json). They are siblings, and one does not replace the other.

<uap3:Extension Category="windows.appExtension">
  <uap3:AppExtension
    Name="com.microsoft.windows.ai.agentInfo"
    Id="ZavaAgent"
    DisplayName="Zava Agent"
    PublicFolder="Assets">
    <uap3:Properties>
      <Registration>agentRegistration.json</Registration>
    </uap3:Properties>
  </uap3:AppExtension>
</uap3:Extension>

Static vs dynamic: register with odr agent-info add

Agent Launchers register two ways: statically through the package manifest at install time, or dynamically at runtime with odr agent-info add — and the choice is a real product decision, not a formality. Static registration (Step 4) is right for agents that always ship. Dynamic registration lets you add or remove agents based on app logic: a license check, a subscription tier, or a feature flag.

Run dynamic registration from inside your packaged app by shelling out to odr.exe. The command takes the path to your agent registration JSON and returns a JSON response with the assigned agent_id and an extended_error of 0 on success:

One hard constraint from the docs: “Due to package identity requirements, you can’t use agent-info add and agent-info remove from an unpackaged app. You must run these commands from within a packaged application that also contains the associated App Action.” To pull an agent back out, call odr agent-info remove with the same path — and note you can only remove agents your own package added dynamically.

Pros
  • Static: zero runtime code; agent is present the moment the app installs
  • Static: ideal for free, always-available agents bundled with the app
  • Dynamic: gate agents behind auth, subscription, or feature flags
  • Dynamic: add/remove agents without reinstalling the package
Cons
  • Static: every shipped agent is visible to all users, no gating
  • Static: changing the agent set requires a package update
  • Dynamic: must run from a packaged app with the associated App Action
  • Dynamic: you can only remove agents your own package added
using System.Diagnostics;

ProcessStartInfo startInfo = new ProcessStartInfo
{
    FileName = "odr.exe",
    Arguments = $"agent-info add \"<path to agentDefinition.json>\"",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    CreateNoWindow = true
};

using Process process = new Process { StartInfo = startInfo };
process.Start();

string output = await process.StandardOutput.ReadToEndAsync();
string error = await process.StandardError.ReadToEndAsync();

await process.WaitForExitAsync();
// output -> { "agent_id": "ZavaAgent_cw5n1h2txyewy_Zava.ZavaAgent", "extended_error": 0 }

Step 5: Verify it appears with odr agent-info list

Ship it: three artifacts, one matching string

A Windows Agent Launcher is not complicated, it is just unforgiving about consistency. Wire an App Action with agentName + prompt on every input combination, author agent.json with action_id pointing at that action’s id, set the file to Content / Copy if newer, declare the com.microsoft.windows.ai.agentInfo extension, then prove it with odr agent-info list. Register statically for free always-on agents and dynamically behind a license check for paid ones. Do those five things in order and your existing Windows app is a first-class, system-discoverable agent.

Treat odr agent-info list as your acceptance test: if your agent is not in that JSON array with the correct package_family_name and action_id, no Windows surface can launch it. After building and deploying your packaged app (static) or running odr agent-info add (dynamic), open a terminal and list the registry.

A successful registration returns an array where each entry carries the package_family_name and action_id you use together to identify and invoke the action, plus the resolved metadata from your agent.json. You can also pass icon qualifiers — odr agent-info list –theme dark,light –scale 200 — to confirm your themed and scaled icons resolve correctly.

If the command returns an empty array, work backward through the checklist: did agent.json copy to the output directory (Step 3); does PublicFolder + Registration point at the real file (Step 4); does action_id match the App Action id (Steps 1 and 2). For dynamic failures, read the extended_error field — a non-zero value is an HRESULT, and the message field describes it. For example E_INVALIDARG (0x80070057) fires on a bad JSON path or a double registration, and E_NOTFOUND (0x80070490) on removing an agent that was never registered.

odr agent-info list

# Expected (abridged) output:
# {
#   "package_family_name": "ZavaPackageFamilyName",
#   "action_id": "ZavaAgentAction",
#   "id": "ZavaAgent_cw5n1h2txyewy_Zava.ZavaAgent",
#   "name": "Zava.ZavaAgent",
#   "display_name": "Zava Agent",
#   "version": "1.0.0"
# }
odr agent-info list returns an empty arrayAlmost always one of three things. (1) agent.json never reached the package — confirm Build Action = Content and Copy to Output Directory = Copy if newer. (2) PublicFolder in the manifest does not match where the file actually lands, so the Registration path is dead — make PublicFolder and your project folder agree. (3) The manifest extension Name is wrong — it must be com.microsoft.windows.ai.agentInfo, not the actions Name.
Agent appears but cannot be invoked / action not foundThe action_id in agent.json does not match the id of any App Action in the same package. Open the generated registration.json and confirm the action’s id (the Id on the [WindowsAction] attribute) exactly matches action_id in agent.json — case-sensitive.
My edits to the generated JSON keep disappearing on buildThe Microsoft.AI.Actions source generator regenerates the action definition file every build, overwriting manual edits (allowedAppInvokers is the classic casualty). Set GenerateActionRegistrationManifest to false in your .csproj to preserve hand edits, then re-enable only when you intentionally regenerate.
E_INVALIDARG (0x80070057) from odr agent-info addEither the JSON path you passed is invalid, or you are trying to register an agent that is already registered. Verify the absolute path resolves inside the package, and call odr agent-info remove first if you are re-adding.
agent-info add fails from my console appYou are running it from an unpackaged process. odr agent-info add and remove require package identity and must run from a packaged app that also contains the associated App Action. Move the call into your MSIX-packaged app.

Builder’s take

I build agent infrastructure for a living (Cyntr and Loomfeed), and the Agent Launcher model is the most interesting thing Microsoft shipped at Build 2026 for app developers. It is also the most under-documented. Here is what actually matters once you get past the reference pages:

  • The whole feature is three artifacts that must agree on one string: action_id in agent.json must equal the id of your App Action. Ninety percent of ‘my agent does not show up’ bugs are a mismatch here or a stale generated registration.json overwriting your edits.
  • The agentName + prompt rule is non-negotiable and easy to get wrong: every input combination must accept both. If you add an attachedFile combination, it still needs agentName and prompt, or the launcher silently fails validation.
  • The buried gotcha that wastes an afternoon: agent.json needs Build Action = Content and Copy to Output Directory = Copy if newer. Miss it and the file never reaches your package, so static registration finds nothing.
  • Static vs dynamic registration is a real product decision, not a footnote. Gate paid agents behind dynamic odr agent-info add after a license check; ship free ones statically in the manifest.
  • Treat odr agent-info list as your unit test. If your agent is not in that JSON array with the right package_family_name and action_id, no surface can launch it, full stop.

Frequently asked questions

How do I make my app an agent on Windows?

Register it as an Agent Launcher with three artifacts: an App Action that exposes agentName and prompt TextActionEntity inputs, an agent.json definition manifest whose action_id matches that action’s id, and a uap3:Extension in your package manifest with Name com.microsoft.windows.ai.agentInfo pointing at the agent.json. Then verify with odr agent-info list. Your app must be MSIX-packaged with package identity.

What goes in agent.json for a Windows Agent Launcher?

Eight properties: manifest_version (“0.1.0”), version (semantic, e.g. “1.0.0”), name (unique reverse-domain id), display_name, description, optional placeholder_text, icon, and action_id. All but placeholder_text are required. display_name, description, and icon support ms-resource:// localization. action_id must equal the id of an App Action in the same package.

Why must an App Action have agentName and prompt entities?

Those two TextActionEntity inputs are what qualify an App Action as an Agent Launcher. The system passes the agent’s name and the user’s prompt through them when it invokes the agent. The strict rule is that every input combination on the action must accept both agentName and prompt — you can add optional entities like attachedFile, but you can never drop the two required ones.

How do I register a Windows Agent Launcher dynamically?

Run odr agent-info add “” from inside your packaged app, typically by shelling out to odr.exe with System.Diagnostics.Process. It returns JSON with an agent_id and extended_error of 0 on success. Remove it with odr agent-info remove. Both commands require package identity and must run from a packaged app that contains the associated App Action.

Why doesn’t my agent show up in odr agent-info list?

The most common cause is that agent.json was not set to Build Action = Content and Copy to Output Directory = Copy if newer, so it never reached the package. Next most common: the manifest PublicFolder plus Registration path do not point at the real file, the extension Name is not com.microsoft.windows.ai.agentInfo, or action_id does not match the App Action id. Work through those four in order.

Do I need a packaged app to build an Agent Launcher?

Yes. App Actions and Agent Launchers require package identity, so your app must be MSIX-packaged (a packaged WinUI 3, WPF, or WinForms desktop app). You cannot register an Agent Launcher, nor run odr agent-info add or remove, from an unpackaged app. Target Windows SDK 10.0.26100.0 or greater.

Primary sources

  • Get started with Agent Launchers on Windows — Microsoft Learn
  • Agent definition JSON schema for Agent Launchers on Windows — Microsoft Learn
  • Agent Launchers on Windows overview — Microsoft Learn
  • Get started with App Actions on Windows — Microsoft Learn
  • Microsoft Build 2026: Windows Is Now an Agent Platform — byteiota

Last updated: June 3, 2026. Related: Agent Infrastructure.

E2B Sandbox in Production — A Review
Build a LangGraph Multi-Agent Crew With Claude (Tutorial)
AI agent industry digest — week of May 23, 2026
RAG vs Agent Memory — When to Use Which (Tutorial)
AI Features PM Questions: 10 Every Product Manager Asks
TAGGED:Agent Launchersagent.jsonApp ActionsMicrosoft Build 2026On-Device RegistryWindows Agent FrameworkWindows AIWinUI 3
Share This Article
Facebook Email Copy Link Print
Leave a Comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

More Popular from Alatirok

Dashboard visualizing token consumption per agentic coding task across frontier AI models
Observability

Tokens Per Agentic Coding Task: The 2026 Variance Data

By Surya Koritala
21 Min Read
What Is Cognition Devin? The Enterprise Guide for

What Is Cognition Devin? The Enterprise Guide for 2026

By Surya Koritala
Diagram of an AI agent holding a USDC wallet with spending-limit guardrails enforced before an onchain transfer
Commerce

What Is Circle Agent Stack? USDC Wallets for AI Agents

By Surya Koritala
24 Min Read
Identity & Provenance

AI Agent Identity: Entra Agent ID vs Okta vs SailPoint

AI agent identity governance, Entra vs Okta vs SailPoint: a 2026 buyer matrix on what each…

By Surya Koritala
Observability

Why Does My AI Agent Context Window Fill Up So Fast?

Why does my AI agent context window fill up so fast? Tool definitions eat two-thirds of…

By Surya Koritala
Agent Infrastructure

Migrate OpenAI Agent Builder to Agents SDK Before Nov 30

A hands-on tutorial to migrate OpenAI Agent Builder to Agents SDK before the Nov 30, 2026…

By Surya Koritala
Agent Infrastructure

Best Voice AI Agent Framework 2026: Vapi vs LiveKit vs Pipecat

The best voice AI agent framework 2026 depends on your call volume. Our neutral ranking covers…

By Surya Koritala

Purpose-Built Legal AI vs General LLM: 2026 Verdict

Purpose-built legal AI vs general LLM, settled with real 2026 benchmark data: where ChatGPT and Claude…

By Surya Koritala

what’s actually being built in AI agents, who’s building it, and why it matters. Independent. Opinionated.

Categories

  • Home
  • Products
  • Agents
  • Capital
  • Commerce

Quick Links

  • Home
  • Products
  • Agents

© Alatirok by Loomfeed. All Rights Reserved.

Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?