The core pattern
Here’s the fundamental cycle:1
Snapshot
Capture the current UI state and assign refs to elements:
2
Interact
Use refs to click, type, or inspect elements:
3
Re-snapshot
After the page loads (or any UI change), take a fresh snapshot:
This pattern mirrors how humans use computers: observe → act → observe again. The snapshot gives you a moment-in-time view of what’s possible.
When to re-snapshot
You need a fresh snapshot whenever the UI changes significantly:After navigation
Browsers, settings panels, and multi-screen apps:After dialogs open
Dialogs, sheets, and popovers add new elements:After content loads
Dynamic content loading in browsers or document apps:When refs fail to resolve
If you get an error like this:Working with dynamic UIs
Dynamic interfaces require careful timing:Wait for changes to settle
After triggering an action, wait before snapshotting:wait command (from WaitCommand.swift) simply sleeps for the specified duration.
Check element state
Useget to read element values without re-snapshotting:
is to check boolean conditions:
Use —interactive for cleaner snapshots
Large apps have hundreds of structural elements. Focus on what matters:SnapshotCommand.swift:66-74:
Element resolution strategies
You don’t always need refs. agent-native supports two resolution strategies:Ref-based (snapshot first)
- Fast interactions after initial snapshot
- You see exactly what you’re clicking
- Refs work across multiple commands
- Requires a snapshot step
- Refs become stale when UI changes
Filter-based (direct search)
ElementResolver.swift:6-52, this searches the tree on-demand using filters:
- No snapshot needed
- Works with dynamic UIs where refs would be stale
- Good for one-off commands
- Slower (searches the tree every time)
- Less visibility into what exists
- Ambiguous if multiple elements match
For agent workflows, prefer ref-based resolution. It’s faster and gives your agent visibility into the full UI context.
Best practices
1. Start with an interactive snapshot
2. Use wait after UI-changing actions
3. Re-snapshot liberally
Whenever you’re unsure if the UI has changed, just snapshot again:4. Use —compact for complex UIs
5. Check snapshots in JSON for parsing
6. Handle ref resolution failures gracefully
Always be ready to re-snapshot if a ref fails:Example: Multi-step workflow
Here’s a complete example of opening a file in TextEdit:1
Open the app
2
Snapshot to see what's available
3
Click the File menu
4
Re-snapshot to see the menu
5
Click 'Open...'
6
Wait for the file dialog
7
Snapshot the file picker
See also
Accessibility tree
Understanding the tree structure
Refs and snapshots
Deep dive into the ref system