1. 项目概述一个运行在手机上的AI“操作员”最近在捣鼓一个挺有意思的东西我把它叫做“AndroidClaw”。简单来说这是一个直接运行在你安卓手机上的AI智能体。它的核心目标是让大语言模型LLM能真正“动手”操作你的手机。想象一下你不再需要自己一步步点开微信、找到联系人、打字发送而是直接对手机说“帮我给张三发条消息说我晚点到”然后AI就能理解你的意图自动完成这一系列操作。这就是AndroidClaw想做的事——把LLM变成一个能看懂屏幕、会点击、会输入、会滑动的手机操作员。这个项目的灵感来源于我对现有一些AI智能体和自动化工具比如OpenClaw、NanoBot等的观察。我发现很多强大的想法要么跑在云端要么依赖复杂的PC端环境真正能“常驻”在手机里、利用手机原生能力特别是无障碍服务的轻量级方案并不多。所以我的目标很明确构建一个纯粹的Android原生应用它集成了LLM的规划与决策能力以及手机的无障碍交互能力让AI能直接在设备端理解和执行任务。它适合谁呢如果你是对AI应用开发、移动端自动化感兴趣的开发者或者你厌倦了重复性的手机操作想探索一种更“智能”的交互方式那么这个项目会是一个很好的起点和参考。整个项目采用Kotlin开发核心架构清晰强调可运行、易扩展和实际部署。2. 核心架构设计如何让AI“看见”并“操作”手机要让一个AI模型在手机上“干活”光有聪明的“大脑”LLM是不够的它还需要“眼睛”来看屏幕需要“手”来点击和输入。AndroidClaw的架构就是围绕解决这两个核心问题来设计的同时还要保证整个系统能稳定、可靠地长时间运行。2.1 分层架构解析从智能核心到物理交互整个应用可以清晰地分为几个层次自上而下分别是智能决策层、工具执行层、界面理解层和通信持久层。第一层智能体核心Agent Core这是整个系统的“大脑”。它负责最核心的循环理解用户用自然语言提出的请求比如“打开微信找到昨天的群聊”然后将其分解成一个可执行的行动计划。这个计划不是一步到位的而是一个“规划-执行-观察-再规划”的迭代过程。例如AI可能先规划“第一步启动微信”执行后发现屏幕上是微信的登录页面这不符合预期因为我们需要的是主界面于是它会重新观察屏幕规划新的动作“点击登录按钮”或“处理登录状态”。这个层集成了对话记忆能让AI记住之前的交互上下文还管理着所有可用的工具Tools。第二层工具层Tool Layer这是“大脑”指挥“手脚”的指令集。AI规划出的每一个具体动作比如“点击”、“输入文字”、“滑动”都对应一个工具。AndroidClaw内置了丰富的工具主要分为几类手机操作工具这是重中之重包括基于文本的点击phone_click_by_text、基于坐标的点击、长按、滑动、返回、回到主页等。文件与命令工具让AI可以读写应用沙盒内的文件或执行一些简单的Shell命令需权限扩展其能力边界。技能工具这是一个可扩展的设计未来可以接入更复杂的预制技能比如“订咖啡”、“查天气”等组合操作。所有工具都通过一个统一的工具注册与执行框架来管理智能体核心只需调用工具名和参数无需关心底层如何实现。第三层界面理解层UI Understanding Layer这是AI的“眼睛”。在安卓上获取屏幕内容主要有两种方式无障碍服务AccessibilityService和截图。AndroidClaw优先采用无障碍快照的方式。当AI需要观察屏幕时它会调用phone_get_ui_snapshot_compact工具。这个工具会通过无障碍服务获取当前屏幕所有UI元素的树状结构信息包括它们的文本内容、坐标、是否可点击等。这种方式效率高、无需截图、不涉及图像处理而且能获取到一些截图OCR无法识别的控件状态比如复选框是否被选中。注意这里有一个关键设计决策。为什么优先用无障碍快照而不是OCR第一是速度解析XML结构比OCR识别图片快得多第二是精准OCR可能识别错误但直接从控件树获取的文本是100%准确的第三是信息丰富度我们能拿到控件的完整属性resource-id, class这对于精准定位元素至关重要。只有当某些界面元素无法通过无障碍服务捕获比如游戏内画面、自定义绘制的内容时才会降级到截图OCR或坐标映射的方案。第四层通信与持久化层Channel Persistence智能体需要与用户交互也需要记住发生过的事情。这一层包含通道引擎统一处理消息的流入和流出。目前支持本地App内的直接交互也集成了飞书机器人通道让你可以远程通过飞书给手机发指令。数据持久化使用Android官方的Room数据库持久化存储所有的对话记录、消息历史和执行日志。这不仅是用于界面展示更重要的是为AI提供了长期的对话记忆上下文。守护服务与可靠性为了让AI能7x24小时待命应用实现了前台守护服务Foreground Service并利用WorkManager进行健康检查。如果服务意外停止系统会尝试重新拉起它确保智能体始终在线。2.2 关键技术选型与背后的思考为什么用Kotlin和原生Android SDK这是项目定位决定的。我们要深度集成无障碍服务、前台服务、WorkManager等系统级能力这些用原生开发是最直接、最稳定、性能最好的方式。跨端框架或纯云端方案无法实现这种深度的系统交互和低延迟响应。为什么集成LangChain4jLangChain4j是一个优秀的Java/Kotlin生态的LLM应用框架。它为我们提供了三大便利一是多模型支持可以轻松切换OpenAI、Azure、Ollama本地模型等多种后端二是工具调用Function Calling的标准化封装大大简化了将我们的“点击”、“输入”等工具暴露给LLM的流程三是对话记忆管理内置了多种记忆存储方式。我们不必重复造轮子可以专注于手机端特有的能力建设。数据流与状态管理一次完整的用户请求处理流程如下用户通过本地UI或飞书通道发送消息“帮我设置一个明天早上9点的闹钟。”通道引擎将消息路由至智能体核心并存入数据库。智能体核心调用配置好的LLM例如GPT-4将用户请求、历史对话、以及所有可用工具的描述一起发送给LLM。LLM返回一个结构化响应例如{action: tool_call, tool_name: phone_open_app, arguments: {package_name: com.android.deskclock}}。智能体核心在工具层查找并执行phone_open_app工具。这个工具会通过Android的PackageManager启动时钟应用。执行完毕后工具返回结果“已成功打开时钟应用”。智能体核心将结果作为新的上下文再次调用LLM进行下一步规划“应用已打开当前界面是时钟主页。”LLM根据新观察可能规划下一步phone_click_by_text工具参数是{text: 闹钟}。如此循环直到最终完成任务“闹钟已设置为明天09:00”并将最终结果返回给用户。这个过程中每一步的规划、工具调用、结果、耗时、Token使用量都会被结构化记录并实时显示在App的“执行追踪”界面中方便调试和复盘。3. 核心功能实现与实操要点理解了架构我们深入到几个最关键的功能模块看看它们是如何具体实现的以及在实际编码中会遇到哪些“坑”。3.1 无障碍服务AI“眼睛”和“手”的基石无障碍服务AccessibilityService是整个项目能够操作手机的“尚方宝剑”。没有它App就只能截图然后通过图像坐标映射来模拟点击这种方式既不准又慢而且无法处理动态界面如列表滚动。配置与声明首先在AndroidManifest.xml中声明服务并关联一个配置XML文件accessibility_service_config.xml。service android:name.service.PhoneAccessibilityService android:permissionandroid.permission.BIND_ACCESSIBILITY_SERVICE android:exportedtrue intent-filter action android:nameandroid.accessibilityservice.AccessibilityService / /intent-filter meta-data android:nameandroid.accessibilityservice android:resourcexml/accessibility_service_config / /service在配置XML中我们需要精细声明服务的能力accessibility-service xmlns:androidhttp://schemas.android.com/apk/res/android android:descriptionstring/accessibility_service_description android:accessibilityEventTypestypeWindowStateChanged|typeWindowContentChanged|typeViewClicked android:accessibilityFlagsflagReportViewIds|flagRetrieveInteractiveWindows android:accessibilityFeedbackTypefeedbackGeneric android:notificationTimeout100 android:canRetrieveWindowContenttrue android:canPerformGesturestrue/accessibilityEventTypes这里非常关键。我们不需要监听所有事件那样会严重耗电。通常只监听窗口状态变化、内容变化和点击事件这足以让我们知道界面何时发生了重大更新。canRetrieveWindowContenttrue必须为true否则无法获取控件树。canPerformGesturestrue必须为true才能代表用户执行手势操作。快照获取与解析在服务启动并授权后我们就可以在任何时候通过rootInActiveWindow获取当前活动窗口的根节点AccessibilityNodeInfo然后递归遍历这棵树。fun getCompactSnapshot(root: AccessibilityNodeInfo?): UiSnapshot { val nodes mutableListOfUiNode() fun traverse(node: AccessibilityNodeInfo, depth: Int) { if (!node.isVisibleToUser) return // 忽略不可见节点 val text node.text?.toString() val contentDesc node.contentDescription?.toString() val className node.className?.toString() val resourceId node.viewIdResourceName val bounds Rect() node.getBoundsInScreen(bounds) // 构建一个精简的节点信息只包含AI决策所需的关键字段 nodes.add(UiNode( text text, contentDesc contentDesc, className className, resourceId resourceId, bounds bounds, clickable node.isClickable, scrollable node.isScrollable )) // 递归遍历子节点 for (i in 0 until node.childCount) { node.getChild(i)?.let { child - traverse(child, depth 1) child.recycle() // 重要必须回收子节点对象 } } } root?.let { traverse(it, 0) } return UiSnapshot(nodes, System.currentTimeMillis()) }实操心得AccessibilityNodeInfo对象必须手动回收recycle()否则会引起严重的内存泄漏。特别是在深度遍历大型界面如网页、长列表时必须在每次使用完子节点后立即回收。基于快照的精准操作拿到快照后AI就可以进行分析。例如当LLM决定要点击“登录”按钮时它会调用phone_click_by_text工具参数是{text: 登录}。工具的实现逻辑是再次获取当前快照。在快照的所有节点中寻找text或contentDesc字段与“登录”匹配的节点。进行模糊匹配比如包含关系因为有时文本可能带有空格或标点。如果找到多个匹配项则根据位置通常优先选择屏幕上可见的、靠前的、控件类型Button优先于TextView进行排序。对最佳候选节点的bounds中心点坐标执行无障碍手势点击。fun clickByText(text: String): Boolean { val snapshot accessibilityService.getCompactSnapshot() val candidates snapshot.nodes.filter { node - node.isClickable (node.text?.contains(text) true || node.contentDesc?.contains(text) true) }.sortedBy { it.bounds.top } // 简单的排序从上到下 val target candidates.firstOrNull() return if (target ! null) { val centerX target.bounds.centerX() val centerY target.bounds.centerY() performGesture(centerX, centerY) // 执行手势 true } else { false } }3.2 工具调用框架连接LLM与手机API工具调用Tool Calling是让LLM能够使用外部能力的关键。我们需要将每个手机操作点击、输入、滑动都封装成一个LLM能理解和调用的“工具”。定义工具使用LangChain4j我们可以用注解的方式很方便地定义工具。例如定义一个打开应用的工具Tool(根据包名打开一个安卓应用) fun phoneOpenApp( P(安卓应用的包名例如com.tencent.mm 代表微信) packageName: String ): String { return try { val intent context.packageManager.getLaunchIntentForPackage(packageName) if (intent ! null) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(intent) 已成功尝试打开应用$packageName } else { 未找到包名为 $packageName 的应用请确认包名是否正确。 } } catch (e: SecurityException) { 权限不足无法启动应用。 } catch (e: Exception) { 打开应用时发生未知错误${e.message} } }Tool注解描述了工具的功能这个描述会作为提示词的一部分给到LLM所以描述必须清晰、准确说明工具做什么、参数是什么。P注解描述参数。LLM会根据这些描述来生成正确的参数。工具方法必须返回String这个结果会被反馈给LLM作为下一步规划的上下文。返回信息应尽可能明确成功或失败都要有清晰的说明。工具注册与执行我们需要一个中心化的工具注册表。在应用初始化时将所有工具类的实例注册进去。class ToolRegistry { private val tools mutableListOfObjectTool() fun register(tool: Any) { tools.add(AnnotationTool.from(tool)) } fun getTools(): ListObjectTool tools fun execute(toolName: String, arguments: MapString, Any): String { val tool tools.find { it.name() toolName } return tool?.execute(arguments) ?: 错误未找到工具 $toolName } }智能体核心在收到LLM返回的工具调用请求时会解析出工具名和参数Map然后交给这个注册表来执行。注意事项工具执行必须放在后台线程协程绝对不能阻塞主线程。同时工具执行环境Context的管理要小心避免内存泄漏。我们通常通过依赖注入如Hilt来提供Application Context。3.3 守护服务与可靠性工程一个手机助手必须是“随时待命”的。这意味着我们的核心服务负责运行AI循环和监听消息需要在后台持续运行并且要尽可能避免被系统“杀掉”。前台服务Foreground Service这是保活的基础。我们需要在服务启动时调用startForeground并提供一个常驻通知。class AndroidClawDaemonService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val notification buildNotification() // 构建一个持续显示的通知 startForeground(NOTIFICATION_ID, notification) // 启动你的AI Agent核心循环 startAgentLoop() return START_STICKY // 服务被杀死后尝试重启 } }通知的渠道Channel必须创建并且要给用户一个合理的说明比如“AndroidClaw正在运行以响应您的指令”。WorkManager健康检查START_STICKY并不完全可靠。我们使用WorkManager设置一个周期性的工作比如每30分钟一次来检查我们的守护服务是否还在运行。class HealthCheckWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { if (!isServiceRunning()) { // 如果服务不在运行尝试重新启动 val intent Intent(applicationContext, AndroidClawDaemonService::class.java) applicationContext.startForegroundService(intent) Log.d(HealthCheck, Daemon service was down, attempting to restart...) } return Result.success() } }然后在应用启动或合适的地方调度这个周期性工作val healthCheckRequest PeriodicWorkRequestBuilderHealthCheckWorker(30, TimeUnit.MINUTES) .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( androidclaw_health_check, ExistingPeriodicWorkPolicy.KEEP, healthCheckRequest )网络状态感知与重连如果使用了飞书等网络通道还需要监听网络连接状态。当网络从无到有时需要重新初始化WebSocket连接等。这可以通过ConnectivityManager监听网络回调来实现。4. 开发、调试与部署全流程4.1 环境搭建与项目初始化开发环境确保你安装了最新版本的Android StudioFlamingo或更高版本和JDK 17。AndroidClaw的minSdk是24Android 7.0targetSdk是34Android 14你需要下载对应的SDK和构建工具。获取代码克隆仓库git clone https://github.com/xiuqianli1996/androidclaw.git。配置API密钥项目核心依赖LLM。你需要在local.properties文件此文件不会被提交到Git中配置你的模型API密钥。例如如果你使用OpenAIOPENAI_API_KEYsk-your-actual-api-key-here或者如果你想在本地运行可以使用Ollama来运行本地模型如Llama 3.1 Qwen2.5等并将模型服务地址配置为http://10.0.2.2:11434对于模拟器或你电脑的本地IP。模型配置在App的设置界面首次启动后会引导进入你需要填写模型相关配置。Provider选择你的模型提供商如OpenAI,Ollama,Azure OpenAI等。Base URL对于OpenAI是https://api.openai.com/v1对于本地Ollama是http://你的IP:11434/v1。Model Name填写具体的模型名如gpt-4o-mini,llama3.1,qwen2.5:7b等。API Key如果使用OpenAI等云端服务此处填写密钥使用本地Ollama通常可留空。4.2 核心开发工作流从想法到功能假设我们要增加一个新功能让AI能够读取短信验证码并自动填入。以下是具体的实现步骤第一步定义工具接口首先思考这个功能需要什么权限和API。读取短信需要READ_SMS权限并且要在AndroidManifest中声明。然后在tools包下创建一个新的工具类或者扩展现有的PhoneTools。Tool(读取最近一条短信的验证码。通常用于自动化登录场景。) fun phoneReadLatestSmsVerificationCode( P(发送方号码的关键词用于过滤短信例如支付宝、银行。可以为空则匹配所有短信。) senderKeyword: String? null ): String { // 1. 检查权限 if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) ! PackageManager.PERMISSION_GRANTED) { return 错误缺少读取短信的权限。请在系统设置中为AndroidClaw授予该权限。 } // 2. 查询短信 val uri Uri.parse(content://sms/inbox) val cursor context.contentResolver.query( uri, arrayOf(address, body, date), if (senderKeyword.isNullOrBlank()) null else address LIKE ?, if (senderKeyword.isNullOrBlank()) null else arrayOf(%$senderKeyword%), date DESC LIMIT 10 // 取最新的10条 ) // ... 解析cursor使用正则表达式从短信正文中提取6位数字验证码 // 3. 返回结果 return if (verificationCode ! null) { 找到验证码$verificationCode (来自$sender) } else { 未在最近的短信中找到验证码。 } }第二步注册工具在应用初始化或工具注册表构建的地方将这个新工具类的实例注册进去。// 在ToolRegistry的初始化方法中 toolRegistry.register(SmsTools(context))第三步测试工具不要直接让AI调用。先编写单元测试或创建一个简单的调试界面手动调用这个工具确保它能正确工作并返回预期的字符串格式。第四步更新Agent系统提示词可选但重要LLM需要知道有这个新工具可用。虽然LangChain4j会自动将工具描述发送给LLM但为了让AI更“聪明”地使用它我们可以在系统提示词System Prompt中加入一些引导你是一个手机助手。当用户提到“验证码”、“短信”、“接收验证码”等词时可以考虑使用phoneReadLatestSmsVerificationCode工具来获取最新的验证码。该工具可以接受一个可选的发送方关键词来过滤短信。这样当用户说“帮我登录一下需要短信验证码”时AI就更有可能主动调用这个工具。第五步集成与端到端测试在真实场景中测试。让AI执行一个包含读取验证码和输入验证码的多步骤任务观察其规划和执行是否流畅。4.3 调试技巧与问题排查实录开发这类AI与系统深度交互的应用调试比普通App复杂。以下是我在实践中总结的几个高效调试方法1. 实时执行追踪界面AndroidClaw内置了一个悬浮窗式的执行追踪器Execution Overlay。它会实时显示AI的“思考”过程当前LLM接收到的提示词和返回的原始响应。工具调用详情调用了哪个工具参数是什么返回结果是什么。耗时统计每一步规划、工具执行花了多少时间。Token消耗每次调用LLM用了多少Token如果模型提供商支持。这是最核心的调试工具。当AI行为不符合预期时首先看这里是LLM的规划逻辑错了还是工具执行失败了或者是工具返回的结果让LLM误解了2. UI快照查看器在设置中开启“调试模式”后可以手动触发一次phone_get_ui_snapshot_compact并以可折叠的树状结构展示当前屏幕的所有无障碍节点信息。你可以清晰地看到每个节点的文本、类名、坐标和可点击状态。这能帮你确认AI想点击的那个“登录”按钮在无障碍快照里到底是不是叫“登录”它的坐标是否正确3. 运行时日志查看器应用内集成了一个日志查看器会收集所有核心流程的Logcat输出通过自定义的LogcatTree实现。你可以在这里看到详细的异常堆栈、网络请求、数据库操作等信息。支持长按删除方便清理旧日志。4. 常见问题排查清单问题现象可能原因排查步骤AI完全无响应1. 守护服务未启动。2. LLM配置错误API Key、Base URL。3. 网络不通。1. 检查通知栏是否有AndroidClaw的常驻通知。2. 检查设置中的模型配置特别是Base URL和API Key。3. 尝试在设置页面手动发送一条测试消息查看执行追踪界面是否有任何输出。AI能“思考”但工具执行失败1. 无障碍服务未开启。2. 工具所需的权限未授予。3. 工具内部逻辑错误如空指针。1. 进入系统“无障碍”设置确认AndroidClaw服务已开启。2. 检查应用权限确保已授予所需权限如悬浮窗、短信等。3. 查看运行时日志寻找工具执行时的崩溃或错误信息。AI点击位置不对1. 无障碍快照获取的坐标不准某些ROM有bug。2. 屏幕分辨率/密度适配问题。3. AI匹配了错误的文本有多个相似文本。1. 使用UI快照查看器确认目标节点的坐标是否合理。2. 尝试使用phone_click_coordinates_from_screenshot工具基于截图坐标对比测试。3. 在工具调用前让AI先使用phone_get_ui_snapshot_compact确认当前界面确保上下文正确。多步骤任务中途失败1. LLM的上下文长度不足忘记了之前步骤。2. 界面状态变化超出预期如弹窗、网络延迟。3. 工具执行结果的反馈信息不够明确导致LLM误解。1. 检查模型配置是否使用了上下文过小的模型。考虑升级模型或优化提示词让总结更精简。2. 在关键步骤后增加delay工具或让AI主动等待界面稳定例如调用phone_get_ui_snapshot_compact直到出现某个关键元素。3. 优化工具返回的字符串使其更结构化、无歧义。例如失败时返回“失败未找到元素‘提交按钮’”而非简单的“失败”。5. 飞书通道调试如果你集成了飞书机器人调试可以在电脑上进行更方便。确保飞书开放平台的应用配置正确特别是“权限管理”和“事件订阅”。应用已经发布了可用版本并且你所在的飞书群聊已经添加了该机器人。AndroidClaw应用内的飞书设置填写了正确的App ID和App Secret并且“启用飞书通道”开关已打开。手机和运行飞书服务端的网络能够互通通常需要内网穿透或部署在公网服务器。5. 性能优化与进阶思考当基本功能跑通后我们会面临性能和体验上的挑战。5.1 性能优化点快照获取频率与去重AI每规划一步都要获取快照。频繁调用rootInActiveWindow可能影响系统性能。可以设置一个简单的缓存机制比如在短时间内如500ms连续请求返回缓存的快照。同时在监听无障碍事件TYPE_WINDOW_CONTENT_CHANGED时可以设置一个防抖debounce延迟避免界面微小时的变化就触发AI重新规划。LLM调用优化这是主要的耗时和成本环节。提示词精简精心设计系统提示词和Few-shot示例用最少的Token表达最清晰的指令。将历史对话进行智能摘要而不是全部发送。模型选择对于简单的、模式化的操作如“打开微信”可以尝试使用更小、更快的模型如GPT-3.5-Turbo。对于复杂的规划任务再用大模型。并行与流式对于多步骤中互不依赖的任务可以考虑并行执行。使用支持流式响应的模型可以让用户更快地看到AI的“思考”过程。工具执行超时与重试网络操作或某些系统调用可能超时。为每个工具设置合理的超时时间如10秒并提供重试机制最多2次。重试前最好让AI重新观察一次界面因为超时期间界面可能已变化。5.2 可靠性提升让AI更“鲁棒”状态验证与恢复AI执行phone_click_by_text(“确定”)后不能假设点击一定成功。下一步规划前应该调用phone_get_ui_snapshot_compact验证“确定”按钮是否已经消失或者期望的新界面元素是否出现。如果没有则进入恢复逻辑比如尝试再次点击或执行返回操作后重试整个子流程。异常处理与友好反馈工具层捕获的所有异常都应转化为对人类和AI都友好的错误信息返回。例如网络超时返回“操作超时可能是网络不稳定”而不是一堆Java异常栈。权限管理的引导在工具执行时如果发现权限不足返回的错误信息应直接引导用户去系统设置的哪个页面开启权限。甚至可以提供一个phone_open_settings工具直接跳转到对应的设置页。5.3 未来可能的扩展方向结构化UI理解UI Grounding当前主要依赖文本匹配。可以引入轻量级的视觉模型如MobileSAM、小型ONNX格式模型对截图进行分析识别图标、布局结构与无障碍快照信息融合形成更丰富的界面描述让AI对复杂界面如图片按钮、游戏界面的理解能力更强。技能市场与编排将常用的多步骤操作如“滴滴打车从公司回家”、“美团点一份常点的外卖”封装成“技能”。用户可以直接调用技能而无需每次都从头用自然语言描述。技能内部可以是一系列预定义的工具调用序列也可以是一个小型的、专门训练过的模型。多模态输入结合手机的语音输入实现真正的“语音助手”。用户可以直接说话发指令AI通过语音转文本后处理。甚至可以结合摄像头实现“看到什么就操作什么”的增强现实式交互。跨设备协作让手机上的AI助手能与电脑上的其他自动化工具如浏览器插件、桌面脚本通信完成跨设备的复杂工作流。开发AndroidClaw这类项目最大的乐趣在于你正在亲手搭建一个存在于掌中的数字智能体。它不再是一个被动的问答机器而是一个能主动感知环境屏幕、执行动作点击、并持续学习的“行动者”。每一次调试看着它从笨拙地找不到按钮到流畅地完成一连串操作都像在教导一个新生婴儿。过程中充满了对安卓系统底层的探索、对LLM提示工程的琢磨、以及对用户体验的细致考量。如果你也对此感兴趣不妨从克隆代码、配置一个自己的API Key开始亲手体验一下让AI来操作你手机的感觉。