Shortcut catalogs help phone agents until they grow: a full deeplink list cut Qwen3.7-Plus from 61.5% to 53.0%
GUI-Hopper jumps with verified deeplinks, PhoneCLI replays compiled navigation. Both run on Qwen3.7-Plus, both peak at a middle catalog size, and both depend on a landing check that phoneshell's own deep-link step does not have.
Given the full catalog of verified deeplinks for MobileWorld's apps, an untrained Qwen3.7-Plus agent succeeded on 53.0% of 351 runs, against 61.5% with no deeplinks at all. Three days later a second paper, on the same backbone, found the same shape for compiled navigation commands: growing its app map from 50 to 100 screens dropped Settings from 95.7% to 78.3%. The papers are GUI-Hopper (arXiv:2609.30887, 25 September 2026, Tongyi Lab and Shanghai Jiao Tong University) and PhoneCLI (arXiv:2609.35671, 28 September 2026, University of Hong Kong).
What the two papers built
GUI-Hopper mines Android deeplinks from app manifests and shortcut definitions, drops components that are not exported, checks each candidate resolves, then opens it on a real device and keeps only entries that land on a meaningful screen. For 26 apps in MobileWorld-Real that yields 1,251 callable entries, 246 of them with parameters; Bilibili alone has 330. One map app's search screen was reachable through 11 entries across 5 domains and 3 URI schemes before deduplication. A Qwen3.5 model is then trained on hybrid trajectories (deeplink or GUI action) with online RL, and at run time a retriever hands it at most 10 candidates. After each call the runtime checks that the landing Activity matches the one recorded in the catalog.
PhoneCLI crawls each app offline, breadth first, up to 50 screens and depth 3, and
compiles every screen into a replayable command. Across AndroidLab's 9 apps that is 320 screens, 2,822
elements, 1,089 navigation edges and 2,017 operations, about ten minutes per app. Online, a router picks
a command, a verifier approves it, the app is force-stopped and the recorded taps replay with no model
call, then a landing check confirms the screen. The paper's own example replays
force_stop | launch | tap(548,1428) | tap(496,874). Any failure hands control to the plain
VLM agent.
| Setting | Benchmark, runs | Without shortcuts | With shortcuts | Our count and test | Source |
|---|---|---|---|---|---|
| Qwen3.7-Plus, untrained, deeplinks task-matched | MobileWorld, 117 tasks x 3 | 61.5% | 62.4% | 216 vs 219 of 351 | GUI-Hopper Table 4 |
| Qwen3.7-Plus, untrained, top 10 retrieved | MobileWorld, 117 x 3 | 61.5% | 59.5% | 216 vs 209, p 0.64 | GUI-Hopper Table 4 |
| Qwen3.7-Plus, untrained, full catalog | MobileWorld, 117 x 3 | 61.5% | 53.0% | 216 vs 186, p 0.027* | GUI-Hopper Table 4 |
| GUI-Hopper 9B, top 10 retrieved | MobileWorld, 117 x 3 | 56.7% | 63.5% | 199 vs 223 | GUI-Hopper Table 4 |
| Qwen3.5-9B, GUI-only training vs hybrid | MobileWorld-Real, 119 tasks | 77.1% | 86.6% | not reported per task | GUI-Hopper Table 2 |
| Qwen3.7-Plus, VLM-only vs PhoneCLI | AndroidLab, 138 tasks x 1 | 50.7% | 63.0% | 70 vs 87, p 0.052 | PhoneCLI Tables 1 and 2 |
| Qwen3.7-Plus, map as text only (no replay) | AndroidLab, 138 x 1 | 50.7% | 55.1% | 70 vs 76 | PhoneCLI Table 2 |
| Kimi-K3, VLM-only vs PhoneCLI | AndroidLab, 138 x 1 | 68.8% | 69.6% | 95 vs 96 | PhoneCLI Tables 1 and 2 |
| M3A on Qwen3.7-Plus, with PhoneCLI routing | AndroidWorld, 116 x 1 | 61.2% | 65.5% | 71 vs 76, p 0.59 | PhoneCLI Table 4 |
Counts are the reported rate times the number of runs, rounded; p values are our two-sided Fisher exact tests. *The MobileWorld runs are three per task, so treating 351 runs as independent overstates the evidence; per-task results are not published. PhoneCLI reports its gains as significant with a test it does not name; unpaired, 87 against 70 of 138 gives p 0.052, and a paired test needs per-task outcomes the paper does not print.
Both papers found an optimum catalog size, and it is not the largest
With task-matched deeplinks, untrained Qwen3.7-Plus barely gains in success (61.5% to 62.4%) but takes about 16% fewer steps (25.6 to 21.4 on average). Widening the offer to the retrieved top 10 costs 2 points; the full catalog costs 8.5. GUI-Hopper's trained 9B model holds 62.8% to 63.8% across the same three supplies, which is the paper's argument for training. Note the other reading of the same table: the trained 9B with retrieved deeplinks (63.5%) is 2 points above the untrained Qwen3.7-Plus with none (61.5%), 223 against 216 of 351 runs.
PhoneCLI measured map size directly on two apps. Settings went 87.0%, 95.7%, 78.3% at 10, 50 and 100 screens; Clock went 63.0%, 77.8%, 66.7%. The catalog the router reads grows from about 130 tokens at 10 screens to 3.5k at 100, and the authors attribute the fall to mis-routing among more, noisier candidates. Neither paper frames it this way, but the two curves describe one mechanism: the shortcut is deterministic, the choice of shortcut is not, and the choice gets harder with every entry.
PhoneCLI's "can only help" holds only while every check works
The abstract says compilation "can only help" because every failure falls back to the plain agent, which is the VLM-only baseline. The paper's own ablation does not bear that out as a guarantee. Removing any one of five mechanisms lands at or below the 50.7% baseline: no landing check 50.7% (70 of 138), no landing hint 50.0% (69), no command completion 48.6% (67), no semantic enrichment 47.8% (66), no element classification 47.1% (65). Those are 0 to 5 tasks, inside single-run noise (65 against 70 gives p 0.63), so they do not show the layer hurts either. They show the floor is a property of the checks, not of the design. On Calendar, the map injected as text collapsed success to 0 of 14; replay recovered 4 of 14.
The fallback also assumes a reset that a real phone does not give. PhoneCLI's runs restore a clean
emulator snapshot before every task, and a failed landing check calls Restart(app) before
handing over. On a user's phone a force-stop discards whatever was typed but not saved, and it undoes
nothing already sent. The replayed taps are element centres stored as normalised screen positions and multiplied out to
pixels at run time, which survives a change of resolution but not a change of layout; every run in the
paper uses one Pixel 7 Pro emulator on Android 13.
What it means for an agent on an iPhone
The instruction phoneshell gives every model, rule 5, is "Prefer phone_open_app and phone_open_url over tapping your way through the home screen. A deep link is one deterministic step instead of five fragile ones." Both papers agree the step is deterministic. Both also show the choice of link is where the failures move, and both verify every catalog entry on a device before a model sees it. phoneshell has no catalog: the model types a URL it remembers. That is GUI-Hopper's untrained condition with an unverified supply, which the paper did not test and we have not measured.
Our landing check is weaker than either paper's. actions.py treats an
open_url as successful if the foreground bundle id changed or the screenshot differs by more
than 2% after 1.6 seconds. A link that opens the right app on the wrong screen passes. In replayed
macros the gap is wider: the recorder stores open_url steps with no anchor and no expected
text, and none of its seven recording calls ever sets expect. Tap, type and picker steps do
carry an anchor, so a wrong landing is caught at the next tap, if there is one, not at the link. PhoneCLI measured what
removing the landing check costs on its benchmark: 12.3 points.
As far as we know, iOS offers no equivalent of Android's exported-component list that an outside tool can enumerate on an unmodified phone. Custom URL schemes are declared in each app's Info.plist and universal links in the developer's apple-app-site-association file, so a mining pipeline like GUI-Hopper's would start from app bundles and web domains, not from the device. We have not built one. The cheaper fix is on our side: a landing check that compares the screen reached to an expected element, which is what both papers already do.
Check it yourself
- GUI-Hopper:
https://arxiv.org/abs/2609.30887; Table 4 (deeplink supply), Table 2 (MobileWorld-Real), Appendix A and Table 5 (catalog of 1,251 entries). - PhoneCLI:
https://arxiv.org/abs/2609.35671; Tables 1 to 4, Section 3.4 (map budget), Appendix A.1 (map statistics). The paper linkshttps://github.com/HKUDS/OpenPhone. - Our tests:
scipy.stats.fisher_exact([[216,135],[186,165]])gives p 0.027;fisher_exact([[87,51],[70,68]])gives 0.052;fisher_exact([[76,40],[71,45]])gives 0.59. - phoneshell:
grep -n "def open_url" -A 28 phoneshell/actions.py;grep -n "recorder.record(" phoneshell/mcp_server.py;grep -n "5\. Prefer" phoneshell/mcp_server.py.
What would prove this wrong
Two predictions, dated 31 March 2027. First, any follow-up that offers an untrained agent a verified
shortcut catalog at two or more sizes on the same tasks will again find the largest size below the
best size by at least 5 points. A result where success rises monotonically with catalog size, on a
catalog of at least 500 entries, would show the routing cost can be engineered away without training.
Second, when phoneshell adds a landing check that asserts an expected element after
open_url, the share of deep-link steps that report success but land on the wrong screen
will be above zero on our 80 tasks; if it is zero, the weakness described here is theoretical on this
suite.
Sources
- Sun, Cai, Zhang et al. (Tongyi Lab, Alibaba; Shanghai Jiao Tong University), From Tapping to Hopping: Augmenting Mobile GUI Agents with App-Native Deeplinks, arXiv:2609.30887, submitted 25 September 2026
- GUI-Hopper HTML edition: Table 1 (MobileWorld), Table 2 (MobileWorld-Real), Table 4 (deeplink supply), Appendix A (catalog of 1,251 entries)
- Jiang, Xu and Huang (University of Hong Kong), PhoneCLI: From App Interfaces to Callable Commands for Mobile Agents, arXiv:2609.35671, submitted 28 September 2026
- PhoneCLI HTML edition: Tables 1 to 4, Section 3.4 (map budget), Appendix A.1 (map statistics)
- HKUDS/OpenPhone, the repository the PhoneCLI paper links
- phoneshell actions.py open_url and agent/macros.py replay, read 29 September 2026