一个本地 OpenClaw 自动化项目的架构难点与解决方案
说明:本文已做脱敏处理。文中隐去了具体平台名、账号标识、业务话术、规则细节和部分目录命名;保留的是架构思路、工程取舍与关键技术方案。你可以把它理解为一个"本地内容生产与浏览器执行系统"的技术复盘。
一、为什么我要把 OpenClaw 做成本地项目
过去很长一段时间,很多 AI 自动化项目都停留在 Demo 层:大模型能写文案、会回答问题、能规划步骤,但一旦真正进入业务执行,就会立刻暴露出三个现实问题。
第一,模型的"会说"不等于系统的"能做"。一个 prompt 可以把流程讲得头头是道,但真正落到执行端,浏览器会失焦、登录态会失效、页面结构会变化、上传动作会卡住、接口返回也未必稳定。第二,SaaS 化的云端执行虽然看起来优雅,但对很多依赖本地会话、本地浏览器、已登录状态和个人工作环境的场景来说,云端反而不是最优解。第三,长链路自动化不是一个"单点能力"问题,而是一个"系统协同"问题,模型生成、风险约束、人工确认、浏览器控制、结果回写、可观测性,缺一不可。
所以我最后没有把这个项目做成"一个能调用模型的脚本",而是把它做成了一个围绕 OpenClaw 展开的本地自动化系统。它的目标并不是炫技,而是解决一个很实际的问题:在本机已有账号会话和工作环境的前提下,如何让 AI 从"给建议"真正走到"稳定执行",并且在执行失败时可回溯、可恢复、可继续迭代。
这个系统后来逐渐稳定成几层架构:
- 最外层是 CLI 与本地工作台,提供统一入口。
- 中间层是 orchestrator,负责把"生成、审批、预检、发布、同步"串成完整任务。
- 执行层是 OpenClaw,包括 agent 调用、browser 控制、页面快照、网络响应监听等能力。
- 状态层是本地文件化存储,记录账号画像、草稿、审批包、发布结果、任务进度和运行快照。
- 兜底层是模板与规则系统,在模型不稳定时仍能产出最低可用结果。
从结果上看,这套架构的真正价值不是让某一个步骤更智能,而是让整个自动化链路从"偶尔能跑通"变成"可以持续运行、持续定位问题、持续优化"的工程系统。
二、整体架构:不是单 Agent,而是一条可落地的本地执行链
如果用一句话概括这套系统,我会说它是一个"以 OpenClaw 为执行内核、以 orchestrator 为编排中心、以本地状态存储为事实来源"的自动化应用。
在实现上,最关键的不是某个模块写得多复杂,而是边界划分清晰。
首先,OpenClaw 没有被直接散落在业务代码各处,而是被收敛为统一适配层。项目里专门有一层对 openclaw 命令行的封装,负责处理 agent 调用、browser 命令、JSON 提取、异常包装和超时控制。这样做的好处是,业务层不需要知道底层到底是命令行输出、stderr 回退还是 JSON 包裹文本,只需要拿到稳定的结构化结果。
其次,真正的业务入口不是浏览器脚本,而是 orchestrator。它负责把单个动作拼装成完整流程,比如生成草稿、补齐图片、打包审批、自动批准、执行发布、回写状态。换句话说,浏览器只是执行器,真正定义任务生命周期的是 orchestrator。
再次,系统没有把状态散落在内存里,而是显式落盘。账号画像、Chrome 配置、学习快照、草稿、审批、发布记录、指标快照、工作台任务,都写进本地状态目录。这个设计看起来"土",但对本地自动化非常关键,因为一旦浏览器挂掉、终端关闭、工作台刷新,系统仍然知道自己执行到了哪里。
最后,系统同时提供 CLI 和 Web Studio 两个入口。CLI 适合串命令、批量跑、自动化集成;Studio 适合人工介入、查看状态、做半自动决策。这种双入口结构解决了一个常见矛盾:自动化链路并不总是应该 100% 无人化,尤其在内容生产、风险审核、登录态判断这类场景里,人机协同比"强行全自动"更靠谱。
从架构上看,这其实是一种很典型的"本地 AI 应用后端化"思路。也就是说,不把 AI 当成一个聊天窗口,而是把它嵌入到一个有状态、有执行器、有规则、有控制面的应用里。
三、难点一:模型输出不稳定,如何把"自然语言能力"转成"工程可依赖能力"
很多人做智能体项目,最先遇到的问题不是模型不聪明,而是模型太自由。它可能会返回解释、Markdown、JSON、半结构化文本,甚至把你要求的字段放在嵌套对象深处。对聊天来说,这不是问题;对工程系统来说,这是灾难。
这个项目里最早踩的坑,就是把模型输出直接当成可信输入。实践几次以后我意识到,真正可用的方式不是"要求模型每次都听话",而是"系统必须对模型不听话有容错能力"。
因此第一层解法,是给 OpenClaw agent 的调用加统一包装。无论底层返回的是完整 JSON、包在文本中的 JSON、还是对象中的 reply 文本,系统都会先做提取和归一化,再交给业务层处理。这里的关键不是解析技巧,而是一个原则:模型响应永远视为不可信边界输入。
第二层解法,是给每个关键能力准备 deterministic fallback。比如样本分析失败,可以退回到基于关键词和规则的启发式分析;学习快照生成失败,可以退回到行业画像、历史样本和风险规则拼接出的模板快照;草稿生成失败,也能直接走模板化结构,至少产出可编辑的基础草稿,而不是整条链路报废。
第三层解法,是把"智能生成"与"系统决策"拆开。模型负责补充表达、归纳规律、生成内容草案,但真正决定是否允许发布、风险是否过高、是否需要免责声明、哪个后端可用,仍然由规则和程序来判断。这样做的结果是,模型能力变成了增益项,而不是单点故障源。
这个改动对系统稳定性的提升非常大。以前链路成败取决于模型那一次"回得好不好";后来链路是否可执行,主要取决于系统有没有为不稳定留出缓冲区。对工程来说,后者显然更可靠。
四、难点二:本地浏览器会话极其脆弱,如何把"已登录状态"变成可管理资源
如果一个自动化项目需要依赖真实浏览器和真实账号会话,那么浏览器本身就不再只是工具,而是系统资源。很多失败不是出在代码逻辑,而是出在"这次浏览器没挂上""这次窗口不是原来的窗口""这次登录态看起来像在线,但实际不可用"。
这个项目一开始也吃过这个亏。最初的思路比较直接:拉起浏览器,附着调试端口,然后开跑。后来发现这套方式在实际使用里并不稳,因为浏览器会话不是瞬时对象,而是跨多天、多轮任务复用的长期状态。
所以我最后把浏览器会话管理独立成了一层。每个账号都绑定固定的本地 Chrome user-data-dir、固定 profile 目录和固定 remote debugging port;初始化时自动生成两个脚本,一个负责拉起旧会话窗口,一个负责把这个窗口重新接回 OpenClaw。这样,账号和浏览器实例之间不再是临时关系,而是稳定映射关系。
更重要的是,系统不再把"登录态"理解为一个布尔值,而是一个带来源的状态。比如缓存态、缓存加会话态、显式检查态,它们的可信度不同,使用策略也不同。若本地曾经发布成功,可以暂时视为有较高可信度的缓存登录;若调试端口存活但页面内容无法判定,则只能标记为 unknown;若页面里明确出现登录或退出信号,再更新为显式确认状态。
这种设计背后其实是在解决一个本地系统常见但容易被忽略的问题:外部世界的状态不是同步可读的。浏览器"在不在"、页面"是不是正确标签页"、账号"是不是真的登录",都不是一行代码能绝对判断的。所以工程上必须接受不确定性,并把不确定性显式建模。
从后续运行效果看,这种"状态分层 + 会话绑定 + 显式探测"的方式,比单纯依赖一次 status 命令稳得多。它让浏览器从一个不可控黑盒,变成一个勉强可治理的资源池。
五、难点三:浏览器自动化最怕页面变动,如何降低 DOM 脆弱性
做过浏览器自动化的人都知道,最不可靠的往往不是启动浏览器,而是和页面交互。前端页面一旦改版,按钮文案变了、节点树层级变了、弹窗多了一层、渲染时机推迟了,原来那套 selector 很容易全部失效。
在这个项目里,我没有把自动发布建立在重度依赖 CSS selector 的方案上,而是尽量走"页面快照 + 可见文本 + 兜底点击"的路线。具体来说,系统会先通过 OpenClaw 获取页面 snapshot,把可见节点整理成可搜索的结构;优先使用 snapshot ref 去点击,如果 ref 因为页面重渲染失效,再退回到基于可见文本和可视区域的 DOM 搜索点击。
这个策略听起来不如精细 selector"优雅",但在不断变化的业务页面里反而更耐用。因为对人来说,我们识别页面元素最稳定的依据本来也不是 DOM 路径,而是"屏幕上有没有一个叫这个名字的按钮"。系统向这种认知方式靠拢,鲁棒性反而更强。
另外,图片上传没有走复杂交互模拟,而是直接写入 input[type=file]。这是另一个非常务实的选择。很多"点击上传按钮再选文件"的流程在自动化时会被系统文件弹窗卡住,但只要目标页底层仍是标准 file input,直接赋值通常更稳。
还有一个经验很关键:发布成功不要依赖页面文案判断,而要依赖更强的信号。项目里后续采用的是 URL 特征和网络响应结合来确认发布结果,而不是只看页面上有没有"成功"两个字。因为页面提示文案最容易受样式和实验开关影响,网络响应和跳转状态才更接近真实事实。
这部分实践给我的一个结论是,浏览器自动化的核心不是"模拟得像人",而是"在系统允许的范围内,尽量选择最少歧义的信号和最少脆弱的交互路径"。
六、难点四:长链路自动化如何避免"一步失败,全盘报废"
从产品视角看,这个系统最吸引人的能力是一键自动完成整条链路;但从工程视角看,这恰恰也是最危险的部分。因为链路越长,失败点越多:生成失败、配图失败、审批判断异常、预检未通过、浏览器失联、发布页未加载、结果未回写,任何一个点都可能让任务中断。
我对这个问题的处理方式,不是继续把链路藏起来,而是把链路显式拆段。系统内部把一次完整任务至少拆成几个阶段:排队、内容生成、素材准备、发布中、成功或失败。每个阶段都有独立状态、更新时间、进度信息和结果对象。
在 Web Studio 里,前端并不直接等待一个巨大的同步请求,而是先创建 job,再轮询 job 状态。这样做的好处有三个。
第一,长任务不会因为前端页面刷新而完全丢失。只要 job 已经写入本地存储,刷新后还能重新接上。第二,执行中的信息可以持续暴露出来,而不是最后只得到一个"成功"或"失败"。第三,系统具备天然的断点观察能力,出了问题能迅速知道是生成阶段的问题,还是发布阶段的问题。
更进一步,发布前还会做 preflight。也就是说,系统先验证登录态、会话可用性、素材条件、目标页面可达性,再决定是否正式发布。这一步非常重要,因为它把很多"运行到一半才发现不可发"的问题,提前挪到了低成本检查阶段。
另外,我并没有直接取消人工审批,而是把审批包作为流程中的独立对象。即便在自动驾驶模式下,也依然先构造草稿和审批信息,再进入批准和发布。这看似多了一层,实则是为未来接入人工复核、风险打分、灰度放行留接口。工程上,真正可扩展的链路往往不是最短链路,而是中间关键节点都能被显式接管的链路。
七、难点五:没有状态中台,自动化就无法真正运维
很多本地项目最开始都会觉得没必要做"状态层",认为 JSON 文件存一点结果就够了。但只要流程一长、参与对象一多、执行周期一拉长,你就会发现,如果没有统一状态中台,后面所有排障、回放、分析、对账都会非常痛苦。
所以这个项目里,我从比较早的阶段就明确采用了文件化状态仓。它并不复杂,本质就是按对象类型分目录存 JSON 和 Markdown,但它解决了很多关键问题。
比如账号画像和浏览器映射可以长期沉淀;草稿、审批包和发布结果可以形成完整链路闭环;学习快照和对标分析可以成为后续生成的输入;工作台任务和状态快照可以帮助恢复现场;发布记录和指标快照又能反向喂给策略层。
更重要的是,状态不是只为"保存结果",而是为"下一次决策"服务。系统后续生成选题卡、热点池、学习快照时,并不是从零开始,而是会参考历史已发布内容、已有 benchmark 样本和本地规则知识。这就让系统从单次执行器,逐渐变成一个会积累上下文的本地智能应用。
当然,文件化状态也不是没有代价。它在并发写入、一致性控制、查询效率上肯定不如数据库。但对一个强调本地优先、单机运行、可读可查的项目来说,这种取舍是值得的。因为它把"透明度"放在了"复杂度"前面。很多时候,排障最快的方式不是写一条 SQL,而是直接打开对应目录,看最近一次任务到底写了什么。
从这个角度讲,文件系统在这里不只是存储介质,更像是一个低门槛、强可审计的本地事实层。
八、难点六:自动化系统不只是后端,还需要一个可协同的控制面
如果只有 CLI,这个项目当然也能跑,但会非常难用。因为 CLI 更适合工程师,不适合频繁查看状态、抽取候选内容、人工做最后一步确认。尤其当系统开始承担"半自动"和"全自动"混合模式时,一个轻量控制面几乎是必需品。
所以后来我补了一个本地 Studio。它不是传统意义上的复杂前端,而是一个足够轻的本地工作台:首页展示登录态、最近草稿、最近发布、模型路由和执行概况;中间有一键自动发布入口;还支持从卡池里抽题,生成多个版本,再决定保留、重来还是直接推送发布。
这个设计解决的,不只是"好不好看"的问题,而是"自动化怎么被人真正使用"的问题。一个只有命令行的系统,最终很容易回到"会的人才能用";而一个提供状态概览、任务轮询和人工接管能力的控制面,才更接近可运营产品。
我在这里学到的一点是:AI 工程项目很容易把注意力都放在模型和执行器上,但真正决定使用体验的,往往是控制层。用户不是只想知道系统有没有能力,他更想知道系统现在在做什么、做到哪里了、是否需要他介入、失败后能不能继续。
换句话说,没有控制面的自动化,更像是脚本;有了控制面的自动化,才更像产品。
九、一些关键取舍:为什么我没有追求"最先进",而是追求"最可落地"
回头看整个项目,有几个取舍我现在仍然认为是对的。
第一,本地优先,而不是云端优先。只要场景依赖真实浏览器会话和个人工作环境,本地就是更现实的落点。
第二,文件化状态优先,而不是先上数据库。前期最重要的是可追踪、可回看、可人工修正,不是高并发。
第三,规则和模板优先于"全靠模型"。模型输出再强,也必须建立在硬边界和兜底机制之上。
第四,双入口优先于单入口。CLI 负责自动化集成,Studio 负责人工协同,二者结合才覆盖真实使用场景。
第五,弱依赖页面结构,强依赖稳定信号。自动化不怕步骤多,就怕依据脆弱。
这些取舍共同指向一个结论:本地 AI 自动化系统最重要的不是"某个能力有多炫",而是"系统整体是不是能连续工作一周、一个月,还能不断修正"。
十、结语:OpenClaw 真正难的不是调用,而是把它放进一套工程系统
很多人第一次接触 OpenClaw 这类工具时,会把注意力放在"能不能调浏览器""能不能跑 agent""能不能返回 JSON"。这些当然重要,但它们都只是能力原件,不是最终系统。
这个项目让我真正体会到的一点是:OpenClaw 不是一个"替代工程"的捷径,反而会倒逼你把工程边界想清楚。你必须回答很多以前可以回避的问题,比如状态放在哪里、失败怎么回退、登录态怎么判定、页面变动怎么兜底、人工在哪一步介入、模型失常时谁来接管。
也正因为如此,当这些问题被逐个解决之后,系统才开始显现出真正价值。它不再只是一个会操作浏览器的 AI,而是一套本地可持续运行的自动化工作系统:它能生成内容,能调用智能体,能管理浏览器会话,能显式审批,能预检发布,能持久化状态,能通过控制面被人接管和观察。
如果让我用一句话总结这次架构实践,我会说:
不是 OpenClaw 让自动化变得可靠,而是工程化让 OpenClaw 变得可靠。
这也是我目前对本地 AI 项目最核心的理解。真正有价值的,不是做出一个"看起来很聪明"的 agent,而是做出一套即使在模型波动、页面变化、会话脆弱、任务漫长的情况下,依然能稳定交付结果的系统。这样的项目,才真正接近生产力工具,而不是一次性的技术演示。