← 返回文章归档

把任务状态从屏幕里拆出来:TSR 给长程移动端 GUI Agent 挂了一个外置状态机

解析 TSR(Task-State Representation,2026-07-01):它不改 agent、不训模型,而是在固定的 GUI actor 外面挂一个训练无关的状态更新器,用动作前后两张截图对比,持续维护任务摘要、进度追踪和动作校验三块结构化状态。对做 APP 自动化测试的人,这篇最值钱的地方不是又涨了几个点,而是它把长程用例里最难的三件事——目标漂移、进度幻觉、界面延迟导致的死循环——拆成了三个可单独维护、可单独消融的字段。

#GUI Agent#Computer Use#Mobile Agent#Long-Horizon#APP 自动化测试

论文:A Task-State Representation for Long-Horizon Mobile GUI Agents arXiv:2607.00502v1,2026-07-01(10 页,3 figures,4 tables) 作者:Yujie Zheng、Zikang Liu、Xin Zhao、Ji-Rong Wen(中国人民大学高瓴人工智能学院 / 北航软件学院) 一句话结论:TSR 把长程移动端 GUI Agent 一直含糊处理的”任务状态”从”一堆历史截图和思考日志”里显式拆出来,做成一个训练无关、挂在固定 actor 外面的外置状态对象。它真正推进的不是榜单成绩,而是把”agent 到底走到哪一步了”这个隐式假设,落成了三个可维护、可注入、可单独消融的结构化字段:全局任务摘要、进度追踪、动作校验。对做 APP 自动化测试的人,这篇的价值在于它给出了一个不碰底座模型就能加的”用例执行状态机”雏形,并且很诚实地说明了它什么时候会帮倒忙。

大多数长程 GUI Agent 论文在比”谁能把跨应用任务做完”。TSR 关心的是一个更结构性的问题:现在主流的 thought-action-observation 循环,把两类完全不同的信息塞进了同一个 prompt——一类是持久任务状态(用户到底要什么、已经完成了哪些子目标、还剩几步),一类是瞬时观测状态(当前这一屏显示了什么)。这两类东西混在一起,随着轨迹变长,actor 就得在每一步都从原始历史里重新”推导”自己走到哪了,这个负担是随轨迹长度线性增长的。

这个缺口对做移动端自动化测试的人其实很熟。一条跨页面、跨应用的长用例跑到中段挂掉时,我们最想先分清的是:它是忘了原始目标(点着点着跑偏了)、误判了进度(以为某步做完了其实没有)、还是被界面延迟骗了(点了一下界面没及时刷新,脚本以为失败,又点一遍,陷入局部死循环)。TSR 把这三种失败明确命名成 goal drift、progress hallucination、stale-screen repetition,并且给每一种都对应了一块专门维护的状态字段。这种”把失败模式和状态字段一一对上”的做法,比很多只报成功率的论文更贴工程。

这篇论文在 GUIAgent 谱系里的位置

放到 AndroidWorld / MobileWorld / MemGUI-Bench / VenusBench-Mobile 这条移动端评测线里,TSR 不是再造一个 benchmark,也不是又训一个更强的执行 actor。它站在这些环境之上,做的是长程上下文管理这一层的活。

和它最近的一批工作是轨迹压缩:HiAgent 按子目标切分工作记忆,IterResearch 周期性重建一个精简的工作区,还有一批用 RL 学”怎么把历史摘要短”的方法。作者的判断很直接——这些方法本质上都是把整条轨迹当成一条要被压短的单一数据流来处理。TSR 换了个思路:它不压缩历史,而是在 actor 那条没被改动的观测历史旁边,单独维护一个结构化的状态对象。历史该多长还多长,状态另开一份。

这个区别落到工程里其实很关键。测试脚本里我们早就知道”当前 UI 状态”和”业务/用例进度”要分开管:前者是页面上看得到的东西,后者是断言链和步骤计数器。TSR 相当于把这套”UI 观测 vs 用例进度分离”的老经验,搬到了 LLM-based agent 的 prompt 结构里。

图 1:TSR 框架总览。上半部分是标准 GUI actor——把指令、最近几屏截图、历史思考和动作全塞进一条会持续膨胀的原始轨迹,持久状态和瞬时观测混在一起。下半部分是 TSR 的做法:状态更新器 U_φ 对比动作前后两张截图,更新一个包含全局任务摘要、进度追踪、动作校验三块的结构化状态块 S_t,再序列化注入回 actor 的输入。actor 本身完全不变。

图 1 把这套结构讲得很清楚。左边是共享的任务输入(指令 + 当前和最近几屏截图),右上是没被动过的标准 actor,右下是 TSR 挂上去的那块外置状态。注意一个细节:actor π_θ 全程固定,整个机制都在推理时外部运行,不需要任何训练或架构改动。这是它自称 “training-free” 的底气,也是它能当”通用外挂”的前提。

核心思路:一个外置状态,三块功能视图

TSR 的定义很干净。它维护一个外部状态 S_t,在每一步动作后由状态更新器更新,再注入回 actor。状态由三块功能视图组成——注意这三块不是三个独立模块,而是同一个状态对象里的三个字段,每步一起更新:

Global Task-State Summary(全局任务摘要)。当早期的视觉上下文被截断(为省 token,系统通常只保留最近 m 张截图),actor 容易丢掉最初的任务目标。这块摘要专门记录任务的持久语义 + 累积进度,保证哪怕最近几屏只显示了界面的一个很窄的切片,原始指令始终可见。对应的失败模式就是 goal drift。

Progress Tracker(进度追踪)。长程复杂任务里,agent 经常搞不清自己的总目标进行到哪了。这块追踪器把任务拆成原子级需求,维护四个字段:任务分解、已完成里程碑、当前子目标、剩余需求。把”已核实的进度”和”未解决的步骤”都写明,就压住了 actor 幻觉出根本没发生过的历史观测、或者提前判定任务完成的风险。对应 progress hallucination。

Transition-Aware Focus(动作校验/转移感知)。因为历史 H_{t-1} 反映的是过去的意图而非环境反馈,actor 在系统延迟或失败时容易陷入重复循环。这块视图通过对比 o_{t-1}o_t 两张观测来评估上一个动作的效果:如果结果不确定,它不让 actor 盲目重试,而是生成一个”下一步聚焦”——比如先去核实状态、或者下拉刷新一下列表——引导 actor 的下一个决策。对应 stale-screen repetition。

这里有个工程上很值得抄的点:动作校验的信号来自截图对比,不是来自 actor 自己的文字判断。actor 说”我点了删除按钮”,这只是它的意图;TSR 拿动作前后两张截图去看界面到底变没变,才是环境反馈。这正好是自动化测试里 oracle 设计的核心分歧——你到底信脚本”以为做了什么”,还是信”界面/后端状态实际变成了什么”。

方法拆解:状态更新的单次函数调用

整套系统的更新逻辑就一个函数。任务开始时,初始状态 S_0 只从任务指令 I 推导。此后每一步,在 actor 执行完动作 a_{t-1}、环境产出观测 o_t 之后,状态更新器 U_φ 吃进五样东西——任务指令、上一步状态、上一步 actor 响应、动作前截图、动作后截图——通过一次函数调用产出更新后的状态:

S_t = U_φ(I, S_{t-1}, r_{t-1}, o_{t-1}, o_t)

U_φ 由一个 prompted LLM 实现,输出一个包含全部三块视图的结构化 JSON。然后 actor 拿到的是标准上下文再加上这块序列化状态:

a_t = π_θ(I, O_t, H_{t-1}, I(S_t))

其中 I(S_t) 是把三块视图格式化成一段文本块,追加到 actor 的 prompt 后面。关键还是那句话:π_θ 全程不变。

说白了,TSR 就是在每步之间插了一个”状态维护 LLM 调用”,它读前后两屏 + 上一步状态,吐出一份更新过的结构化进度单,再喂回执行 agent。这个设计的代价也很直白:每步多一次 LLM 调用(论文说约 1024 tokens),延迟和成本都涨。这一点后面局限性会再谈。

实验结果:涨点集中在真正的长程任务上

作者用两个底座模型(Qwen3.5-plus、Kimi-k2.5)在四个在线移动 GUI benchmark 上评测。看 Table 1 的主结果,有几个判断值得单独拎出来。

表 1:TSR 主结果。两个底座模型 × 四个 benchmark 的成功率(SR)对比,以及平均步数。最大涨幅出现在 MobileWorld(Qwen3.5-plus +12%、Kimi-k2.5 +9%),但在 AndroidWorld 上 Qwen3.5-plus 反而掉了 3.45%。

第一,最大涨幅集中在轨迹最长、跨应用依赖最强的 benchmark 上。 MobileWorld 上 Qwen3.5-plus 从 43.00 涨到 55.00(+12%),Kimi-k2.5 从 49.00 到 58.00(+9%)。这个 benchmark 的平均轨迹最长,正好印证了作者的假设——显式进度追踪在 agent 要走很多步的时候最有用。在偏记忆、偏用户中心的 benchmark(MemGUI-Memory、VenusBench-Mobile)上,两个模型也都有 +3.48% 到 +5.22% 的收益。

第二,它不是普适正收益,这一点论文写得很诚实。 Qwen3.5-plus 在 AndroidWorld 上掉了 3.45%,而 Kimi-k2.5 在同一个 benchmark 上涨了 3.45%。作者的解释是:结构化任务状态追踪的效用,取决于底座模型自身的规划能力和任务复杂度分布。换句话说,给一个本来就短、本来就单应用的任务硬套一个长程状态机,反而是噪声。

第三,更高的成功率不一定要更多步数。 有几个配置里(Kimi-k2.5 在 VenusBench-Mobile:41.2→38.3 步;Qwen3.5-plus 在 MemGUI-Memory:65.4→64.5 步),TSR 让任务完成得更直接。而在 MobileWorld 上步数是随成功率一起涨的,说明这里 TSR 帮 agent 熬过了那些它原本会中途放弃的复杂任务。这两种模式对测试很有意义:一种是”少走冤枉路”,一种是”熬过了原本会超时放弃的用例”。

消融:三块视图是协同的,动作校验最关键——但也最会翻车

作者在 Qwen3.5-plus 上做了消融,分别去掉三块视图(内部状态仍然更新)。这张表是全文我最看重的部分,因为它暴露了方法的边界。原表(论文 Table 2)关键行如下:

方法MobileWorldAndroidWorld
Baseline43.0061.21
+Context w/o summary(去掉摘要)50.0059.48
+Context w/o tracker(去掉进度追踪)49.0061.21
+Context w/o transition(去掉动作校验)48.0063.79
+Context full(完整 TSR)55.0057.76

(数据来自论文 Table 2,Success Rate %)

在 MobileWorld(长程)上,完整 TSR 比任何一个去掉一块的变体都高 5–7%,说明三块视图是协同起作用的;而单独去掉动作校验(transition)造成的下滑最大(55→48),说明校验动作是否真的生效,是长程任务里最关键的信号

但到了 AndroidWorld(偏短、偏单应用),整个模式反过来了:去掉动作校验反而比 baseline 更好(63.79 vs 61.21),而完整 TSR 反倒掉到 57.76。作者的解释很到位——对短程单应用任务,转移校验引入了不必要的决策噪声。所以 TSR 应该被理解成条件性有效,最值钱的场景是那些需要跨很多步持续追踪状态的任务。

这个消融结论如果照搬到测试工程,直接对应一条经验:逐步做视觉校验(每一步都对比前后截图判定成败)在长链路端到端用例里是刚需,但在短小的单页面回归用例里可能是过度设计,反而增加误判。什么用例值得挂重校验,什么用例挂了反而添乱,这本身就是测试策略要回答的问题。

两个案例:一个救回来了,一个帮了倒忙

论文用两张图讲了 TSR 在真实轨迹里的两面。

图 2:Stale-screen recovery(界面延迟恢复)。baseline 在一个书签删除任务里,因为界面延迟刷新,反复对同一个"删除"动作点了又点(Step7→Step10 一直在点三点菜单和 Bookmark 选项),陷入死循环;TSR 的动作校验检测到"删除后 pupper 帖子仍在列表里(UI 可能需要刷新)"这个不确定转移,把 actor 引导去"下拉刷新列表核实",而不是盲目重试。

图 2 是那个救回来的例子,也几乎是每个写过移动端自动化用例的人都踩过的坑:点了删除,列表因为异步刷新还没更新,脚本以为没删掉,又去点一遍,结果把状态点乱了。TSR 的做法是把”上一步结果不确定”这件事显式写进状态(Last Step Result: pupper 帖子仍可见,UI 可能需要刷新),然后生成一个明确的下一步聚焦——下拉刷新去核实——而不是重试删除。这正是自动化测试里”等待/重试/刷新策略”要解决的经典问题,只不过 TSR 把它交给了一个读截图的状态更新器来判断。

图 3:Over-decomposition failure(过度分解失败)。在一个"找出上个月所有美食照片并按 Tokyo/Paris 分类"的任务里,状态更新器把任务拆得太细,导致 actor 逐张检查照片元数据(一张张点开看拍摄日期),而不是用全局视觉推理批量判断,最终超出步数预算。

图 3 是帮倒忙的例子,也是这篇论文难得的自黑。进度追踪器把”分类美食照片”这个任务拆成了”逐张核实每张照片的拍摄日期”,于是 actor 老老实实一张张点开看元数据,而本来靠一眼看缩略图就能大致分类。结果是步数爆掉。作者由此给了一句很克制的结论:任务状态表示应该被当成”引导”,而不是对当前屏幕证据的”覆盖”。当结构化状态和眼前的视觉证据冲突时,不该让状态盖过视觉。

这一条对测试工程同样是警告:如果你给 agent 塞了一份过度细化的检查清单,它可能会机械地逐项核验,反而放弃了本可以一次性判断的捷径。断言/oracle 的粒度不是越细越好。

对 APP 自动化测试的启发

抛开榜单,TSR 的结构对做移动端 QA 的人有几个能直接借鉴的点:

一,把”用例进度”从”UI 观测”里拆出来单独维护。 现在很多基于 LLM 的自动化探索/用例生成 agent,还是把整条操作历史一股脑塞进上下文。TSR 证明了单开一份结构化的进度对象(已完成子目标 / 当前子目标 / 剩余需求)能显著改善长链路稳定性。落到 Appium/Maestro/UIAutomator 之上做的智能编排层,这份进度对象可以直接映射成用例的步骤状态机。

二,步级校验优先用视觉转移,而不是 actor 自述。 TSR 的动作校验靠对比前后截图,而不是信 agent 说”我点成功了”。这对应测试里一个老争论:oracle 到底看 UI 状态、业务状态还是日志。TSR 给的答案偏视觉转移——至少在纯截图型 agent 场景下,前后帧对比是比文字自述更可靠的步级 oracle。工程上可以再往上叠:视觉转移 + 后端状态校验 + 网络请求核对,构成多层断言。

三,校验策略要按用例长度分级。 消融结论很清楚:长链路端到端用例值得每步做视觉校验,短小单页面回归用例挂上反而添噪声、增延迟。这直接对应测试策略里”哪些用例值得重校验、哪些不值得”的分级。

四,警惕过度分解。 图 3 的失败提醒我们:自动生成的检查清单如果拆得太碎,agent 会机械逐项核验,丢掉批量判断的捷径。测试生成里,断言粒度和步骤分解粒度需要有个上限。

局限性与点评

论文的 Limitations 写得比较实在,几个点值得原样搬过来:

  • 状态更新器会传播错误。 如果 U_φ 错误地把某个子目标标成已完成、或漏掉一个剩余需求,actor 就会基于一个有缺陷的状态继续决策,错误会跨步累积。这是所有”外置状态机”方案的通病——状态本身错了,比没有状态更危险。
  • 每步多一次 LLM 调用(约 1024 tokens),延迟和成本都涨。对本来 baseline 就能成功的短任务,这份开销是纯负担,还可能因为过度分解拖累性能。
  • 只在 Android 系移动 benchmark 上验证过,能不能推广到桌面或 Web GUI 环境,论文没测。
  • 三块视图目前是每步一起更新的,作者自己也承认更聪明的做法是按需激活——只在需要时才启用某块视图,以降低简单任务上的噪声。

补充几点我的判断。真正贡献上,TSR 最有价值的不是那 +12% 的数字,而是它把”长程 agent 的隐式状态”显式化、结构化,并且做到了训练无关、可即插即用。三块视图对应三种失败模式的映射是清晰的,消融也支持”三块协同”的说法。

可能被高估的部分:第一,收益高度依赖底座模型和任务分布——AndroidWorld 上 Qwen 掉点、Kimi 涨点这种相反结果,说明这套方法离”稳定通用外挂”还有距离。第二,baseline 是作者自己按前人工作复现的标准 actor,论文没有和其他上下文管理方法(HiAgent、IterResearch 等)做直接的成功率对比,所以”比轨迹压缩类方法更好”目前更多是定性论述而非实测。第三,状态更新器本身是个 prompted LLM,它的可靠性、JSON 输出的稳定性、以及错误传播的实际发生率,论文没有量化,而这恰恰是落地时最需要知道的。

可复现/可落地建议:如果要在自动化测试里试这套思路,值得先复现的是”动作校验用前后截图转移”这一块——它对应步级 oracle,单独就有价值,而且不依赖整套状态机。进度追踪和任务摘要可以先做成可选,按用例长度开关。同时一定要监控状态更新器的错误率,给它加一个”状态与当前屏幕证据冲突时以视觉为准”的兜底规则,正好对应图 3 的教训。

总结

TSR 做的事情说白了很朴素:把长程移动端 GUI Agent 一直混在历史里的”任务状态”拿出来,单独挂一个训练无关的外置状态机,用截图转移持续维护任务摘要、进度追踪和动作校验三块。它不改模型、不训 actor,在长程跨应用任务上拿到最高 +12% 的成功率,在短任务上则可能帮倒忙——而且论文很诚实地把这个边界、这个失败案例、这个成本都摆了出来。

对做移动端自动化测试的人,这篇论文最该带走的不是那个数字,而是三条可操作的经验:用例进度要和 UI 观测分开维护、步级校验优先用视觉转移而非 agent 自述、校验和分解的粒度要按用例长度分级——以及一条兜底:结构化状态是引导,不是对眼前屏幕证据的覆盖。

参考链接