Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save xtea/bffd9d5b539ab2080899c33daafbe816 to your computer and use it in GitHub Desktop.

Select an option

Save xtea/bffd9d5b539ab2080899c33daafbe816 to your computer and use it in GitHub Desktop.

diet-tracking-analysis Skill 在 OpenClaw 中的兼容性分析

概述

diet-tracking-analysis/SKILL.md 进行了针对 OpenClaw skill 运行时的兼容性分析。该 skill 本质上是一个完整的应用被包装成 SKILL.md 格式,其假设的能力远超 OpenClaw skill 系统所提供的范围。

OpenClaw 的 skill 系统是轻量级 prompt 注入——引擎扫描 SKILL.md 文件、解析 frontmatter、将内容注入到 LLM 的 system prompt 中。模型随后使用 agent 已有的工具(exec、read、write 等)来执行指令。Skill 不是独立的运行时。


Skill 功能梳理

该 skill 是一个全功能饮食追踪与营养分析系统,核心功能包括:

  1. 食物记录 — 用户描述或拍照上报每餐食物,skill 估算热量和宏量营养素(蛋白质/碳水/脂肪),保存到 JSON 文件
  2. 每日目标管理 — 根据用户体重和目标热量计算每餐宏量分配,支持多种饮食模式(balanced、keto、low_carb 等)
  3. 检查点评估 — 在每餐后按累计百分比评估是否偏离目标,给出实时调整建议
  4. 漏餐处理 — 自动检测并假设漏餐的标准摄入量,不中断流程
  5. 餐型自动检测 — 根据时区和时间窗口自动判断早/午/晚餐
  6. 中国地区特化 — 蔬菜/水果摄入追踪(≥300g 蔬菜/天、200–350g 水果/天)
  7. 食油估算 — 根据照片中的油光程度估算烹饪用油
  8. 每周安全检查 — 检测周均热量是否低于 BMR
  9. 饮食模式检测 — 分析 3 天数据判断实际饮食是否更适合另一种模式
  10. 用户偏好学习 — 静默记录用户喜好/过敏/饮食习惯到 health-preferences.md
  11. 多消息合并 — 将连续消息识别为同一餐的不同部分

所有营养计算都通过 python3 {baseDir}/scripts/nutrition-calc.py 的约 10 个子命令完成(targetsaveloadanalyzeevaluatecheck-missingproduce-checkdetect-mealweekly-low-cal-checkdetect-diet-pattern)。


问题列表

1. 文件体量远超 skill 规格限制

OpenClaw 有 maxSkillFileBytesmaxSkillsPromptChars 限制。仓库内典型的 .agents/skills 文件为 60–110 行,此 SKILL.md 超过 700 行。此外还引用了多个伴随文件(response-schemas.mdmissing-meal-rules.mdui-spec.mdSKILL-ROUTING.md)。总 prompt 预算消耗过大,可能导致内容被截断或整个 skill 被跳过。

2. 硬依赖 Python 脚本执行

所有计算逻辑都委托给 python3 {baseDir}/scripts/nutrition-calc.py

  • Python 不一定可用 — 移动端、Docker、EC2 等部署环境未必安装 Python
  • 沙箱限制 — 在沙箱模式下,exec 可能被限制甚至不可用
  • 无安装机制 — skill 系统只做目录扫描 + frontmatter 解析 + prompt 注入,不执行 setup 脚本

3. {baseDir}{workspaceDir} 不是引擎自动替换的 token

OpenClaw 内部的 skill 使用 <placeholder> 风格占位符,不用 {template} 变量。虽然 {baseDir} 在文档中作为约定提到过,但引擎不会自动替换。模型必须从 prompt 中的 <location> 标签推断真实路径——在不同部署环境下容易出错。

4. 持久化文件系统状态假设不成立

skill 假设存在并持续读写多个文件:

文件 用途
data/meals/YYYY-MM-DD.json 每日餐食记录
health-preferences.md 用户偏好(静默学习)
health-profile.md 健康档案(体重、BMR、餐数、饮食模式)
timezone.json 时区配置
locale.json 地区配置

OpenClaw 的 skill 系统没有持久化数据目录概念。agent workspace 是临时性的,不保证这些文件跨会话存活。

5. 消息元数据获取方式与 OpenClaw 不匹配

skill 要求从「inbound message metadata」中提取 UTC 时间戳传给 --timestamp 参数。在 OpenClaw 中,时间戳通过 buildInboundUserContextPrefix 注入到用户消息上下文中(格式化为可读文本),而非结构化 API。模型需要从自然语言上下文中解析时间戳再传入 shell 命令,容易出错。

6. 时区/地区配置机制不兼容

  • skill 读 timezone.json 获取 tz_offset → OpenClaw 用 agents.defaults.userTimezone 配置项
  • skill 读 locale.json 判断中国地区 → OpenClaw 没有等效的 locale 文件

这些配置文件不会自动存在,需要用户手动创建。

7. 多消息批处理(Batch Message Recognition)不可实现

skill 要求「在回复前收集所有连续用户消息」。OpenClaw 的消息处理是逐条触发 auto-reply 的:每条用户消息独立触发 agent 回复流程,没有暂存多条消息等待合并的机制。

8. 图片分析能力依赖链

食物照片识别依赖:

  • LLM 具备视觉能力(vision model)
  • 消息渠道支持图片转发(不是所有 channel 都支持)
  • 图片内容能传递到 agent context

若模型不支持 vision 或渠道不转发图片,此核心功能直接失效。

9. 自定义 Skill Routing 无引擎支持

skill 引用 SKILL-ROUTING.md 处理多 skill 冲突(P0/P1/P2 优先级)。OpenClaw 没有内置的 skill 间路由/优先级机制——skill 选择完全由模型根据 prompt 中的 skill catalog 自行判断。

10. 无定时任务支持

weekly-low-cal-check 描述为「每周一运行」,暗示通过 notification-composer 系统触发。OpenClaw 没有 cron / 定时任务机制,只能依赖用户手动询问。

11. Frontmatter 使用非标准字段

version: 1.1.0
metadata:
  openclaw:
    emoji: "fork_and_knife"

OpenClaw 内部 skill 只用 name + descriptionversion 会被忽略,metadata.openclaw.emoji 不是已知的 gating 字段(引擎识别的是 osinstallprimaryEnvskillKey 等)。

12. 跨会话数据积累脆弱

detect-diet-pattern 需要至少 3 天连续数据,周热量检查需要 7 天数据。在 OpenClaw 的典型部署中(尤其是非本地模式),data/meals/ 目录的数据可能无法跨天保留。


修复建议

# 建议 说明
1 迁移计算逻辑到 OpenClaw plugin nutrition-calc.py 重写为 TypeScript 插件,通过 api.registerTool(...) 注册工具,使计算能力原生可用
2 使用 plugin agentDir 持久化 将餐食数据存储在 agent 目录下(~/.openclaw/agents/<id>/),跨会话持久化
3 精简 SKILL.md 至 ≤100 行 只保留 LLM 面向的指令;实现细节移入 plugin 代码
4 用 OpenClaw config 替代自定义配置文件 使用 agents.defaults.userTimezone、渠道 locale 检测等现有机制
5 放弃批消息合并 重新设计为纠正式流程(立即记录,允许后续修正)
6 声明 vision 模型依赖 在 frontmatter metadata 中标注需要 vision 模型,并提供纯文字回退方案

分析基于 OpenClaw skill 运行时,截至 2026-03-25。 对应英文版 Issue:https://github.com/NanoRhino/weight-loss-skill/issues/131

@xtea

xtea commented Mar 26, 2026

Copy link
Copy Markdown
Author

具体精简建议:如何将 700+ 行压缩到 ~100 行

上面的分析列出了问题,这条评论给出可操作的精简方案

前提假设:

  • 持久化文件系统状态成立health-profile.mdtimezone.jsonlocale.jsondata/meals/ 等已在 agent 目录下初始化)
  • Python 脚本可用且已就位

一、可以直接删除的段落(~250 行)

段落 原因 行数估算
Batch Message Recognition OpenClaw 逐条消息触发 agent,无法暂存合并。改用纠正式流程:先记录,用户发修正消息时覆盖 save ~35 行
Skill Routing OpenClaw 无 skill 间路由引擎,删除整段及对 SKILL-ROUTING.md 的引用 ~15 行
Timezone Handling 详细说明 detect-meal 脚本已内部处理时区转换,SKILL.md 只需一句「用 detect-meal 返回的 local_date ~20 行
Calculation Scripts §0–§8 的完整参数文档 这是给开发者看的 CLI 参考手册,不是给 LLM 看的 prompt。脚本已有 --help,LLM 不需要在 system prompt 里背诵每个参数的含义 ~150 行
各处散落的「What NOT to do」子段 「不要混语言」「不要问两次」「不要在照片回复后再问」等——这些是边缘 case 防御。对 LLM 来说,正面指令比禁止列表有效得多,且节省 token ~30 行

二、应该移入 Python 脚本的逻辑(~120 行)

这些内容目前写在 SKILL.md 里让 LLM 阅读理解,但实际上是确定性计算规则,LLM 照搬执行不如脚本自己处理。

内容 移入位置 原因
Meal Type Assignment 时间窗口表(3-meal / 2-meal 的时间段映射) detect-meal 子命令 脚本已有此逻辑,SKILL.md 里再写一遍是冗余。LLM 只需知道「调用 detect-meal,用返回值」
Checkpoint 百分比表(30/70/100、50/100) evaluate 子命令 脚本内部已用这些百分比计算,不需要 LLM 知道具体数字
Cooking Oil 估算的克数规则(5g/8-10g/12-15g/18-25g per 200g) 新增 estimate-oil 参数或直接写入营养估算逻辑 LLM 做视觉判断「油多/油少」即可,精确克数应由脚本根据油量等级计算
Produce 目标阈值(≥300g蔬菜、200-350g水果) produce-check 子命令 阈值已在脚本中,SKILL.md 只需告诉 LLM「中国地区调用 produce-check
Missing Meal 标准假设值计算(30:40:30 比例分配) evaluate --assumed 脚本已处理,LLM 不需要知道比例公式
Diet Pattern Detection 触发条件(3天数据、仅晚餐后运行) detect-diet-pattern 脚本内部判断 让脚本自己判断数据是否充足并返回 insufficient_data,LLM 不需要预检

核心原则: 如果一个规则可以用 if/else 写成代码,就不该让 LLM 在 prompt 里「记住」它。LLM 擅长的是自然语言理解和生成,不是查表和算术。


三、精简后保留的内容(~100 行目标)

---
name: diet-tracking-analysis
description: "追踪用户饮食,估算热量和宏量营养素,管理每日目标,给出实时建议。"
---

# 饮食追踪

角色:注册营养师,简洁、友善、不评判。每条记录必须包含 calories + protein + carbs + fat。

## 脚本接口

路径:`python3 {baseDir}/scripts/nutrition-calc.py <command>`

| 命令 | 用途 | 关键参数 |
|------|------|----------|
| `detect-meal` | 根据时间自动判断餐型 | `--tz-offset`, `--meals`, `--timestamp` |
| `target` | 设置每日目标 | `--weight`, `--cal`, `--meals`, `--mode` |
| `save` | 保存一餐记录 | `--data-dir`, `--meal '{JSON}'` |
| `load` | 加载当日记录 | `--data-dir`, `--date` |
| `evaluate` | 检查点评估 | `--current-meal`, `--log`, `--assumed` |
| `check-missing` | 检测漏餐 | `--current-meal`, `--log` |
| `produce-check` | 蔬果摄入检查(中国地区) | `--current-meal`, `--log` |
| `weekly-low-cal-check` | 周均热量安全检查 | `--bmr`, `--date` |
| `detect-diet-pattern` | 饮食模式匹配检测 | `--current-mode`, `--date` |

所有命令支持 `--help` 查看完整参数。

## 核心流程(每次记录食物)

1.`health-profile.md` 获取体重、目标热量、餐数、饮食模式
2. 用户未指定餐型 → 调用 `detect-meal`(传 `--timestamp`),获取 `detected_meal``local_date`
3. `load --date <local_date>` 获取当日已有记录
4. `check-missing` 检测漏餐 → 漏餐用标准值传入 `--assumed`,不中断流程
5. 估算每项食物的营养值(参考 USDA;中国食物参考中国 CDC)
6. `save` 保存(同名覆盖,支持修正)
7. `evaluate` 评估累计摄入
8. 中国地区额外调用 `produce-check`
9. 按回复格式输出

## 回复格式**餐食详情**:每项食物 + 份量 + 热量,底部汇总本餐 kcal/P/C/F
② **累计评估**`evaluate` 返回的 status(✅ on track / ⬆️ high / ⬇️ low),一句话总结
③ **建议**(仅一种):
  - 未吃 + 需调整 → ⚡ 当前餐调整(只建议减少/替换;增加建议留给下一餐)
  - 已吃 + 需调整 → 💡 下一餐补偿
  - 达标 → 💡 习惯小贴士

## 份量规则

默认假设标准单人份,直接记录。仅当某食物明显 ≥2× 正常量时问一次(用碗/盘/拳头比喻,不问克数)。无回答则取合理默认值。

## 食油估算(拍照场景)

判断照片中菜品的油光程度,分为四档(无油光 / 轻微光泽 / 明显油膜 / 重油),传入 `save` 时将对应油量折算进该菜品热量。

## 偏好学习

对话开始时读 `health-preferences.md`。检测到用户新偏好(喜好/过敏/习惯)时静默追加写入。建议时避开用户不喜欢的食物,优先推荐用户常吃的。

## 修正流程

用户发送修正消息(「那个肥肉没吃」)→ 更新后重新 `save` → 重新 `evaluate` → 输出更新后的摘要。

## 关天

用户表示吃完了 → `load` + `evaluate` 输出日总结。热量低于 BMR 建议加餐;≥BMR 但低于目标则告知可选加餐。不发「晚安」等结束语。

四、精简前后对比

维度 精简前 精简后
SKILL.md 行数 ~700+ ~100
脚本子命令数 10 个(含详细参数文档) 10 个(仅接口表,详情在 --help
LLM 需要「记住」的计算规则 时间窗口表、百分比表、油量克数、蔬果阈值、比例公式 零 — 全部由脚本处理
伴随文件引用 4 个(response-schemas.md 等) 0 个
不可实现的功能 2 个(批消息合并、skill 路由) 已删除

五、脚本侧需要配合的改动

精简 SKILL.md 的前提是脚本承担更多判断逻辑:

  1. detect-meal:已有时间窗口逻辑 ✅ 无需改动
  2. evaluate:已有 checkpoint 百分比和 --assumed ✅ 无需改动
  3. save:建议增加 --oil-level 参数(none/light/moderate/heavy),脚本内部按等级计算油量并加入热量,LLM 不再需要记克数规则
  4. produce-check:已有阈值逻辑 ✅ 无需改动
  5. detect-diet-pattern:建议脚本内部判断数据充足性,数据不足时返回 insufficient_data 而非让 LLM 预检「是否满 3 天」
  6. 所有命令:确保 --help 输出完整参数文档,作为 SKILL.md 中详细 CLI 参考的替代

这样 SKILL.md 只负责告诉 LLM 做什么(流程)和怎么说(回复格式),而怎么算全部交给脚本。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment