OpenClaw+Auto.js实战:用200行代码搭建企业级自动打卡系统
1. 企业考勤自动化OpenClaw 调度 Auto.js 到底能解决什么问题每天上班最紧张的时刻往往不是挤地铁而是站在公司楼下盯着手机看时间——离打卡截止还有三分钟电梯却停在 18 楼不动。这种场景下一套跑在自有设备上的自动打卡系统就成了刚需。OpenClaw 加 Auto.js 的组合本质上是用「调度大脑 执行终端」的思路把打卡这件事从「人盯着手机点」变成「机器按计划点」。先说清楚这套方案是什么。OpenClaw 是一个支持定时任务编排的自动化调度工具可以部署在你的电脑或服务器上按 cron 表达式触发 HTTP 请求或脚本。Auto.js 则是安卓端的自动化框架通过无障碍服务模拟人手操作能打开应用、点击按钮、读取界面元素。两者配合的逻辑很直接OpenClaw 在指定时间向手机上的 Auto.js 服务发一条指令Auto.js 收到后唤醒屏幕、打开考勤应用、完成打卡动作再把结果回传。这套方案适合谁第一类是需要固定时间打卡但经常因为会议、通勤、临时事务错过节点的上班族第二类是有多台闲置安卓设备、想跑通最小可用自动化流程的技术爱好者第三类是做企业内部工具的同学需要一套可审计、可扩展的考勤辅助方案。它不适合的场景也很明确任何试图伪造地理位置、绕过企业考勤规则的行为都不在讨论范围内。我们做的是物理点击层面的自动化设备真实放在工位网络真实连接公司 Wi-Fi操作真实发生在应用界面上。为什么不用纯云端方案因为大多数考勤应用对虚拟定位、模拟器、多开环境有检测机制一旦触发风控轻则打卡无效重则账号异常。而 Auto.js 跑在真实手机上点击事件来自系统无障碍层行为特征和真人操作高度一致。OpenClaw 的价值在于把「什么时候触发」这件事从手机端剥离出来交给更稳定的调度层管理。手机端只负责执行不负责判断时间这样即使手机重启、脚本崩溃调度层依然可以重试或告警。我试过把定时逻辑直接写在 Auto.js 里用setInterval或timers做轮询结果遇到两个坑一是安卓系统对后台定时任务有省电限制锁屏后脚本容易被挂起二是手机时间被手动调整或时区变化时本地定时会错乱。把调度权交给 OpenClaw 后时间判断在服务端完成手机端只监听一个 HTTP 端口稳定性提升明显。下面这张表对比了两种架构的差异维度手机端定时OpenClaw 调度时间准确性受系统省电策略影响服务端 cron 精确触发失败重试需自行实现调度层可配置重试多设备管理每台单独设置统一任务编排日志审计分散在手机集中记录请求与响应节假日跳过脚本内硬编码调度表达式灵活控制理解了架构差异接下来的步骤就清晰了先让手机端跑起来一个能接收指令的 Auto.js 服务再在 OpenClaw 里配置定时任务去调用它最后用模拟请求验证整条链路。整个过程不需要 Root不需要改定位核心代码控制在 200 行以内。2. 前置准备TaoToken 接入与 OpenClaw 环境初始化在开始写打卡脚本之前需要先把调度层的基础设施搭好。OpenClaw 本身是一个任务编排框架但如果你希望它在触发打卡失败时能调用大模型做日志分析、异常归因或者用自然语言生成当天的打卡摘要就需要接入一个稳定的模型 API。TaoToken 在这里的角色是提供模型调用能力让 OpenClaw 的告警和日志模块具备语义理解功能。先明确一点TaoToken 不是打卡系统的必需组件打卡的核心链路是 OpenClaw 定时触发 Auto.js 执行。但企业级场景下你需要知道「今天打卡为什么失败了」「是网络问题还是按钮没找到」「连续三天失败要不要升级告警」这些判断如果靠人工翻日志效率很低。接入模型后OpenClaw 可以把失败日志丢给模型做归因输出人类可读的结论。TaoToken 的接入地址是https://taotoken.net/api你需要在控制台创建一个 API Key。创建路径是登录后进入控制台找到 API Keys 页面新建一个 Key 并复制保存。这个 Key 只会显示一次丢了只能重建。拿到 Key 后OpenClaw 的配置文件里需要填三个东西Base URL、API Key、Model ID。Base URL 填https://taotoken.net/apiModel ID 根据你实际使用的模型填写比如claude-sonnet-4-20250514或gpt-4o这类标识。如果你用的是 Claude Code 做脚本润色或日志分析配置方式略有不同。Claude Code 需要设置环境变量ANTHROPIC_BASE_URL和ANTHROPIC_API_KEYBase URL 同样指向https://taotoken.net/api。这样 Claude Code 在调用模型时会走 TaoToken 的通道不需要额外配置网络层。对于 Codex 用户配置文件在~/.codex/auth.json需要写入api_key和base_url字段base_url 填https://taotoken.net/api。OpenClaw 的安装本身不复杂Windows、Mac、Linux 都有对应的安装包或命令行工具。安装完成后先跑一个最小任务验证环境是否正常。比如创建一个每分钟触发一次的测试任务让它向一个本地 HTTP 服务发请求观察日志输出。这一步的目的是确认 OpenClaw 的 cron 解析、网络请求、日志记录三个模块都能工作。环境初始化阶段容易忽略的是时区设置。OpenClaw 默认使用系统时区如果你的服务器在 UTC 时区而公司考勤按北京时间cron 表达式就要相应偏移。建议在 OpenClaw 配置里显式指定时区或者在 cron 表达式里用TZAsia/Shanghai前缀。这个细节在后面配置打卡任务时会直接影响触发时间提前处理好能省不少排查时间。另外手机端和 OpenClaw 所在机器需要在同一网络内或者通过内网穿透让 OpenClaw 能访问到手机的 IP。最简单的做法是手机和电脑都连公司 Wi-Fi手机在 Wi-Fi 设置里查看自己的局域网 IP比如192.168.1.100。OpenClaw 触发时直接请求http://192.168.1.100:9317/dingtalk/punch即可。如果 OpenClaw 部署在云服务器就需要在公司路由器做端口映射或者用反向代理把手机服务暴露到一个可访问的地址。这部分涉及网络配置建议先在内网环境跑通再考虑远程方案。3. 可复制配置OpenClaw 任务定义与 Auto.js 脚本骨架这一节给出可以直接复制使用的配置片段。先看 OpenClaw 的任务配置。OpenClaw 支持 YAML 或 JSON 格式的任务定义下面是一个完整的打卡任务配置保存为punch-task.yamlname: dingtalk-morning-punch schedule: 55 8 * * 1-5 timezone: Asia/Shanghai action: type: http method: POST url: http://192.168.1.100:9317/dingtalk/punch headers: Content-Type: application/json body: device: office-phone-01 scene: morning timeout: 30000 retry: max_attempts: 3 interval: 60 on_failure: notify: type: webhook url: https://your-webhook-endpoint/alert analyze: enabled: true model: claude-sonnet-4-20250514 base_url: https://taotoken.net/api api_key: ${TAOTOKEN_API_KEY}这个配置的含义是每周一到周五早上 8:55 触发向手机 IP 的 9317 端口发 POST 请求超时 30 秒失败后重试 3 次、间隔 60 秒。如果最终失败调用 webhook 告警并用模型分析失败日志。${TAOTOKEN_API_KEY}从环境变量读取避免明文写在配置文件里。如果你用 Claude Code 来生成或润色 Auto.js 脚本可以在项目根目录创建.claude/settings.json写入以下内容{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: your-api-key-here } }这样 Claude Code 在会话中调用模型时会自动使用 TaoToken 的通道。对于 Cline 用户MCP 配置里需要填三件套Base URL 填https://taotoken.net/apiAPI Key 填你的 KeyModel ID 填你选的模型标识。Cline 的 MCP 配置文件通常在~/.cline/mcp_settings.json结构如下{ mcpServers: { taotoken: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: your-api-key-here, TAOTOKEN_MODEL: claude-sonnet-4-20250514 } } } }接下来是 Auto.js 端的脚本骨架。在手机上安装 Auto.js 或 AutoX.js 后新建一个脚本文件粘贴以下代码// Auto.js 打卡服务端脚本 // 监听 9317 端口接收 OpenClaw 的 POST 请求 const PORT 9317; const APP_NAME 钉钉; // 创建 HTTP 服务 let server $web_server.create(); server.listen(PORT, (req, res) { if (req.method POST req.url /dingtalk/punch) { let body req.body; console.log(收到打卡指令: JSON.stringify(body)); try { let result doPunch(); res.send({ success: true, msg: 打卡完成, timestamp: new Date().toISOString() }); } catch (e) { res.send({ success: false, msg: 打卡失败: e.message, timestamp: new Date().toISOString() }); } } else { res.send({ success: false, msg: 未知请求 }); } }); function doPunch() { // 唤醒屏幕 device.wakeUp(); sleep(1000); // 上滑解锁根据实际锁屏方式调整 swipe(500, 1500, 500, 500, 300); sleep(1000); // 打开考勤应用 launchApp(APP_NAME); sleep(5000); // 查找打卡按钮 let punchBtn textContains(打卡).findOne(10000); if (!punchBtn) { // 尝试通过坐标点击需根据实际界面调整 punchBtn descContains(打卡).findOne(5000); } if (punchBtn) { punchBtn.click(); sleep(2000); console.log(打卡按钮已点击); return true; } else { throw new Error(未找到打卡按钮); } } // 保持脚本运行 setInterval(() {}, 1000);这段脚本的核心逻辑是启动一个 HTTP 服务监听 9317 端口收到 POST 请求后执行doPunch函数。doPunch里先唤醒屏幕、上滑解锁然后打开钉钉用textContains(打卡)查找按钮并点击。如果找不到尝试用descContains再找一次。实际使用时你需要根据自己手机上的钉钉界面调整查找条件可以用 Auto.js 的「布局分析」功能查看当前界面的元素属性。脚本启动后在 Auto.js 里运行它然后查看手机 Wi-Fi 设置里的 IP 地址把 OpenClaw 配置里的192.168.1.100替换成实际 IP。这样调度层和执行层就连接起来了。4. 验证请求与成功结果核验从模拟触发到日志确认配置写完后不要直接等第二天早上自动触发先手动模拟一次完整请求确认链路通畅。验证分三步先测手机端服务是否可达再测 OpenClaw 能否成功调用最后检查打卡结果和日志。第一步在电脑上打开终端用 curl 直接请求手机服务curl -X POST http://192.168.1.100:9317/dingtalk/punch \ -H Content-Type: application/json \ -d {device:office-phone-01,scene:test}如果手机端脚本正常运行你会看到类似这样的返回{ success: true, msg: 打卡完成, timestamp: 2025-01-15T08:55:03.000Z }同时手机屏幕上应该能看到自动打开钉钉、点击打卡按钮的过程。如果返回success: false说明脚本执行过程中出了问题需要看 Auto.js 的控制台日志定位。常见问题是找不到打卡按钮这时候用布局分析工具查看按钮的实际属性调整textContains或descContains的参数。第二步在 OpenClaw 里手动触发任务。OpenClaw 通常提供run或trigger命令来立即执行某个任务openclaw task run dingtalk-morning-punch执行后观察 OpenClaw 的日志输出正常情况会显示请求已发送、响应状态码 200、响应体内容。如果显示超时或连接拒绝检查手机 IP 是否变化、防火墙是否拦截了 9317 端口、手机和电脑是否在同一网段。第三步核验打卡结果。打开钉钉的考勤记录页面确认刚才的模拟请求是否产生了一条打卡记录。同时检查 Auto.js 的日志看doPunch函数是否完整执行。一个完整的成功日志应该包含以下关键节点[08:55:01] 收到打卡指令: {device:office-phone-01,scene:test} [08:55:02] 屏幕已唤醒 [08:55:03] 解锁完成 [08:55:08] 钉钉已启动 [08:55:10] 找到打卡按钮准备点击 [08:55:12] 打卡按钮已点击 [08:55:13] 打卡完成如果日志在某个节点中断比如卡在「钉钉已启动」之后没有后续说明打卡按钮查找失败。这时候需要检查钉钉版本是否更新导致界面变化或者打卡按钮的文本从「打卡」变成了「上班打卡」之类的变体。调整查找条件后重新测试。OpenClaw 侧的日志同样重要。一个成功的任务执行记录应该包含[2025-01-15 08:55:00] Task dingtalk-morning-punch started [2025-01-15 08:55:00] Sending POST to http://192.168.1.100:9317/dingtalk/punch [2025-01-15 08:55:03] Response 200: {success:true,msg:打卡完成} [2025-01-15 08:55:03] Task completed successfully如果看到Response 200但响应体里success是false说明 HTTP 链路通了但打卡动作失败问题在手机端。如果看到timeout或connection refused问题在网络层。如果看到401或403检查 OpenClaw 的请求头是否被手机端服务拒绝。验证通过后把 OpenClaw 任务设为启用状态等待下一个工作日自动触发。建议在正式启用前连续手动触发三次确认稳定性。三次都成功后再切换到自动模式避免第一天就翻车。5. 常见报错排查401、local proxy failed、reading choices 与 OAuth 问题即使配置看起来没问题实际运行中还是会遇到各种报错。这一节整理几类高频错误和对应的排查思路。401 Unauthorized这个错误通常出现在 OpenClaw 调用模型 API 做日志分析时。如果你在任务配置里启用了analyze模块但 API Key 无效或过期就会返回 401。排查步骤检查环境变量TAOTOKEN_API_KEY是否设置正确Key 是否在控制台被删除或重置。如果用的是 Claude Code检查ANTHROPIC_API_KEY是否与 TaoToken 控制台里的一致。注意 Key 前后不要有空格复制时容易带上换行符。local proxy failed这个报错说明 OpenClaw 在尝试连接手机 IP 时失败了。可能原因有三个手机 IP 变了、手机和电脑不在同一网段、手机端 Auto.js 服务没启动。排查方法先在电脑上 ping 手机 IP确认网络可达再用 curl 直接请求手机服务确认端口开放最后检查 Auto.js 脚本是否在运行状态有时候手机锁屏后脚本被系统杀掉需要把 Auto.js 加入电池优化白名单。reading choices 报错这个错误一般出现在模型返回格式不符合预期时。比如你让模型分析日志但模型返回的内容不是 JSON 格式OpenClaw 解析失败就会报reading choices。解决办法是在 OpenClaw 的 analyze 配置里加上response_format: json或者在提示词里明确要求「只返回 JSON不要有其他内容」。如果模型仍然返回非 JSON可以在 OpenClaw 里加一层容错解析提取 JSON 部分再解析。OAuth 相关错误如果你用 Claude Code 或 Codex 时遇到 OAuth 报错通常是因为认证方式冲突。Claude Code 支持 API Key 和 OAuth 两种模式如果你设置了ANTHROPIC_API_KEY但又走了 OAuth 流程可能会报OAuth token invalid。解决方法是明确使用一种模式要么在settings.json里只配 API Key要么只走 OAuth 登录。对于 Codex检查~/.codex/auth.json里的api_key字段是否填写正确base_url是否指向https://taotoken.net/api。打卡按钮找不到这不是报错但表现为脚本执行成功却没打卡。原因是钉钉界面更新或不同版本按钮文本不同。排查方法用 Auto.js 的布局分析功能查看当前界面上打卡按钮的实际属性。可能是text是「上班打卡」而不是「打卡」也可能是id更稳定。把查找条件从textContains(打卡)改成id(punch_button).findOne(10000)或text(上班打卡).findOne(10000)。如果按钮在 WebView 里可能需要用className或坐标点击。手机锁屏后脚本失效这是安卓省电策略导致的。Auto.js 在后台运行时系统可能会限制其网络和 CPU 活动。解决方法在手机设置里把 Auto.js 加入「不受限制」的应用列表关闭电池优化允许后台活动。部分手机还需要在开发者选项里关闭「后台进程限制」。如果仍然不稳定可以考虑用 Termux 配合 Tasker 做保活或者把手机设置为「充电时永不休眠」。OpenClaw 任务不触发检查 cron 表达式是否正确。55 8 * * 1-5表示周一到周五的 8:55 触发但如果你在 UTC 时区实际触发时间是北京时间 16:55。在 OpenClaw 配置里显式设置timezone: Asia/Shanghai可以避免这个问题。另外检查任务是否被禁用有些 OpenClaw 版本新建任务默认是 disabled 状态需要手动启用。响应超时如果 OpenClaw 显示 timeout但手机端日志显示打卡成功说明响应回传慢了。可能是手机网络延迟或 Auto.js 处理时间过长。把 OpenClaw 的timeout从 30000 调到 60000给手机端更多时间。同时优化 Auto.js 脚本减少不必要的sleep比如把sleep(5000)改成用waitForActivity等待界面加载完成。排查问题的核心思路是分段定位先确认网络通不通再确认服务在不在最后确认业务逻辑对不对。每一段都有对应的日志和验证方法不要一上来就改代码。6. 长期运行建议与接入文档参考跑通最小可用流程后下一步是让它稳定运行。企业级场景下稳定性比功能丰富更重要。几个实用建议第一给手机分配固定 IP在路由器里做 DHCP 静态绑定避免 IP 变化导致 OpenClaw 请求失败。第二在 Auto.js 脚本里加心跳检测每隔几分钟向 OpenClaw 发一个健康检查请求这样调度层能知道手机端是否在线。第三OpenClaw 任务配置里开启重试和告警失败时及时通知不要等到月底看考勤记录才发现漏打。如果你需要把打卡结果同步到其他系统比如企业微信、飞书或内部 OA可以在 OpenClaw 的on_success回调里加一个 webhook把打卡结果推送到目标系统。OpenClaw 支持在任务完成后触发多个动作配置方式参考官方文档的actions字段。对于需要长期编码和 Agent 调度的场景Coding Plan 提供了更完整的任务编排能力适合把打卡系统和其他自动化任务统一管理。如果你只是想验证模型调用是否正常可以用模型对话页面快速测试 API Key 和 Base URL 是否配置正确。接入过程中遇到配置问题API Keys 页面和接入文档里有详细的参数说明和示例代码。整套方案的核心代码不到 200 行但覆盖了调度、执行、验证、告警四个环节。实际部署时建议先在测试环境跑一周观察日志和打卡记录确认没有漏打或误打后再正式启用。技术本身是中性的用它来减少重复劳动、提升效率才是这套方案的价值所在。