Make your app agent-ready in an afternoon
Declare your screens and elements, implement one interface, host it — and watch an agent describe and drive your app, with the SDK handling transport, consent, and audit.
"Agent-ready" sounds like a project. It isn't. Making an app drivable by an AI agent is far less work than the phrase suggests, because you only write one thing — a description of what your app can do — and the SDK takes care of the wire. There's no transport to build, no token scheme to invent, no audit log to design. You declare your surface, implement an interface that's mostly one-liners over state you already have, and start a host. By the end of an afternoon any MCP-capable agent on the machine can describe your app and operate it by name. Here's the whole path, start to finish.
Step 1 — declare your surface
Everything begins with the AppSpec: a declarative description of what your app is.[2] It has two parts you'll care about first.
Screens are the navigable areas of your app — a home view, a settings page, an export dialog. Each one is just an id, a human-readable name, and a one-line purpose. The id is what an agent passes when it wants to navigate; the name and purpose are what a person sees when they're deciding whether to approve.
Elements are the drivable controls on those screens. Each element carries a key (<screen-id>.<element-id>, e.g. settings.api-host), a type or role like TextBox, Button, or ComboBox, a short purpose, and the set of actions it supports — a subset of set_value, get_value, invoke, focus, highlight, click_link, and press_key. A text field declares set_value and get_value; a button declares invoke. If a control holds something sensitive like an API key, mark it secret and the router redacts its value everywhere — reads, gets, and the audit trail.
That's the entire mental model. You are not writing automation; you are publishing a menu. The agent reads that menu and plans against it, which is exactly why this approach is stable across redesigns: you're declaring what a control means, not where it's painted.
Step 2 — implement the interface
Once the surface is described, you expose it by implementing IAppUseSurface. It looks like a lot of methods at first glance, but most are genuine one-liners delegating to state your app already holds.
DescribeAsyncreturns the AppSpec you just designed.ReadScreenAsyncreturns a snapshot of the current screen's element values.GetValueAsync/SetValueAsyncread and write a single element by key.InvokeAsyncruns the action behind a button or command.
The window, focus, highlight, and capture methods are there when you want them, and any you don't care about can simply return success or report that they're not supported. The point is that none of this is new logic — SetValueAsync("home.message", v) sets a field your app already has; InvokeAsync("home.send") calls the handler your Send button already calls. You're wiring named keys to behavior that already exists.
Step 3 — host it
With the surface in hand, you turn the app into an App-Use participant with a single call at startup:[1]
await using var host = await AppUseHost.StartAsync(new AppUseHostOptions
{
AppId = "hello",
AppName = "Hello",
AppVersion = "1.0",
Surface = new HelloSurface(),
});
Console.WriteLine($"App-Use endpoint: {host.Endpoint.Current!.Url}");
// ... your main loop ...
That's it. StartAsync brings up the loopback transport, mints a per-instance bearer token, and registers the running instance so the local Hub can find it. Your app keeps running exactly as before — same window, same UX — it's now just also reachable by an agent.
Step 4 — drive it
From any MCP-capable agent on the same machine, the loop is the same for every App-Use app. The agent calls apps.list to discover what's running, app.describe to read your surface, and then app.invoke (along with app.get_value / app.set_value / app.navigate) to operate it. Nothing in this loop is specific to your app — the agent learned how to drive it from the spec you declared, not from a hand-written adapter. The moment your host is up, your app is part of the agent's vocabulary.
What you get for free
This is the part worth dwelling on, because it's where the afternoon really comes from. You wrote a surface and one StartAsync call. In exchange, the SDK provides:
- the transport — a local loopback endpoint, with nothing exposed to the network;
- a per-instance bearer token, so each running copy of your app authenticates independently;
- registration, so the Hub discovers your instance automatically;
- the consent gate, so a human can be asked before a risky action runs; and
- the audit log, so every call against your app is recorded.
None of that is code you write or maintain. You didn't build a security model — you inherited one. That's the trade the protocol makes: you describe your app honestly, and the plumbing that makes it safe to drive comes with the SDK.
Make it accessible while you're at it
Here's a bonus that turns this afternoon into a genuinely good investment. The metadata an agent needs — a stable identity for each control and a human-readable purpose — is the same metadata the operating system's accessibility layer needs for screen readers.[3] If you bind your surface keys to the values you already (or should) set for AutomationProperties.Name and AutomationId, you're feeding two consumers from one source of truth. The work you do to make a control describable to an agent makes it describable to assistive technology too. One investment, two audiences — and both of them benefit from you being precise about what each control is for.
You're done
That's the whole arc: design a surface, implement an interface that mostly forwards to existing state, call StartAsync, and an agent can describe and drive your app — transparently, with consent and audit handled for you. No rewrite, no pixel-hunting, no bespoke adapter to keep alive. An app you shipped years ago can join the agent ecosystem before the afternoon is out. Declare what your app can do, and let it speak for itself.
References
- App Use — 5-minute quickstart. https://aiappuse.com/docs/quickstart.htm
- App Use — The AppSpec model. https://aiappuse.com/docs/app-spec.htm
- App Use — Accessibility. https://aiappuse.com/docs/accessibility.htm
Related articles
Ready to let your app speak for itself?
Declare a surface, implement one interface, host it — and any MCP agent can drive your app transparently.
Get started Read the quickstart