[控场AI]
· 10 分钟阅读· 5,149 字

用Claude Code与Android CLI做Agentic工程

用Claude Code与Android CLI做Agentic工程

开发者正转变为 Agent 团队管理者,核心是搭环境、控上下文、定完成标准。

文章基于 Google Android DevRel 团队的技术分享,提出开发者的角色正在从写代码转变为管理 Agent 团队。核心论点有三:其一,Agent 失败时应视为信息缺失的 bug,而非能力不足,因此需要为 Agent 搭建包含文档、架构规则、决策历史、真机与 profiler 的完整环境,Android CLI 提供了统一入口;其二,上下文存在甜点区,约 15 万 token 能兼顾能力与成本,需通过 Grill Me、spec 切片、逐 issue 执行等工作流控制窗口,agents.md 应控制在 250 行内且由团队统一维护;其三,工具层需分工明确——Hooks 提供确定性、Skills 按需加载、MCP 接外部服务、CLI 处理本地高频操作。最大收益来自预先定义「完成」标准:仅提供失败测试套件即可让 Android Bench 通过率从 22% 升至 90%。

开发者的角色正在变成「Agent团队管理者」

Google Android Developer Relations 的 Ben 和产品经理 Steven 在一场技术分享中给出了一个判断:开发者的角色正在改变,而且变化速度快到「这场演讲的内容可能已经过时」。他们用 Claude Code 演示,但强调这套方法论是 agent 无关的——它更接近一种思维方式,而非某个工具的使用技巧。

核心观点是:当 Agent 没能实现某个功能时,不要急着下结论说「AI 还做不到」,而应该反过来问——它缺了哪一块信息?把 Agent 的失败当成 bug 来对待,这正是那些做 Agent harness 的团队内部开发的方式。真正的生产力增益来自「并行运行多个 Agent」,而这要求你先为 Agent 搭好一个能自主成功、不需要你反复重新提示的环境。

环境:让 Agent 拥有你拥有的全部上下文

所谓「环境」,不只是给 Agent 访问代码的权限。演讲中列举的清单包括:准确的文档、项目 spec、项目规则、团队聊天空间(让 Agent 理解决策是如何做出的)、历史决策记录和 PR 评论,以及一台真机或模拟器。

「你不会指望在没有设备或模拟器的情况下写 Android 代码,那也不该指望 Agent 能做到。」同理,如果希望 Agent 优化性能,它需要能跑 profiler;如果 App 依赖后端服务,Agent 最好也能与之通信。

这正是 Android CLI 的定位。它是 Google 新的命令行工具,用于对接各类 Android 工具:SDK manager、启动模拟器、连接 Crashlytics 等后端。它本身不是 AI 产品,只是坐在你的 shell 里,因此可以配合任何 Agent 使用。

Crashlytics 发现的问题

他们用自研的网球应用 Sideline 做了实证。团队把 Firebase Crashlytics 接入开发环境后,发现了一个此前完全不知道的问题:某台折叠设备上出现 ANR,且在模拟器上无法复现。借助 Android CLI 的设备串流能力,Agent 自己连接到了出问题的那台设备上验证修复——而演讲者本人当时手上并没有这台机器。最终这是一个两行的修复,提 PR、合并、发版,1.0 构建中问题消失。

上下文:150K token 才是甜点区

一两年前行业在比拼上下文窗口大小,甚至有人尝试把整个 developer.android.com 塞进 prompt,结果并不理想。如今窗口大小基本停在 100 万这一量级,模型能力却仍在上升——Android Bench 的曲线显示,context window 已趋平,而模型能力持续攀升。

关键在于:上下文是固定预算。多数 Agent harness 并不把完整的百万窗口暴露给用户,因为结果反而更差。演讲给出的经验值是——把对话控制在约 15 万 token,能拿到模型全部能力且不出现 context rot。

上下文不只是你输入的内容。系统指令、工作区信息、已安装的 skills、MCP 工具、以及完整的消息与工具调用历史都会随每次 prompt 一起发送。Gradle 日志是这里的重灾区:又长又啰嗦,大部分内容无用。大厂 harness 会自动截断,但极简派 Agent(如 mini SWE agent)会把完整日志发给模型,成本上升极快。一个简单对策是用 Gradle 的 quiet 模式。

保持在这个窗口内的办法是工作流。演讲推荐了 Matt Pocock 的一系列 skills:先用「Grill Me」让 Agent 反过来向你提问,把模糊点从脑子里挤出来落到 issue 上;再生成 spec 文档并切片成多个 issue,每个 issue 大致能塞进 15 万 token 窗口;然后逐个 issue 执行「构建—验证—循环」,结束即清空上下文。

agents.md 的作用范围

agents.md 的取舍

agents.md 适用于「始终相关」的信息:架构与模块规则(比如 UI 组件属于 design system 模块)、常见的 code review 错误、团队反复强调的偏好。它应保持在 250 行以内。

一个反直觉的发现:有研究显示,让 Agent 自己修改 agents.md 会让性能下降约 2% 到 3%,但成本上升 20%。替代做法是让 Agent 在每次 PR 结束时写一份复盘,由团队在回顾会上统一决定如何修改。演讲者认为这个文件正在成为团队协作的关键基础设施。

另外,这类最佳实践随模型版本变化很快——曾经流行用大写字母写「NEVER do this」,后来 Anthropic 表示大写效果不再理想,改用小写即可。

Context rot 指的是当上下文窗口被填充到接近上限时,模型对其中信息的利用效率反而下降的现象——不是「装不下」,而是「装得下但用不好」。典型表现包括:对早期内容的注意力衰减、对无关噪声的过度敏感、以及指令遵循能力的退化。这也是为什么多数商业 Agent harness 不把完整的百万级窗口直接暴露给用户,而是通过自动截断、摘要压缩、工具结果裁剪等方式把有效上下文维持在可控范围内。文中提到的 Gradle 日志重灾区正是 context rot 的经典诱因:冗长且高度重复的日志会挤占有效信息的位置,同时拉低模型对关键信号的辨识度。因此「15 万 token 甜点区」并非模型能力的硬边界,而是信噪比与成本之间的经验平衡点。

工具层:Hooks、Skills 与 MCP 的分工

想改变 Agent 行为,不该什么都往 agents.md 里塞。

Hooks 用来加确定性。Agent 暴露了各类事件(会话开始/结束、读写文件等),你可以挂上脚本。比如「写完代码总是跑 linter」不必写成文字规则,而是一个 stop hook 跑确定性脚本;再比如对密钥文件加读写 hook,直接返回「不允许」。

Skills 用来按需加载上下文。它由名称、描述(限 1024 字符)和正文组成,正文可以非常大。Android CLI 的 skill 描述很短,正文却极长——只有真正要用 Android CLI 时才加载。这里有个安全提醒:不要盲目安装网上那些「100 个 agentic engineering skills」的仓库,一是你不知道里面写了什么,二是 100 条描述乘 1000 字符就是十万字符,代码还没开始写窗口就被吃掉一大块。推荐做法是只装 Android CLI 基础 skill,再由它按需搜索并安装合适的技能。

Skills 的安全风险

MCP 与 CLI 并非替代关系。CLI 快、可组合、在本地 shell 中运行几乎零成本,而且 TerminalBench 这类基准让模型对终端操作非常熟练。MCP 更适合接入已有的外部服务——GitHub、Figma、Slack 都提供了 MCP server,安装即用。而 Perfetto、Gradle、Android 命令这类一直跑在 shell 里的工具,留在本地更合理。

Android Profiler 命令在 Sideline 上的表现可以说明问题:应用要求实时 30 帧,实测只有 20 到 22 帧。Agent 用 profiler 录制了设备上的系统 trace,发现 AI 线程被调度到了最慢的核心上,还主动调用了 Android 文档搜索,拉取官方 Performance Hint API 的指导,最终优化系统调度达到 30 帧目标。

Agent harness 指包裹在模型之外、负责驱动 Agent 完成任务的运行时框架。它通常包含几个部分:系统提示与工具定义的组织、消息与工具调用历史的管理、工具执行与结果回传、上下文裁剪与压缩策略、以及权限与安全控制。同一个模型在不同 harness 下表现可能差异巨大——因为 harness 决定了模型看到什么、能做什么、失败后如何重试。文中反复出现的「大厂 harness 会自动截断」「极简派 harness 会把完整日志发给模型」,说的就是这一层的策略差异。理解 harness 的存在有助于解释一个常见困惑:为什么在某个产品里表现平平的模型,换一个 Agent 工具后能力显著提升——变的往往不是模型,而是它周围的这套脚手架。

验证循环:模型不缺能力,缺的是「完成的定义」

「让 Agent 实现一个大改动,它回来说做完了,你装上 App 手动点来点去,再把 bug 打回去」——这个循环必须停止。演讲者把这称作「不要再当 Agent 的 QA 测试员」。

典型反例是把整个项目迁移到 Navigation 3:Agent 自信宣布迁移完成,但旋转屏幕就崩溃,转场动画全丢了,Gradle 文件也没清理。问题不在能力,而在没有事先定义什么叫「完成」。

数据很能说明差距:在 Android Bench 上,某模型仅用「migrate nav2 to nav3」这类自然提示时通过率是 22%;而预先给它一套会失败的测试套件后,整体基准通过率跃升到 90%。注意这不是给答案——没有告诉它怎么迁移,只是给了验收标准。

验证循环带来的通过率提升

验证循环不必是完整测试套件。做 UI 时可以要求「渲染 Compose Preview,确认符合 Figma 规格,并把结果展示给我」——要求它拿出证据,而不是接受一句「我做完了」。做业务逻辑时跑单元测试;修崩溃时通过 Remote Test Lab 在真机上验证。

更有效的是分层验证:先跑最快的单元测试和 Compose Preview,通过后再跑 connected tests 与 Journeys,最后才跑耗时的完整远程设备测试。给出分层指令后,Agent 会逐层循环,而不是每一步都在每一轮重跑。

在 Sideline 上新增 XR 眼镜形态的演示里,这个效果很直观:第一轮到第二轮之间,JVM 测试定义了六个 Compose Preview 状态,完全没调用模拟器,速度很快;第二轮和第三轮之间,长字符串之类的布局问题在模拟器启动前就被发现并修好;等到模拟器循环跑起来,才暴露出前两层无法覆盖的问题。每一层循环都在加固应用,顺序是先快后慢、先弱后强。

最后,配合 Claude Code 的 schedule 命令可以设定任意节奏,让两个遗留的 Crashlytics 崩溃问题被自动修复、自动验证、以 PR 形式提交——形成一个能自愈的应用。

Android Bench 是 Google 针对 Android 开发任务构建的基准测试集,用于衡量模型在真实工程场景中的表现,任务涵盖导航迁移、性能优化、崩溃修复等。它区别于通用代码基准的地方在于:任务运行在接近真实的 Android 项目环境中,评判标准是构建是否通过、测试是否绿灯、运行时行为是否符合预期,而非单纯的代码相似度。文中的 22% 与 90% 对比之所以有说服力,正是因为基准本身就内建了可执行的验收信号——当提示中附带会失败的测试套件时,模型获得的不是「答案」,而是「什么叫成功」的可验证定义。这也解释了为什么「写你自己的 eval」被演讲者列为核心建议:通用基准只能反映平均能力,而团队真正的瓶颈往往在特定代码库与特定工作流上。

实践建议

演讲者的总结只有一句:开始像对待软件开发一样对待 Agent 环境的搭建。网上的建议彼此冲突很正常,最好的办法是写你自己的 eval,用数据判断它是否真的有效。

一个值得注意的细节是:Sideline 的 agents.md 里刻意保留清晰的架构定义,因为它既省 token 又省上下文长度——Agent 不必反复翻查代码库做推断。对闭源应用来说,由于 LLM 无法从公开代码中学习你的架构,持续维护 agents.md 的回报更高。

#Agentic Engineering#Claude Code#Android CLI#AI 编程#agents.md#验证循环#Android Bench
分享:

相关推荐