MISSION 05 · 出任务TASK 22

Android 工程师的落地

前面都是通用原理,这一章专门写给你——一个 Android 工程师。Agent 落到你身上是两件事:一是用 Agent 帮你开发(改你的工作流),二是在 App 里接一个 Agent(改你的产品)。两件事的架构考量很不一样,尤其后者有几个移动端特有的坑,踩了就是上架事故。

开发工作流App 内接入后端代理密钥安全Kotlin

第一件事:用 Agent 帮你开发

这是见效最快的一步,今天就能用上。把编码 Agent(第二十一章)接进你的 Android 项目,它对你这行的价值点很具体:

  • 啃陌生代码库:接手一个祖传模块,让它 grep + 读文件帮你画出「这个功能从 UI 到数据层的调用链」,比你自己翻快得多。
  • 写测试与样板:补 ViewModel 的单元测试、生成 data class 和序列化、写 Compose 预览——这类有明确对错、又枯燥的活,是 Agent 的甜点区(有 ./gradlew test 当判官)。
  • 迁移与重构:XML 布局迁 Compose、Java 转 Kotlin、升级 API——让它一个文件一个文件做,每步跑编译验证。
  • 查报错:把一段 stack trace 丢给它,让它 grep 定位、给出根因假设。
要点

让它对你的项目更好用的一次性投资:在仓库根目录放一份 约定文件(如 CLAUDE.md),写清楚——模块结构、用的架构(MVVM/MVI)、测试怎么跑(./gradlew testDebugUnitTest)、代码风格、绝对不能碰的东西。这就是第十一章的「文件即记忆」:你写一次,它每次进项目都自动加载,少走无数弯路。这比你每次在对话里重复交代高效得多。

第二件事:在 App 里接一个 Agent

这是产品层面的落地,也是坑最多的地方。先说那条最重要、不容商量的架构铁律:

✋ 铁律

永远不要把 API key 放进 App。Android App 是发到用户手机上的,APK 可以被反编译,任何硬编码的密钥——藏在 BuildConfigstrings.xml、native 层、还是用 ProGuard 混淆过——都会被扒出来。密钥一泄露,别人就能拿你的账号疯狂调用,账单算你的。Agent 的循环和密钥,必须待在你的后端

所以正确架构是:Agent 跑在后端,App 只是它的一个界面。App 把用户请求发给你的后端,后端持有密钥、跑第三章那个循环、执行工具,把结果流式返回给 App。客户端从头到尾不碰模型 API、不碰密钥、不跑循环

▸ Android 类比

你早就懂这个模式——它就是你对待任何第三方付费 API 的方式。你不会把支付网关的 secret key、或推送服务的 server key 打进 App,而是让 App 调你自己的后端,后端再拿着密钥去调第三方。Agent 完全一样:把模型 API 当成一个「贵且带密钥的第三方服务」,后端是你的 BFF(Backend for Frontend),App 只跟你自己的后端说话。唯一的新东西是——这次后端里跑的是一个会循环、会调工具的 Agent,而不是一次性的转发。

客户端要做的事:收发 + 流式渲染

App 侧的活很轻:发请求、把流式返回的 token 一段段渲染出来(别等全部生成完才显示,那体验很差)。骨架大致这样:

Kotlin · 客户端只跟自己的后端说话
// App 调用的是你自己的后端,不是模型厂商,更不带任何密钥
interface AgentApi {
  @POST("/agent/chat")
  @Streaming                              // 流式:边生成边显示
  suspend fun chat(@Body req: ChatRequest): ResponseBody
}

class AgentRepository(private val api: AgentApi) {
  fun send(text: String): Flow<String> = flow {
    val body = api.chat(ChatRequest(message = text))
    body.charStream().buffered().useLines { lines ->
      lines.forEach { line ->               // 后端用 SSE 逐块推
        if (line.startsWith("data:"))
          emit(line.removePrefix("data:").trim())
      }
    }
  }.flowOn(Dispatchers.IO)
}

// ViewModel 里把 Flow 收集进 UI state,Compose 自然重组显示

后端那半(跑循环、执行工具、SSE 推流)就是第十五章那段 TypeScript/Kotlin 循环,只是把最终结果换成流式往下游吐。你在 Android 里已经会用 Flow 处理异步流,这套心智直接迁移。

移动端特有的几个考量

  • 延迟与流式:Agent 一轮可能要几秒、多轮任务几十秒。必须流式 + 明确的「思考中/调用工具中」状态提示,否则用户以为卡死了。
  • 网络与生命周期:请求可能很长,要处理进程被杀、切后台、断网重连;长任务考虑丢到后端异步跑,App 轮询/推送结果,而不是让一个 HTTP 连接扛几十秒。
  • 成本归属:每个用户的每次对话都在花你的钱(第二十章那笔平方级的账)。要有限流和配额,否则一个恶意用户或一个死循环就能刷爆你的账单。
  • 设备端小模型?能不能在手机上本地跑?小模型(如设备端的轻量模型)能做简单分类/补全,但完整的、能调工具的 Agent 循环目前仍主要靠云端。别指望把 Fable 5 塞进手机。
⚠ 坑

如果你的 App 内 Agent 有工具(能查用户数据、能下单、能改设置),第十九章的安全课在这里全部生效,而且后果直接落到真实用户身上。用户的输入是不可信的、Agent 可能读到别的用户数据、又能产生副作用——致命三要素随时凑齐。务必在后端的工具实现里做鉴权和权限隔离:这个用户的 Agent 只能碰这个用户自己的数据、危险动作要二次确认。绝不能因为「反正调用发自我们自己的 App」就信任请求内容——注入不挑客户端。

◉ Agent 自白

作为一个 Agent,我想告诉你把我接进产品时最容易被低估的一件事:我不是一个函数,我是一段会持续花时间、花钱、还可能被诱导的过程。你接一个普通 REST API,调用即返回、行为确定、成本固定;接我,则要为「一次调用背后是一串循环」重新设计你的延迟预期、成本模型和安全边界。好消息是,这些你作为 Android 工程师其实都有对应经验——流式你有 Flow、异步长任务你有 WorkManager、密钥隔离你有 BFF、限流你有拦截器。你不需要新范式,只需要把已有的工程直觉,套到「后端跑着一个会循环的我」这个新事实上。下一章,我们终于回到你翻开这本书的起点:Web3。你当初在 DoraHacks 看到的那些 Agent × 链的项目,到底在做什么、怎么做、又有哪些独有的雷——而这会直接接上你的另一本书《上链》。