AI 代理工作区中自动生成 state 文件的排查记录

背景 某 AI 代理工具的工作区目录中,反复出现一个状态文件。即使手动删除,过一段时间后文件仍会重新生成。 工作区中同时还能看到另一个隐藏目录下的状态文件。经过人工对比,这两个文件内容完全相同。于是问题变成了: 现象 工作区中存在两个状态文件: 其中顶层的 state 文件删除后会再次出现。隐藏目录中的 state 文件一直存在。 两个文件内容相同,JSON 结构也相同,主要记录工作区初始化状态,例如: 这些字段看起来不像用户数据,也不像配置密钥,而是程序用于判断工作区是否完成初始化的运行状态信息。 排查方式 排查过程中保持只读原则,没有删除、移动、修改文件,也没有重启服务。 主要检查方向包括: 排查结果 结果显示,这两个文件都属于工具正常运行会产生的文件,但地位并不完全相同。 顶层的状态文件是当前版本代码中的 canonical 路径,也就是当前主状态文件。 隐藏目录中的状态文件是 legacy 兼容路径,也就是旧路径或兼容路径。当前代码仍然会读取它,并在需要时把里面的状态迁移回顶层的 canonical 文件。 换句话说,这不是两个互相冲突的状态文件,而是同一份工作区状态在新旧路径之间共存。 为什么删除后还会出现 删除顶层状态文件后,如果隐藏目录中的 legacy 状态文件仍然存在,那么下一次工具启动、工作区初始化、代理会话创建或 heartbeat 触发时,程序会重新读取 legacy 状态。 如果程序发现顶层 canonical 状态文件不存在,就会根据 legacy 状态重新生成顶层文件。 因此,文件并不是“神秘复活”,而是程序的兼容迁移逻辑主动恢复了它。 可以理解为: 是否属于异常 从排查结果看,没有明显异常迹象。 两个文件内容一致,权限正常,字段结构正常,也没有发现异常进程或可疑写入行为。顶层文件比隐藏目录中的文件更新,说明当前程序确实更偏向使用顶层 canonical 文件,而隐藏目录中的文件更像历史兼容残留。 这种情况更像是软件版本迁移期间的兼容设计,而不是数据损坏或异常垃圾文件。 …

使用 systemd 为 AI 网关服务设置内存上限:从高峰占用到 6GB 硬限制

背景 某台小型 Linux 主机上运行着一个 AI 代理网关服务。该服务平时占用并不高,但在运行一段时间后,systemctl status 显示历史内存峰值曾达到约 5.5GB。 状态中可以看到类似结构: 这说明服务并不是单一进程,而是由主进程和若干子进程共同组成。若只限制某个 Node 进程,无法可靠覆盖整个服务组。更合理的方式是使用 systemd cgroup 资源限制,对整个 service 统一设置内存上限。 问题 该主机总内存约为 8GB,且没有启用 swap。AI 网关服务如果在高负载或异常情况下继续增长内存占用,可能导致系统进入异常状态,例如: 因此,需要给该服务设置一个最大内存使用上限。 目标不是修改应用源码,也不是给应用打补丁,而是通过系统服务管理器限制资源使用。 方案选择 最终采用的是 systemd 用户级 service drop-in 配置。 这种方式的特点是: 也就是说,这不是“打补丁”,而是系统层面的标准资源控制。 配置目标 最终设置为: 含义如下: 启用内存统计,让 systemd 记录该服务的内存使用情况。 软限制。服务内存超过 5GB 后,systemd 会开始施压、回收、限速,尽量避免继续膨胀。 硬限制。整个服务 cgroup 的内存占用不能超过 6GB。主进程和子进程合计计算。 如果服务因超出内存限制触发 OOM,systemd …

一次本地 AI 代理 HEARTBEAT 频率与新闻摘要格式的调整记录

背景 某本地 AI 代理系统已经开始定期执行 HEARTBEAT 任务,并能够通过邮件发送状态报告。整体执行链路已经跑通:任务可以被触发,邮件可以正常发出,收件端也能收到报告。 不过在实际使用后,暴露出两个需要调整的问题: 第一,HEARTBEAT 执行频率过高。默认频率约为 30 分钟一次,对于日常状态汇总来说过于密集,容易造成邮件噪音。 第二,新闻摘要任务的输出质量不理想。虽然系统能够抓取公开 RSS 新闻标题并生成邮件,但内容基本停留在“标题列表 + 固定占位摘要”的层面,缺少真正可读的摘要信息。 因此,这次调整主要围绕两个目标展开: 问题一:新闻摘要内容过于粗糙 原先的新闻邮件结构大致如下: 这种输出存在明显问题: 期望的格式是每条新闻形成一个小型三语新闻卡片,例如: 这种格式的优点是: 新闻摘要任务规则的修改 原来的任务说明只要求“发送一封简洁的中文新闻摘要邮件”,这会导致 AI 代理自然倾向于输出中文简报,而不是三语新闻卡片。因此,任务规则需要明确改写。 修改后的规则重点包括: 修改后的核心目标不是“多翻译几种语言”,而是让邮件本身变成可读、可用、可追溯的国际新闻摘要。 问题二:HEARTBEAT 默认频率过高 另一个问题是 HEARTBEAT 默认频率较高。系统状态检查本身已经正常执行,但 30 分钟一次对于当前用途来说没有必要。 经过只读检查后,确认当前系统并不是通过外部定时器或 cron 控制 HEARTBEAT,而是由 AI 代理自身的配置项控制。 检查结果显示: 因此,最终修改目标是: 修改方式 修改前先进行了 dry-run,确认配置写入动作可以被接受。 示意命令如下: dry-run 成功后,再实际写入: 系统返回配置已更新,但同时提示需要重启 …

用 Heartbeat 文件管理本地 AI 代理的每日邮件通知

背景 在本地部署 AI 代理之后,一个很自然的需求是让它承担一些低风险、可重复的日常检查工作。例如: 这些任务看起来都可以用传统脚本完成,例如写一个 Python 脚本,再配合 cron 或 systemd timer 定时执行。但如果本地 AI 代理本身已经内置了 Heartbeat 机制,那么更合理的做法不是再造一套外部自动化系统,而是把任务边界写进代理的 Heartbeat 配置文件,让代理自己按授权范围执行。 本文记录一次围绕 Heartbeat 文件、邮件通知和发件人显示名的整理过程。 Heartbeat 文件的定位 最初容易产生一个误解:Heartbeat 文件是不是一份普通说明文档? 实际检查后可以确认,它更适合被理解为: 本地 AI 代理的周期任务授权清单。 它不是长期记忆文件,也不是系统状态总表,更不是脚本。它的核心作用是告诉代理: 因此,Heartbeat 文件不应存放大量历史信息、主机清单、连接细节、密码、令牌、日志原文或临时排障内容。那些信息应该分别放在长期记忆文件、工具环境说明文件、每日记录文件或专门的配置文件中。 Heartbeat 文件只负责回答一个问题: 代理现在被授权定期做什么? 最初的需求 本次需求可以分成四类每日邮件: 要求是: 这样的需求非常适合写进 Heartbeat 文件。 不应该额外写一套完整脚本 一开始可以想到一种传统方案: 这套方案当然可行,但它有一个问题: 如果脚本自己完成全部工作,那么即使没有 AI 代理,也能收到邮件。 这就偏离了 Heartbeat 文件的真正用途。此时 …

在边缘节点上复刻服务器邮件通知环境:Postfix 本机中继方案实践

背景 在多台服务器和个人设备组成的运维环境中,系统通知邮件是一项非常基础但重要的能力。备份任务、定时任务、系统服务、自动化脚本和监控程序,都可能需要在异常发生时主动发出通知。 已有几台系统已经具备稳定的本机邮件发送能力。这些系统并不直接对外提供邮件服务,也不负责接收邮件,而是通过本机邮件程序把通知交给 Postfix,再由 Postfix 中继到外部 SMTP 服务器。新的边缘节点也需要具备同样的能力,以便后续承载系统通知、自动化任务提醒和本机代理程序通知。 目标不是搭建完整邮件服务器,而是搭建一个安全、轻量、统一的本机发信环境。 目标设计 最终目标如下: 该方案具备几个特点: 既有系统方案盘点 在正式搭建新节点之前,先对已有系统进行了只读检查。检查对象包括两类服务器节点和一台桌面工作站。 检查重点包括: 盘点结果显示,已有几台系统虽然发行版不同,但实际发信路径已经收敛到同一种思路: 其中,Debian/Ubuntu 系系统使用 hash:/etc/postfix/… 类型的 Postfix 映射文件;Arch 系系统则使用 lmdb:/etc/postfix/… 类型的映射文件。这一点非常重要,因为不同发行版的 Postfix 默认映射类型可能不同,不能直接照抄。 新节点是 Ubuntu 系统,因此更适合复刻 Debian/Ubuntu 系的 Postfix hash 方案,而不是照搬 Arch 系的 lmdb 方案。 为什么选择 Postfix,而不是 msmtp 轻量脚本发信可以使用 msmtp,但如果目标是让整个系统具备统一发信能力,Postfix 更合适。 原因包括: 因此,新节点采用: 而不是: 安全边界 该方案的安全边界非常明确: …

让本地 AI 代理接入 WordPress:从后台管理员到受控内容管理接口

在使用本地 AI 代理辅助运维和内容整理时,一个自然的问题会出现:能不能让 AI 代理直接连接到 WordPress 实例,用来管理分类、标签和博客文章? 答案是可以,但更重要的问题不是“能不能连接”,而是“应该以什么方式连接、授予多大权限、允许它做哪些操作”。 对于 WordPress 来说,最稳妥的方式并不是让 AI 代理像真人一样打开浏览器、登录后台、点击菜单完成操作,而是通过 WordPress 提供的 REST API 进行内容管理。这样既更稳定,也更容易控制权限边界。 一、不要把 AI 代理当成人类后台管理员 很多人第一反应是给 AI 代理一个 WordPress 管理员账号,让它登录后台,然后管理文章、分类和标签。 这种方式虽然直观,但并不理想。 后台网页界面是给人使用的,页面结构、按钮位置、插件界面、主题设置都可能变化。AI 代理如果通过浏览器模拟人工操作,稳定性会比较差,也容易误点。更重要的是,如果直接使用高权限管理员账号,一旦代理执行了错误操作,影响范围可能非常大。 更推荐的方式是:把 AI 代理视为一个外部内容管理程序,通过 WordPress REST API 与站点通信。 这样做的好处是: 二、推荐接入方式:REST API + Application Password WordPress 自带 REST API,可以通过接口读取和写入内容。例如: 为了让外部程序安全访问 WordPress,可以使用 WordPress 的 …

一次便携式 Linux 设备 Wi-Fi 与 USB 共享网络冲突的排查与修复

背景 某台便携式 Linux 设备同时具备两种联网方式: 系统中原本有几类自定义辅助脚本: 其中,连接脚本用于扫描并连接 Wi-Fi,断开脚本用于手动断开 Wi-Fi。系统本身则启用了 dhcpcd,用于统一管理 DHCP、IP 地址、DNS、默认路由和 metric 优先级。 最初发现的问题 一次系统自检中发现,设备上同时存在 dhcpcd 和 dhclient,并且二者都在处理同一个无线接口。 这类情况容易造成网络栈混乱: 同时还观察到: 这里的一个重要教训是:自动化代理可以帮助收集信息,但安全和网络相关结论必须回到原始命令输出核对。尤其在高权限环境下,不能让代理在未经确认的情况下直接执行修复、重启服务或修改网络状态。 需求澄清 这台设备不是固定服务器,而是便携式设备,因此网络策略与普通服务器不同。 实际需求可以概括为: 因此,不适合让 Wi-Fi 连接脚本同时负责 Wi-Fi 认证、DHCP 请求、DNS 更新和默认路由修改。更合理的分工是: 只读排查 正式修改前,先进行只读检查,重点确认当前到底有哪些网络组件在运行: 同时检查自定义脚本内容: 检查结果表明,dhcpcd 已经在系统中启用并运行,而旧版 Wi-Fi 连接脚本中仍然包含类似逻辑: 这意味着脚本在启动 Wi-Fi 认证后,又手动释放 DHCP、重新请求 DHCP,并修改默认路由。这样会与 dhcpcd 的职责重叠,形成“双网络管理器”冲突。 根因 根因不是 Wi-Fi 本身,也不是 USB …

一次 OpenClaw Gateway 迁移后的安全自检与问题收尾记录

背景 某台小型 Linux 主机上运行着 OpenClaw Gateway,作为个人运维辅助入口使用。该实例经历过一次迁移和配置调整,迁移后需要确认几件事: 本次排查的原则是只读优先:先通过 systemd、journal、监听端口、配置目录和进程状态确认现状,不直接修改、不删除、不重启。只有当证据明确显示配置变更需要重启生效,且重启本身也能释放内存压力时,才执行服务重启。 初始自检结论 自检首先确认了几个基础事实: 这说明迁移后的实例基本可用,不属于“服务没起来”或“运行了错误实例”的情况。 不过自检也发现了几个需要继续收尾的问题: 这些问题并不等于实例不可用,但说明迁移后仍需要做一轮细化确认。 问题一:trusted proxy warning 的真正含义 日志中最容易误判的一条 warning 是: 表面看,这像是某个内网地址访问了 OpenClaw,并携带了代理头。进一步查看完整上下文后,发现实际情况并不是“路由器直接访问了 Gateway”。 真正的连接关系是: 日志中的关键信息可以分成两类: 其中: 因此,应该加入 trustedProxies 的不是路由器地址,而是本机 loopback 地址。 正确方向是: 不应在证据不足的情况下把路由器地址加入 trusted proxy。因为当前证据只说明路由器地址出现在 forwarded header 中,并不是它直接连接 OpenClaw Gateway。 问题二:配置变更需要重启才能生效 设置 gateway.trustedProxies 后,日志出现了新的提示: 这说明 OpenClaw 已检测到配置变化,但该项不能热重载,必须重启 Gateway 才能生效。 这里有一个重要判断: …