Agents wander up the hill to ask the card what it can do. It tells them, in App Intents.

Ouro AX for Apple
Siri reads your app like a manual. Write a good one.
On Apple's platforms, an agent meets your app through App Intents. Siri picks what to call from titles and descriptions, finds your things by name, and follows your skills. Ouro AX for Apple is the checklist for getting that right, and an X-ray that checks it for you.
The door
What Siri sees when it looks at your app.
App Intents
The things your app can do. Siri reads their titles and descriptions like a menu.
App entities
The things your app knows about, like a recipe or a document, findable by name.
App Shortcuts
Phrases that work before anyone has set anything up.
App skills
A short how-to, in Markdown, that teaches Siri your app's way of doing a longer job.
How it knows
It knows how it knows.
The X-ray reads a built app from outside, never importing its code, and checks it against thirty claims. It's honest about its limits: what only Siri can answer stays open until Siri is asked.
- App Intents metadataReads what the built app declares, right on your Mac.
- Skills linterChecks the skills bundle's shape, names and words.
- AppIntentsTestingRuns the app's queries, Spotlight index and errors in a test, without Siri.
- SiriEvaluationsAsks Siri itself, again and again, on a device running the Siri beta.
- A personSome things only a human can judge, so the report says which and leaves them open.
Real reports
Spoonjoy and Ouro MD, X‑rayed, before and after.
Spoonjoy went from 5 to 12 of 29 claims holding, and Ouro MD from 8 of 29 to 14 of 30. Plenty of what's left is waiting for Siri's beta or a person rather than failing. Flip between before and after, and open any claim for its reason and its fix.
12 of 29 claims hold
Spoonjoy on iPhone and iPad, with the AX fixes, Siri tools and the cook-along skill (#202 to #204). 59 intents, 10 entities, 10 App Shortcuts, 1 app skill. Under the hood, the claims rest on smaller checks: 289 pass, 13 fail, 15 not run.
- App Intents metadata: ran
- Skills linter: ran
- AppIntentsTesting: did not run
- SiriEvaluations: did not run
- A person: did not run
Holds: Every intent has a title a person would say, not its type name.
Why: Siri tells intents apart by their titles, and Shortcuts lists them by title.
Holds: Every intent has a description that says what it does, beyond its title.failed before
Why: Siri decides which intent fits a request from its title and description together.
Holds: Every parameter has a title.
Why: Siri and Shortcuts show the title when they ask the person for a value.
Holds: Every parameter has a description that says what value it wants.failed before
Why: Siri fills parameters from what the person said, guided by each parameter's description.
Not checked: The app's main actions are tool intents (
@AppIntent(.tool)) or adopt a Siri schema, so Siri AI can call them.Why: With the Siri AI preview, Siri calls only the custom intents an app marks as tools.
Fix: Mark the intents people would ask Siri for with
@AppIntent(.tool), building with the 27.3 SDK behind an availability check.metadata from Xcode tools 27B52 cannot mark tool intents, and no intent adopts a schema; build with the 27.3 SDK to check
Holds: No intent is both a tool and an adopter of a schema that already reaches Siri.
Why: A schema in a domain Siri supports already makes the action available; marking it a tool as well is the misuse Apple's guide names.
Holds: The app offers App Shortcuts for its main actions, so Siri and Spotlight find them with no setup.
Why: App Shortcuts are how an app's actions reach Siri and Spotlight before the person builds anything.
Not checked: When an intent is refused, its error is one sentence that says what to do next.
Why: Siri reads the error to the person; an error that names the fix lets the person, or Siri, recover in one step.
Fix: Throw an error that conforms to
CustomLocalizedStringResourceConvertibleand says what to do: "There's no note X. Pick one from your notes, then try again."needs a behaviour run: AppIntentsTesting against the app on a device or simulator whose OS matches the Xcode (ouro-ax-xray plan, then the XrayProbe template)
Not checked: An intent whose result other people see asks the person to confirm before it acts.
Why: Siri can run an intent from a misheard request; a confirmation stops a message or a share from going out by mistake.
Fix: Call
requestConfirmationbefore the intent sends, shares or posts anything other people see.needs a person: run these through Siri and Shortcuts and check each asks first, if others see or it cannot be undone: Delete Cook Log, Delete Cookbook, Delete Recipe, Disconnect Account Connection, Remove Profile Photo, Remove Recipe from Cookbook, Remove Shopping Item, Revoke Agent Access Key and 4 more
Not checked: Each intent appears under the app in Shortcuts, and its parameter summary reads like a sentence.
Why: People read and edit the summary; awkward phrasing cannot be found by a code-level test.
Fix: Give the intent a
parameterSummarythat reads as a sentence, such asSummary("Open \(\.$note)").needs a person: find the app's 59 intents in the Shortcuts action library and read each summary
Not checked: Siri calls the right intent with the right parameters for direct, indirect and incomplete wording, and declines unexpected requests.
Why: This is the outcome the metadata claims are for: Siri doing what the person asked.
Fix: Read the failing transcripts and sharpen the intent's title, description, parameter descriptions or app skill.
needs SiriEvaluations: the app's scenario set, run five times on a 27.3 beta OS on an Apple Intelligence device
Not checked: After an action, what Siri says names what happened.
Why: The person hears the outcome, not only a chime; a reply that names the result is the spoken receipt.
Fix: Return a result with a dialog or a value that names the outcome, such as
.result(dialog: "Added milk to Groceries.").needs SiriEvaluations: the app's scenario set, run five times on a 27.3 beta OS on an Apple Intelligence device
Holds: Every entity type has a display name a person would say, not its type name.
Why: Siri and Shortcuts name the kind of thing with it ("Recipe", "Note").
Fails: An entity exposes what a person would ask about it as properties.
Why: Siri matches requests to content through an entity's properties; an entity with none offers only its display text.
Fix: Add
@Property(title:)(withdescription:on the 27.3 SDK) for each fact a person would ask about: name, date, amount.- “Access Key” has no properties
- “Account Connection” has no properties
- “Capture Draft” has no properties
- “Chef Profile” has no properties
- “Cooking Step” has no properties
- “Cookbook” has no properties
- …and 4 more like it.
Not checked: Sensitive properties require authentication, and properties only the app needs are hidden from Siri.
Why: By default Siri and Shortcuts can show entity information without unlocking; financial or health data should not be.
Fix: Pass
authenticationPolicy: .requiresAuthenticationto sensitive properties andvisibility: .internalto app-only ones.needs a person: no entity exposes properties yet; review each one when it does
Holds: Siri can find every entity: it is indexed in Spotlight, or its query can list or search it.failed before
Why: Siri finds entities through Spotlight, an enumerable query or dynamic options; an entity it cannot find, it cannot act on.
Not checked: An entity that says it is indexed is in the Spotlight index once the app has content.
Why: Spotlight is the door to personal context: Siri answers from what the app indexed.
Fix: Call
CSSearchableIndex.default().indexAppEntities(_:)when content is created or changes, and on first launch.needs a behaviour run: AppIntentsTesting against the app on a device or simulator whose OS matches the Xcode (ouro-ax-xray plan, then the XrayProbe template)
Not checked: An entity's identifier resolves back to the same entity.
Why: Siri holds an entity by identifier between turns; one that does not resolve breaks a multi-turn request.
Fix: Make the query's
entities(for:)return every identifier its other methods hand out.needs a behaviour run: AppIntentsTesting against the app on a device or simulator whose OS matches the Xcode (ouro-ax-xray plan, then the XrayProbe template)
Fails: Every entity is
Transferable.Why: Siri moves content between apps ("email this recipe"), and Apple's testing guide treats a transferable representation as a requirement for every entity; one without it cannot go anywhere.
Fix: Conform the entity to
Transferablewith at least one representation other apps read, such as plain text or a file.- “Access Key” is not Transferable
- “Account Connection” is not Transferable
- “Cooking Step” is not Transferable
Not checked: An exported entity can be read back.
Why: Apple names a broken Transferable as the way multi-turn Siri requests and drag and drop silently fail.
Fix: Give the entity an importing representation, or a
ProxyRepresentation, that turns the exported data back into the entity.needs a behaviour run: AppIntentsTesting against the app on a device or simulator whose OS matches the Xcode (ouro-ax-xray plan, then the XrayProbe template)
Not checked: Each entity shows a title a person recognises, with a subtitle or image where it helps.
Why: The display representation is what the person sees in Siri, Shortcuts and Spotlight; code-level tests cannot read it.
Fix: Return a
DisplayRepresentation(title:subtitle:image:)built from the entity's own fields.needs a person: find each in Spotlight and Shortcuts and check its title, subtitle and image: Access Key, Account Connection, Capture Draft, Chef Profile, Cooking Step, Cookbook, Recipe, Shopping Item and 2 more
Not checked: Siri finds the entity the person means from their words.
Why: Finding the right recipe or note is most of the work in a request about it.
Fix: Index the entity's searchable text, describe its properties, and make its display title the name people use.
needs SiriEvaluations: the app's scenario set, run five times on a 27.3 beta OS on an Apple Intelligence device
Not checked: Entities shown on screen are annotated, so "this" means what the person sees.
Why: Onscreen context lets a person say "add this to my list"; without an annotation Siri cannot know what "this" is.
Fix: Add
.appEntityIdentifier(EntityIdentifier(for: entity))to each row or detail view that shows an entity, or setNSUserActivity.appEntityIdentifierfor a single one.needs a behaviour run: AppIntentsTesting against the app on a device or simulator whose OS matches the Xcode (ouro-ax-xray plan, then the XrayProbe template)
Not checked: Siri resolves "this" to the entity on screen.
Why: The annotation is for this moment: the person points at something and asks.
Fix: Annotate the views that show entities, and keep the selected one marked as selected.
needs SiriEvaluations: the app's scenario set, run five times on a 27.3 beta OS on an Apple Intelligence device
Holds: A skills bundle is
Skills.skillsbundleholding onlySkills/<name>/SKILL.md, one bundle per target.unchecked beforeWhy: Siri reads nothing else in the bundle, so anything else is dead weight or a sign of a misplaced file.
Holds: Each skill's name is lowercase letters, numbers and hyphens, the same in its folder and frontmatter, and unique across the app.unchecked before
Why: Two skills with one name leave the system to pick between them, and nothing says which it picks.
Holds: A skill's frontmatter holds only
nameanddescription.unchecked beforeWhy: App skills take a subset of the Agent Skills format; other fields are not read.
Holds: A skill's body is at most 10,000 characters and names tools informally, not by type.unchecked before
Why: Siri reads at most 10,000 characters, and knows tools by their titles, not their Swift names.
Not checked: Siri loads the skill for the requests it is written for.
Why: A skill Siri never loads is guidance nobody reads.
Fix: Make the skill's
descriptionname the requests it handles, in the words people use.needs SiriEvaluations: the app's scenario set, run five times on a 27.3 beta OS on an Apple Intelligence device
ouro-ax-xray 0.2.0 · claim set 0.1.0 · Xcode tools 27B52 · 2026-11-04
Siri AI
Tools and skills, ready for the new Siri.
Mark an intent as a tool and Siri AI can call it in the middle of a conversation. Give it a skill and Siri learns your app's way of doing a longer job, like cooking along with a recipe, step by step. The Siri AI parts need the Xcode 27.3 beta SDK, and until you build with it they compile to nothing.
@AppIntent(.tool)
struct StartCookAlong: AppIntent {
static let title: LocalizedStringResource = "Start cooking a recipe"
static let description = IntentDescription(
"Opens cook mode on the recipe's first step and reads it aloud."
)
@Parameter(title: "Recipe") var recipe: RecipeEntity
…
}The skills linter checks a skills bundle at build time, with errors pinned to the line, so a typo in a skill's frontmatter is caught before Siri meets it.
swift run ouro-ax-skills lint path/to/Skills.skillsbundleYour turn
X-ray your own app.
Build your app, point the X-ray at it, and get the same report you just browsed: Markdown for people, JSON for CI, and a page for everyone else.
swift run ouro-ax-xray --app path/to/App.app --out reportThat reads the metadata and lints the skills, right on your Mac. Add the behaviour stage when you're ready, and write a Siri scenario set for the parts only Siri can answer. The full recipe.
Ways of knowing
Three layers: claims, behaviour, and how it feels.
The X-ray checks what your app tells Siri. The other layers finish the picture: Ouro Reins lets an agent drive the app itself, headless, and Ouro Feel measures how it feels in a person's hand.
Claims held
AX X-ray (this page)
Does it say what it does?
Reads the built app's App Intents from outside and checks that its claims hold.
Behaviour
Reins
Does it do it?
Drives the screens as state and actions, headless, with the network blocked.
How it feels
Feel
Does it feel right while it does?
Walks the real app in a simulator and measures its jank, genre by genre.