OpenClaw Skill 适合固化可重复的 Agent 行为。Minitally Skill 可以只暴露一个清晰动作:把用户确认过的消费信息写入 Minitally。
实际落地有两种方式:
- 环境能安装 Node.js 和 CLI 时,直接走 Minitally CLI。
- 环境不能安装 CLI 时,走一个 Python 脚本。
两种方式都从环境变量读取 MINITALLY_API_KEY 和 MINITALLY_API_BASE。
Skill 结构
可以创建这样的目录:
minitally-record-expense/
SKILL.md
scripts/
add_expense.pySKILL.md 保持短而严格:
# Minitally Record Expense
Use this skill when the user asks to record a spending or income item in Minitally.
Before writing:
- Confirm the amount.
- Identify whether it is expense or income.
- Preserve the user's original note.
- Ask if the amount, currency, or budget-exclusion status is unclear.
Preferred path:
- If `minitally` CLI is available, call it.
- Otherwise run `python3 scripts/add_expense.py`.
Never print `MINITALLY_API_KEY`.CLI 方式
如果 Skill 运行环境能执行 CLI,命令保持简单:
minitally expense add --amount 38 \
--note "OpenClaw skill lunch test" \
--merchant "Noodle House" \
--request-id "openclaw-skill-20260507-001"当前源码版本可以用:
pnpm --filter @minitally/cli dev expense add --amount 38 \
--note "OpenClaw skill lunch test" \
--merchant "Noodle House" \
--request-id "openclaw-skill-20260507-001"Python 脚本兜底
脚本只用 Python 标准库,适合限制较多、无法安装 CLI 的环境:
#!/usr/bin/env python3
import json
import os
import sys
import urllib.error
import urllib.request
def arg_value(name, default=None):
if name not in sys.argv:
return default
index = sys.argv.index(name)
if index + 1 >= len(sys.argv):
return default
return sys.argv[index + 1]
api_key = os.environ.get("MINITALLY_API_KEY")
base_url = os.environ.get("MINITALLY_API_BASE", "https://mn.hekmon.com").rstrip("/")
if not api_key:
raise SystemExit("MINITALLY_API_KEY is required")
payload = {
"amount": float(arg_value("--amount", "0")),
"type": arg_value("--type", "expense"),
"note": arg_value("--note", ""),
"counterparty": arg_value("--counterparty", arg_value("--merchant", "")),
"requestId": arg_value("--request-id", ""),
}
if "--exclude-from-budget" in sys.argv:
payload["excludeFromBudget"] = True
request = urllib.request.Request(
f"{base_url}/api/v1/expenses",
data=json.dumps(payload).encode("utf-8"),
headers={
"accept": "application/json",
"content-type": "application/json",
"authorization": f"Bearer {api_key}",
"x-minitally-agent-channel": "cli",
},
method="POST",
)
try:
with urllib.request.urlopen(request, timeout=20) as response:
print(response.read().decode("utf-8"))
except urllib.error.HTTPError as error:
print(error.read().decode("utf-8"), file=sys.stderr)
raise SystemExit(error.code)在 Skill 中调用:
python3 scripts/add_expense.py \
--amount 38 \
--note "OpenClaw skill lunch test" \
--merchant "Noodle House" \
--request-id "openclaw-skill-20260507-001"执行规则
- 每个 OpenClaw workspace 使用单独的 API Key。
- 每次写入都设置 request id。
- 用户说“把刚才那笔记一下”时,如果上下文里可能已经写过,先搜索再创建。
- 只有用户明确说报销、代垫、转账类或不计入预算时,才使用
--exclude-from-budget。

