很长一段时间里,我一直在寻找一个真正能让 OpenClaw 融入日常生活的使用场景。再多一个聊天机器人并不能帮我节省时间。相比之下,一个能够使用本地模型推理、执行定时任务、查询 Gmail、读取 Patrick、与 Home Assistant 交互、处理 Frigate 事件,甚至每天夜里为女儿准备一首歌曲的助手,才开始真正有意思。

本文介绍我正在使用并逐步完善的 homelab 架构。我的目的并不是公开包含真实 IP 地址、账号、Token 或 Home Assistant 实体名称的配置,而是展示一套可以复现的架构、在我这里真正有效的技术选择、遇到的限制,以及我主动设置的安全边界。

24 GB 显存两张 12 GB RTX 3060 用于本地推理。
128,000 tokens为长时间运行的 Agent 任务配置的大上下文。
只加载一个模型为了避免显存被占满而做出的主动选择。
Local-first 架构推理、摄像头、Frigate、Home Assistant 和敏感日志都保留在自己的基础设施中。

Local-first 并不等于 100% 无云。 Gmail 仍然是 Google 的服务,音乐生成也需要使用 Suno 网站。但是 OpenClaw Gateway、主模型、Frigate 数据、家庭自动化决策、历史记录、下载后的 MP3 和日志都保留在我的网络中。这个区别很重要:我的目标是控制每一条数据边界,而不是假装互联网已经不存在。

01为什么选择 OpenClaw,而不只是一个 AI 聊天界面

单独的语言模型能够回答问题。OpenClaw 在模型周围补上了把“回答”变成“行动”所需要的能力:持续运行的 Gateway、持久会话、可控制的浏览器、定时任务、工具、skills、移动端 nodes,以及与其他系统的连接。

在我的使用场景中,我希望有一个统一入口,可以同时处理多个领域:

  • 我的邮件和日历;
  • Patrick 中保存的任务、项目和休假信息;
  • Home Assistant 家庭自动化;
  • Frigate 事件和本地摄像头;
  • 博客和技术监控主题;
  • 例如 Jeanne 每日歌曲这样的创意自动化。

真正的价值并不来自集成数量,而是助手能够保留上下文、选择工具、执行动作、观察结果并继续完成任务。

这也让安全问题变得更复杂。聊天机器人出错,只会生成一个错误答案;Agent 出错,却可能发送邮件、修改任务或触发设备。因此,架构必须围绕权限、边界和验证来设计,而不能只关注“最聪明的模型”。

02我的 homelab 总体架构

我的基础设施被有意拆分成多个职责。AI 服务器不会取代 Home Assistant、NAS 或 Raspberry Pi。每个组件都保留清晰的责任范围。

  • Ubuntu AI 服务器:运行 Ollama、OpenClaw、本地模型、历史记录存储和 Agent 处理。
  • 两张 12 GB RTX 3060:合计 24 GB 显存,用于量化模型。
  • 64 GB DDR4 和 Ryzen 5600X3D:为服务、溢出和非 GPU 任务提供系统内存与 CPU。
  • Coral USB TPU:为 Frigate 使用的目标检测提供专用加速。
  • 独立机器上的 Home Assistant:负责家庭自动化编排、helpers、scripts、Google Cast 和自动化规则。
  • Frigate:负责目标检测、人脸识别和 MQTT 事件发布。
  • Synology 与 Raspberry Pi:负责存储、备份和辅助服务。
  • 移动 nodes:根据设备权限提供通知、定位或授权动作。
[手机 / Mac / WebChat]
             |
             v
      [OpenClaw Gateway]
        |      |      |
        |      |      +--> [浏览器 Skills / gog / himalaya]
        |      |
        |      +---------> [Patrick MCP / Home Assistant MCP]
        |
        +----------------> [GPU 服务器上的 Ollama]
                              |
                    muse-glimmer / Ornith / 视觉模型

[PoE 摄像头] --> [Frigate] --> [MQTT] --> [Home Assistant]
                                           |
                                           +--> 厨房 Google Cast
                                           +--> 移动端通知

[OpenClaw + Suno Web] --> 本地 MP3 --> HA webhook

远程访问方面,我更倾向于使用 WireGuard 之类的 VPN,而不是把 Gateway、Home Assistant 或 Ollama 直接暴露到互联网。

03OpenClaw Gateway 的安装与监控

OpenClaw 以 Gateway 为核心。它是负责会话、路由、channels、定时任务、nodes 和工具调用的控制平面。

推荐安装方式是使用 onboarding 向导:

npm install -g openclaw@latest

openclaw onboard --install-daemon

openclaw gateway status --require-rpc
openclaw channels status --probe
openclaw dashboard

本地控制面板通常通过 loopback 方式暴露在 18789 端口。在没有了解认证和远程访问选项之前,我不建议把它改成公开监听。

我日常使用的检查命令很简单:

openclaw gateway status
openclaw gateway restart
openclaw logs --follow
openclaw doctor

在家庭生产环境中,Gateway 必须被监控。在 Linux 上,它可以通过用户级或系统级 systemd 服务运行。关键是避免两个不同的监控进程同时尝试重启同一个服务。

Gateway 不是模型。 即使本地模型停止或被替换,Gateway 仍然保持运行。定时任务、会话和助手的运行状态都由它保存。

04Ollama:128k 上下文与显存优化

Ollama 以服务形式运行在 GPU 服务器上。我的目标是在为 Agent 任务保留足够大上下文的同时,避免多个模型和多个并发请求争抢 24 GB 显存。

我的 systemd override 配置如下:

# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_CONTEXT_LENGTH=128000"
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q4_0"
Environment="OLLAMA_KEEP_ALIVE=8h"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_NUM_PARALLEL=1"

然后执行:

sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl status ollama
ollama ps

为什么使用这些参数?

  • OLLAMA_CONTEXT_LENGTH=128000 为历史记录、工具和长任务提供较大的上下文预算。
  • OLLAMA_FLASH_ATTENTION=1 在 backend 与模型支持时减少内存压力。
  • OLLAMA_KV_CACHE_TYPE=q4_0 对上下文缓存进行强量化。这是为了让大上下文装入显存而做出的激进选择,可能会带来一定质量折衷。
  • OLLAMA_KEEP_ALIVE=8h 避免每次交互都重新加载主模型。
  • OLLAMA_MAX_LOADED_MODELS=1 防止多个大模型同时驻留在显存中。
  • OLLAMA_NUM_PARALLEL=1 避免多个并发请求成倍放大 KV cache 消耗。

OLLAMA_HOST=0.0.0.0:11434 会让 Ollama 监听所有网络接口。 Ollama 默认并不提供适合互联网暴露的认证机制。这个端口必须限制在 LAN 或可信 VLAN 中,通过防火墙过滤,并且绝不能从路由器做公网转发。

在我当前的配置中,ollama ps 显示主模型 100% 加载在 GPU 上,使用 128k 上下文和 8 小时 keep-alive。这正是我想要的结果:尽量避免大量 offload 到 CPU,因为当系统不断在 RAM 与 VRAM 之间搬运数据时,Agent 性能会迅速下降。

把 OpenClaw 连接到 Ollama

OpenClaw 使用 Ollama 的原生 API。不要在 URL 后面添加 /v1,因为 OpenAI 兼容模式可能降低工具调用处理的可靠性。

~/.openclaw/openclaw.json 中的简化示例:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://<OLLAMA_LAN_SERVER>:11434",
        apiKey: "ollama-local",
        api: "ollama",
        timeoutSeconds: 300,
        contextWindow: 128000,
        models: [
          {
            id: "muse-glimmer:latest",
            name: "muse-glimmer:latest",
            input: ["text"],
            params: {
              num_ctx: 128000,
              keep_alive: "8h"
            }
          }
        ]
      }
    }
  },
  agents: {
    defaults: {
      model: {
        primary: "ollama/muse-glimmer:latest"
      }
    }
  }
}

contextWindow 用来告诉 OpenClaw 可用的上下文预算,num_ctx 会传给 Ollama。我倾向于保持两者一致,避免 OpenClaw 构造出 backend 实际无法执行的上下文。

05根据用途选择模型

我已经不再寻找“绝对最好的模型”。我寻找的是:针对某项具体任务,我的硬件能够稳定运行的最佳模型。

用途 使用或测试的模型 原因
OpenClaw 通用助手 muse-glimmer:latest 在我的测试中,它在质量、工具调用和完整装入 24 GB 显存之间取得了最好的平衡。
编程与 Agent 任务 ornith:35b-q4_K_M 适合操作代码仓库、修改文件并完成多步骤目标的专用模型。
轻量 Agent 或快速测试 ornith:9bqwen3:0.6b 启动快、资源消耗较低,但 Agent 能力更有限。
本地视觉 qwen2.5vl:7bqwen3-vl:4b 用于图片描述、场景分类和丰富通知内容。
对比与研发 Qwen 3.5/3.8、Gemma 4、Devstral、GLM 比较质量、速度、上下文容量和工具可靠性。

我的 ollama list 中还有更多模型,但保存在硬盘上不等于全部加载。OLLAMA_MAX_LOADED_MODELS=1 强制系统做出明确选择,并避免无意义的显存碎片化。

还需要面对一个现实:20B 到 35B 参数的量化本地模型非常有用,但在长工具链、模糊指令或可能包含 prompt injection 的内容上,它并不具备大型云模型同等的稳定性。

06Skills、MCP 与权限隔离

OpenClaw 区分了几个经常被混在一起的概念:

  • 模型:负责推理;
  • 工具:负责执行动作;
  • skill:告诉模型何时以及如何使用工具;
  • MCP 服务器:暴露来自外部应用的结构化函数;
  • Gateway:负责整体编排。

OpenClaw skill 本质上主要是一组 Markdown 指令,通常围绕一个 SKILL.md 文件组织。这并不意味着可以在不阅读内容的情况下安装任何 skill。

openclaw skills search "suno"
openclaw skills verify @machinesbefree/suno-browser-songmaking
openclaw skills verify @machinesbefree/suno-browser-songmaking --card
openclaw skills install @machinesbefree/suno-browser-songmaking

第三方 skill 在审查之前都应该被视为不可信。 即使它只包含指令,也可能要求浏览器访问已经登录的会话。我更愿意为相关服务使用专门的浏览器配置文件,而不是使用已经打开了邮件、客户账号和其他应用的日常 Chrome 配置文件。

我的主要集成

  • gog:以脚本方式访问 Gmail、Calendar、Drive、Docs、Sheets 和 Contacts。
  • Himalaya:根据账号类型,通过 IMAP、SMTP、Gmail 或 Microsoft Graph 管理邮件。
  • Home Assistant MCP:读取家庭自动化上下文并执行已授权的动作。
  • Patrick MCP:读取任务、项目和休假。
  • Browser automation:与没有合适 API 的 Web 服务交互。
  • blogwatcher:监控信息、分析来源并准备博客主题。

我会尽量把只读集成和能够写入或触发动作的集成分开。一个读取日历的工具不需要发送邮件的权限,一个 Suno workflow 也不需要 Home Assistant 管理员 Token。

07通过 gog 使用 Gmail 和 Google Workspace

Google Workspace 部分,我使用 gog。这是一个面向脚本和 Agent 设计的 CLI,提供稳定命令,并输出便于处理的 JSON 或简单文本。

示例:

gog gmail search 'newer_than:7d' --max 20
gog calendar events --today
gog drive ls --max 20 --json

认证基于 OAuth。授权范围必须限制在真正需要的服务,Token 必须保存在系统钥匙串或专用秘密存储中,绝不能放进 prompt、Git 仓库或日志文件。

第一个 workflow 会在每天早晨分析过去 24 小时收到的邮件:

  1. 搜索新邮件;
  2. 过滤明显噪音;
  3. 总结重要主题;
  4. 提取动作和截止日期;
  5. 把动作与 Patrick 中已有项目关联;
  6. memory/YYYY-MM-DD-email-summary.md 中生成持久摘要;
  7. 向移动 node 发送通知。

我从只读模式开始。只有在确认提取结果稳定,而且模型不会把每句话都当成紧急任务之后,才会启用自动创建任务或发送回复。

08使用 Patrick IA 提供业务上下文

Patrick 是我的团队管理助手。它集中保存任务、项目、会议纪要、休假和部分业务上下文。

我已经写过一篇完整文章介绍它的工作方式: Patrick IA:团队管理助手

OpenClaw 使用的 MCP 集成主要暴露以下只读工具:

patrick-read__get-person-open-tasks
patrick-read__get-project-operational-context
patrick-read__get-team-upcoming-time-off

查询某个人的任务时,只需要名字;Agent 不需要向用户索要 UUID。

这个集成让 OpenClaw 可以回答类似问题:

  • “这个人有哪些未完成任务?”
  • “IFS 项目的当前业务上下文是什么?”
  • “下周谁会休假?”
  • “邮件中识别出的动作是否已经存在于 Patrick 中?”

选择只读接口是有意为之。未来如果 OpenClaw 可以直接创建或修改任务,这些工具会被单独隔离,并采用更严格的规则。

09Home Assistant:自然语言控制与暴露范围

Home Assistant 现在提供官方 MCP 服务器,地址为 /api/mcp。MCP 客户端可以访问 Assist API 工具和已授权实体的上下文。

在我的架构中,本地 MCP bridge 可以监听专用内部端口,再把调用转发给 Home Assistant。这个端口不能暴露到互联网。

最关键的是访问控制:

  • 尽可能使用专门的 Home Assistant 用户;
  • 只向 Assist 明确暴露所需实体;
  • 不允许访问无关 domain;
  • 门锁、车库门或其他敏感动作必须有额外规则,不能直接暴露;
  • 记录重要调用。

这样就可以执行自然语言命令:

  • “关闭客厅灯光”;
  • “热泵现在是什么状态?”;
  • “启用夜间模式”;
  • “告诉我主要房间的温度”。

Suno 场景被有意设计成另一套边界。 即使 OpenClaw 在其他用途上能够调用 Home Assistant,晨间歌曲 workflow 也不会获得任何 Home Assistant Token。它只使用一个本地、专用且难以猜测的 webhook。这样即使浏览器或 Suno skill 出错,影响范围也会大幅缩小。

10Frigate:区分人脸识别与生成式视觉

Frigate 在本地完成目标检测和人脸识别。识别成功后,它会通过 MQTT 发布 frigate/tracked_object_update 消息,其中包括:

{
  "type": "face",
  "id": "...",
  "name": "Jeanne",
  "score": 0.95,
  "camera": "camera_cuisine",
  "timestamp": 178...
}

Frigate 必须继续作为人物身份的事实来源。Qwen VL 之类的视觉模型可以描述场景、服装、包裹或环境,但不应该仅凭一张图片猜测某个人是谁。

因此,我把流程分成两条 pipeline:

  • 身份识别:由 Frigate、本地人脸库、识别分数和已知摄像头负责。
  • 可选语义描述:由本地视觉模型丰富通知,例如“一个穿红色外套、手里拿着包的人”。

这种区分可以避免一个常见错误:询问 LLM“图片里是谁?”,然后把它的回答当成事实。生成模型可能产生幻觉,而 Frigate 输出的是结构化的姓名、分数和摄像头标识。

在敏感自动化中,我始终过滤:

  • 事件类型;
  • Frigate 返回的真实技术名称;
  • 精确摄像头;
  • 可配置的最低分数;
  • 需要时使用的区域。

11核心案例:Jeanne 的晨间歌曲

这可能是我整个系统中最“没有必要地复杂”、但也最好玩的自动化。

每天夜里,OpenClaw 会为 Jeanne 准备一首原创歌曲。早晨,歌曲并不会在固定时间自动播放。Home Assistant 会等待 Frigate 通过厨房中的唯一指定摄像头识别到 Jeanne,然后才在同一房间的 Google Cast 上播放歌曲。

02:00
OpenClaw
   |
   +--> 最近 30 首歌曲历史
   +--> 早晨天气
   +--> 概念 + 歌词 + 风格
   +--> 已登录的 Suno 浏览器
   +--> 生成与选择
   +--> 下载 MP3
   +--> 本地存储 + HTTP URL
   +--> POST Home Assistant webhook
                         |
                         v
                   今日歌曲已准备

06:30 - 10:30
厨房 Frigate 摄像头
   |
   +--> type = face
   +--> name = Jeanne
   +--> score >= 0.80
                         |
                         v
                 Home Assistant
                         |
                         +--> 每天只播放一次
                         +--> 厨房 Google Cast

11.1 非常明确的安全边界

OpenClaw 只负责:

  • 创建歌曲;
  • 与 Suno 交互;
  • 下载文件;
  • 在本地提供 MP3;
  • 通过 webhook 发送通知。

Home Assistant 只负责:

  • 等待早晨时间段;
  • 处理 Frigate MQTT 事件;
  • 识别 Jeanne;
  • 检查授权摄像头;
  • 检查允许时间窗口;
  • 防止重复播放;
  • 控制音量和厨房 Google Cast。

OpenClaw 从不直接控制 Google Home,也不会获得任何 Home Assistant 管理员 Token,更不会自己尝试识别 Jeanne。

11.2 安装并检查 Suno skill

我不使用任何第三方 Suno API。@machinesbefree/suno-browser-songmaking skill 通过持久浏览器会话自动操作 Suno 网站。

openclaw skills verify @machinesbefree/suno-browser-songmaking
openclaw skills install @machinesbefree/suno-browser-songmaking

这个 skill 本质上是一份浏览器操作 runbook:收集创作简报、编写歌词、切换自定义模式、填写歌词与风格标签、启动生成并检查结果。

我为 Suno 使用专门的浏览器配置文件。如果需要重新登录,我会在这个配置文件中手动完成。Agent 永远不会收到明文密码。

11.3 在 02:00 安排定时任务

OpenClaw 自带 Cron 调度器。任务由 Gateway 保存,因此 Gateway 重启后仍然存在。

一个隔离任务的示例:

openclaw cron create "0 2 * * *" \
  --name "Jeanne - 晨间歌曲" \
  --session isolated \
  --tz "Europe/Paris" \
  --exact \
  --model "ollama/muse-glimmer:latest" \
  --tools "browser,exec,read,write" \
  --timeout-seconds 3600 \
  --message "执行已经记录的 Jeanne 每日歌曲创建 workflow。只进行一次真实生成,必须读取历史记录,保存到本地,完成 HTTP 检查后再发送 webhook 通知。"

任务使用隔离会话,避免污染主对话。Timeout 被有意设置得较长,因为通过 Web 服务完成生成和下载可能需要较多时间。

11.4 让每天的歌曲真正不同

最难的不是生成一首歌,而是避免每天只换三个词却生成几乎相同的歌曲。

每次运行都会读取持久历史记录,例如:

{
  "date": "2026-08-20",
  "title": "Jeanne 和会跳迪斯科的蜘蛛",
  "story": "一只蜘蛛教 Jeanne 跳魔法舞",
  "characters": ["Jeanne", "迪斯科蜘蛛"],
  "style": "儿童迪斯科放克",
  "weather": "晴天",
  "filename": "2026-08-20-jeanne-spider-disco.mp3",
  "media_url": "http://<OPENCLAW_SERVER>:8088/music/jeanne/2026/08/..."
}

在创建新概念之前,Agent 至少检查最近 30 首歌曲,并特别关注最近七天的内容。

它会避免:

  • 连续两天使用同一主题;
  • 重复相同音乐风格;
  • 重复相同中心角色;
  • 重复相同故事结构;
  • 重复副歌和常用句式。

大约每五首歌中有一首应使用完全原创的世界观。Jeanne 喜欢女巫、蜘蛛、小熊、魔法故事、冒险和一些熟悉的作品世界,但 prompt 从不要求复制现有歌曲、歌词、旋律或某位艺术家的精确风格。

早晨天气只作为灵感:

  • 下雨:魔法雨靴、水坑和青蛙;
  • 晴天:花园、宝藏和野餐;
  • 刮风:风筝或云中旅行;
  • 下雪:小熊和雪城堡;
  • 有雾:有趣的魔法森林。

即使天气数据不可用,也必须继续生成歌曲。灵感来源不能变成强制性的故障点。

11.5 歌词与音乐描述

歌词使用法语,为五岁儿童编写,目标时长为两到三分钟。

推荐结构:

简短前奏
第一段主歌
副歌
第二段主歌
副歌
桥段
最后副歌
结尾

整体语气保持快乐、有趣、安心和充满魔法。女巫、蜘蛛或怪物可以出现,但必须是友好或搞笑的角色。

音乐风格会明显变化:儿童流行、流行摇滚、迪斯科、放克、合成器流行、摇摆、欢乐爵士、民谣、童话音乐、管弦冒险或轻电子音乐。

11.6 存储并提供 MP3

文件不能只下载到硬盘。它还必须通过 HTTP 提供,因为 Chromecast 需要直接获取文件。

目录结构:

/srv/openclaw/music/
└── jeanne/
    └── 2026/
        └── 08/
            └── 2026-08-20-jeanne-spider-disco.mp3

使用 Docker 中 Nginx 的最小 HTTP 服务器示例:

services:
  jeanne-music:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "8088:80"
    volumes:
      - /srv/openclaw/music:/usr/share/nginx/html/music:ro

最终 URL 例如:

http://<OPENCLAW_LAN_IP>:8088/music/jeanne/2026/08/file.mp3

端口只能从 LAN 访问。Volume 以只读方式挂载,并且不会暴露服务器上的其他目录。

在调用 Home Assistant 之前,OpenClaw 会检查 URL 是否正常响应,以及 MIME 类型是否允许 MP3 播放。

11.7 不提供 Token 的情况下通知 Home Assistant

Webhook 不会立即触发播放,它只负责宣布当天歌曲已经准备好。

{
  "date": "2026-08-20",
  "title": "Jeanne 和会跳迪斯科的蜘蛛",
  "media_url": "http://<OPENCLAW_IP>:8088/music/jeanne/2026/08/file.mp3",
  "filename": "file.mp3",
  "style": "儿童迪斯科放克",
  "story": "Jeanne 遇到一只热爱跳舞的蜘蛛",
  "weather": "晴天"
}

测试命令:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "date":"2026-08-20",
    "title":"Jeanne 测试",
    "media_url":"http://<OPENCLAW_IP>:8088/music/jeanne/test.mp3"
  }' \
  "http://<HOME_ASSISTANT_IP>:8123/api/webhook/<RANDOM_SECRET>"

Home Assistant 端:

trigger:
  - platform: webhook
    webhook_id: !secret suno_daily_webhook_id
    allowed_methods:
      - POST
    local_only: true

Webhook 标识必须足够长、随机,并像密码一样管理。它绝不能出现在文章、公开仓库或截图中。

11.8 Home Assistant 状态机

Home Assistant 至少保存以下状态:

  • input_boolean.suno_daily_enabled
  • input_boolean.suno_daily_ready
  • input_boolean.suno_daily_played
  • input_text.suno_daily_title
  • input_text.suno_daily_media_url
  • input_text.suno_daily_date
  • input_number.suno_daily_volume
  • input_number.suno_daily_face_score
  • input_datetime.suno_daily_start_time
  • input_datetime.suno_daily_end_time

初始值:

  • 音量:35%;
  • 最低人脸分数:0.80;
  • 开始时间:06:30;
  • 结束时间:10:30;
  • 每天只播放一次。

Webhook 检查收到的日期是否为当天,保存标题和 URL,启用 ready,并把 played 重置为 false。

每天 00:05 的自动化会重置状态。如果夜间生成失败,系统不会错误地重新播放前一天的歌曲。

11.9 只在厨房识别到 Jeanne 时触发

MQTT trigger 监听:

frigate/tracked_object_update

逻辑条件严格等价于:

type == "face"
AND name == FRIGATE_FOR_JEANNE_ACTUAL_VALUE
AND camera == KITCHEN_CAMERA_9_ACTUAL_VALUE
AND score >= configurable_threshold
AND time between 06:30 and 10:30
AND song ready
AND song date == today
AND song not played
AND kitchen Google Cast available

摄像头、Jeanne 或 media_player 的技术名称绝不能凭空猜测。安装时必须从 Frigate 和 Home Assistant 中读取真实值。

以下情况不会触发任何播放:

  • 识别到 Louis;
  • 识别到其他人;
  • 只有普通 person 检测;
  • 在其他摄像头识别到 Jeanne;
  • 识别分数不足;
  • 事件发生在允许时间之外;
  • 歌曲日期过旧或已经播放。

11.10 防重复与 race conditions

Frigate 可能在几秒内发布多次识别事件。如果两个执行同时启动,简单的 played == false 条件并不总是足够。

更稳健的策略组合包括:

  • Home Assistant 自动化使用 mode: single
  • 可选但推荐的临时 in_progress 锁;
  • 独立播放 script;
  • 短暂等待播放器进入 playing 状态;
  • 只有在发送播放命令之后,才把 played 设为 true。

播放 script 会:

  1. 选择厨房 Google Cast;
  2. 设置音量;
  3. 调用 media_player.play_media
  4. 使用收到的 URL;
  5. 在播放器支持时提供歌曲标题。

11.11 错误处理

  • Suno 不可用:夜间合理重试。
  • 会话过期:干净停止,并要求手动重新登录。
  • 生成失败:重试,但不能无控制地消耗 credits。
  • 下载失败:重新下载,不要重新生成歌曲。
  • HTTP 服务器不可用:文件可读取之前,不通知 Home Assistant。
  • Webhook 不可用:保留 MP3,只重试通知。
  • 夜间任务失败:绝不能静默地用昨天的歌曲替代今天的歌曲。

12用 OpenClaw 做技术监控和博客助手

OpenClaw 也可以成为我的技术监控入口:跟踪 OpenClaw、Ollama、Home Assistant、Frigate、IFS 或 PC SOFT 的新变化,找到已经写过的主题,并准备选题列表。

我不希望它自动发布文章。它可以:

  • 收集来源;
  • 发现变化;
  • 把新主题与旧文章关联;
  • 准备文章结构;
  • 标记需要核实的事实;
  • 提出初稿。

最终发布仍然是人工动作,因为事实错误或误解不应该自动变成公开文章。

13安全、隐私与缩小影响范围

Agent 最大的风险不是它“很聪明”,而是它拥有太多权限。

我的主要规则包括:

  • Gateway 不直接暴露到互联网;
  • 远程访问使用 WireGuard 或其他 VPN;
  • Ollama 限制在 LAN 中并经过过滤;
  • 第三方 skills 安装前必须验证并阅读;
  • 自动化服务使用专用浏览器配置文件;
  • OAuth 凭据和 Token 保存在钥匙串或秘密管理器中;
  • 工作与家庭用途使用分离的 agents 和 workspaces;
  • 写入工具与读取工具分开;
  • Home Assistant 只允许访问已暴露实体;
  • Suno webhook 只允许本地 POST,且不使用 HA Token;
  • 本地日志采用受控保留时间;
  • Git、prompt 和文章中都不保存任何秘密。

本地模型并不能消除 prompt injection 风险。 邮件、网页或文档可能包含试图劫持 Agent 的指令。模型越小或量化越激进,就越应该限制可用工具,并在高影响动作前保留人工确认。

14本地 Agent 的真实限制

128k 上下文成本很高

大上下文有利于长任务,但会显著增加 KV cache 消耗。q4_0 量化帮助它装入显存,但这是一个明确的折衷。

本地模型并不总能替代大型云模型

在简单对话中,muse-glimmer 在我的环境里表现很好。但面对大量工具的复杂 Agent,本地模型可能循环、忘记约束或错误理解结果。

移动 nodes 会消耗电量

定位、运动、采集和通知功能依赖操作系统权限。当手机积极限制后台应用时,这些能力可能被削弱。

OAuth 和 Web 会话会过期

Gmail、Google Workspace 和 Suno 都可能要求重新认证。好的自动化应该清晰停止,而不是试图绕过登录页面。

本地基础设施需要运维

服务、备份、磁盘、显存、更新、证书和日志都需要监控。云服务隐藏了其中一部分工作,本地部署则把这些工作重新交还给你。

15这套架构真正改变了什么

当我不再把 OpenClaw 当作聊天界面,而是把它当作编排器时,它才开始真正产生价值。

Ollama 提供本地推理。OpenClaw 提供会话、定时任务、工具和浏览器。Home Assistant 保留家庭自动化决策权。Frigate 继续负责识别。Patrick 提供业务上下文。Suno 在明确边界内生成音乐。

每个组件都有自己的责任,更重要的是,每种集成都有不同的信任等级。

最终结果不是一个拥有全屋管理员 Token 的全能助手,而是一组有限、可观察、可替换的 workflows。

这可能是最重要的经验:要让 Agent 真正有用,不要一开始就给它所有权限。先从一个明确需求、一条清晰边界、一个可复现测试和一种简单停止方式开始。

重点总结

  • OpenClaw 是 Gateway 和编排器;Ollama 仍然是推理引擎。
  • 我的 AI 服务器使用两张 12 GB RTX 3060,并配置 128k 上下文。
  • 主模型保持加载八小时,同时只加载一个大模型。
  • OpenClaw 应使用 Ollama 原生 API,不要添加 /v1 后缀。
  • 第三方 skills 必须在安装前验证并阅读。
  • gog 为 Gmail 和 Google Workspace 提供适合 Agent 的接口。
  • Patrick MCP 提供任务、项目和休假上下文。
  • Home Assistant MCP 只暴露真正需要的实体。
  • Frigate 是人脸识别的事实来源;视觉 LLM 只负责描述或丰富信息。
  • Jeanne 的歌曲在 02:00 生成,本地存储,然后通过 webhook 通知 Home Assistant。
  • 只有厨房摄像头 9 识别到 Jeanne 时才会触发歌曲。
  • 歌曲只在 06:30 到 10:30 之间通过厨房 Google Cast 播放,每天一次。
  • 这个 Suno workflow 中,OpenClaw 不会获得任何 Home Assistant Token。
  • 架构是 local-first,但 Gmail 和 Suno 仍然是明确识别的云服务。

资料与文档

本文描述的是个人架构,并且示例已经主动匿名化。IP 地址、实体 ID、摄像头技术名称、Token 和秘密必须针对每套安装单独确定,绝不能从公开文章中直接复制。

模型名称和大小只是我当前环境的一个快照。OpenClaw、Ollama、Frigate 和 Home Assistant 的目录变化很快,请始终查阅实际安装版本对应的文档。

人脸识别、摄像头和图片保留策略必须结合具体用途、相关人员、系统安全以及适用于你所在场景的义务进行配置。