2026-03-13 18:44:53
本文仅代表个人观点浅谈 OpenClaw
我并不是在否定 OpenClaw 的价值。相反,我觉得它很有意思,也确实能解决一部分真实需求。但如果问题是“它更适合谁”,我的答案很明确:它更适合小白用户,而不是开发者。
很多人讨论 Agent 产品时,习惯把“能不能做事”和“适不适合我”混在一起。OpenClaw 当然能做事,这点没有问题。问题在于,它完成任务的方式,决定了它更像是一个降低门槛的消费级入口,而不是一个让开发者长期依赖的高效工作流系统。
对小白用户来说,OpenClaw 的价值非常直接。用户不用写代码,不用自己搭工具,只需要把任务说出来,系统就会尽量去完成。哪怕过程不够优雅,哪怕中间有些试探和冗余,只要最后能把事情做完,它就已经创造了价值。
但开发者看问题通常完全不一样。开发者会本能地问几个更现实的问题:这个流程稳定吗?能重复吗?值得长期跑吗?是不是每次都要重新消耗大量 Token 才能完成?如果一个系统的能力很难沉淀、很难复用、很难控制成本,那么它对开发者的吸引力就会迅速下降。
我觉得很多人会高估 OpenClaw 自身的“智力”。它当然有自己的工程价值,比如调度、交互、工具编排、上下文组织,但真正决定上限的,通常还是底层模型本身。
换句话说,OpenClaw 聪不聪明,很多时候并不是 OpenClaw 决定的,而是你给它接了什么模型决定的。模型越强,它看起来越聪明;模型越弱,它的表现就越容易不稳定。
而这会直接引出一个现实问题:好的模型往往特别贵。
至少在 2026 年第一季度 这个阶段,我并不认为我们已经进入了一个可以完全忽略 Token 成本的时代。高质量模型依然很贵,长上下文依然很贵,频繁调用依然很贵。OpenClaw 这类产品又不是一次调用就结束,它往往要持续观察、持续判断、持续规划、持续执行。每多一步,都意味着更多 Token 消耗;如果还夹杂网页浏览、截图理解、页面状态判断和失败重试,成本会被进一步放大。
更关键的是,大量消耗 Token 也不一定能解决问题。模型更贵,不代表任务就一定更稳定;上下文更长,也不代表它一定更理解网页现在到底发生了什么。很多时候它只是花了更多钱,在一个缺少结构化接口的环境里反复试错。
这也是为什么我一直觉得,至少在当前阶段,开发者不可能完全不考虑 Agent 的成本结构。未来当然可能不一样,也许 Token 会便宜到几乎可以忽略不计。但至少今天,尤其是在 2026 Q1,这还不是现实。
我现在很明确的一点是,OpenClaw 不应该被当成“什么问题都值得调用一次”的万能入口。
如果你只是想问一句:“现在 New York 的天气怎么样?”那在我看来,这类任务交给 OpenClaw 几乎没有意义。更直接的方法显然是打开 Google 搜索,或者直接看天气 App。这个问题既不复杂,也不需要多步骤执行,更不需要 Agent 去规划、调用工具、理解上下文。
所以我认为,OpenClaw 的初衷本来就不应该是替代搜索框。它真正应该发挥价值的地方,是那些需要多个步骤、多个工具、多个状态切换的复杂任务。比如跨几个系统整理信息,根据中间结果继续决策,在一组受限工具之间完成完整流程。这类任务才是 Agent 的主场。
如果只是把它用来回答一些原本一秒钟就能搜索得到答案的问题,那不仅没有发挥出 Agent 的优势,反而会放大它在成本、延迟和执行冗余上的问题。
OpenClaw 里我最认同的一部分,其实就是 Skills。
没有 Skills 的 Agent,很多时候只是一个会读页面、会操作浏览器、会尝试点击按钮的模型外壳。它也许能完成任务,但过程通常成本高、不稳定,而且对上下文极度依赖。Skills 的价值就在于,把一部分高频能力封装起来,让 Agent 不用每次都重新猜。
但问题也非常明显:Skills 再重要,也不可能完整。
真实世界的工作流是不断变化的。今天你要处理邮件,明天你要筛选简历,后天你又可能要同步 Notion、发 Slack、监控小红书、抓取某个内部后台。只要场景在变,新的能力封装就会一直出现。你不可能指望一个技能仓库在某一天突然“完整”。
而这里就出现了一个很现实的矛盾:
Skills。也就是说,小白用户是受益者,开发者却往往是那个需要不断填坑、不断补工具的人。
从这个角度说,OpenClaw 更像一个把复杂性转移给开发者、再把便利性交给普通用户的系统。它不是没有价值,但它的价值分配,本身就是偏向非开发者的。
很多 Agent 产品喜欢展示浏览器自动化,因为它很直观,也很像“人类在操作电脑”。模型打开网页、截图、识别界面、判断应该点击哪里,然后一步步往下走。这个演示通常很好看。
问题是,好看不等于高效。
比如你让 OpenClaw 去监控小红书的帖子,如果平台没有公开 API,那么它大概率只能通过访问网页、不断截图、判断页面状态、决定下一步点哪里,最后再把结果返回给你。
这种方式的问题并不是“做不到”,而是它在工程上很不经济:
开发者对这种模式通常会天然不耐烦。因为这本质上是在用模型推理去弥补工程接口的缺失。如果一个任务需要靠模型反复截图、反复理解、反复尝试,才能勉强做完,那它多半不是一个好的长期解法。
一次性的任务也许还能接受,但如果这是一个长期、重复、每天都要跑的任务,开发者首先想到的通常不会是“让 Agent 每天重新看图和思考”,而是“我要不要直接为这个场景做一个专门的工具”。
我自己做 MailClaw,其实就是在解决同一类问题:如果一个 Agent 需要处理邮件,最优解到底是什么?
如果走浏览器路线,Agent 当然可以登录网页邮箱,搜索邮件、阅读邮件、筛选发件人、导出内容,甚至模拟点击删除。但这个方案太重了,也太浪费。
所以在 MailClaw 里,我选择的是另一条路:
mailclaw CLI,支持 macOS、Linux、Windows。这样一来,Agent 如果要“读邮件”,就不需要打开浏览器,不需要截图,不需要观察网页结构,也不需要一边看页面一边决定下一步该怎么点。它只需要执行类似下面的命令:
mailclaw list --q partnership --json
mailclaw get clx123abc --json
或者直接调用 API:
GET /api/emails
GET /api/emails/export
GET /api/emails/:id
从 Agent 的角度看,这种设计的优势非常明显:输入更结构化,输出更结构化,速度更快,成本更低,可重复性更强,权限控制也更清晰。
这也是为什么我后来在 MailClaw 的 Skill 设计里,刻意让 Skill 去调用本地 CLI,而不是让它直接拿浏览器或者 curl 到处拼请求。因为在我看来,Skill 最好的角色不是替代工具,而是成为工具的入口。
前者意味着你把复杂能力堆进 Skill 里,让模型现场发挥;后者意味着你先把真正稳定的能力做成 API、CLI 或服务,再让 Skill 去发现、调用和编排。对开发者来说,显然后者更可靠,也更经济。
这也是我对 OpenClaw 最核心的看法:它的问题不在于 Agent 不够聪明,而在于很多场景下,它缺少一个足够强、足够低成本、足够结构化的工具层。
如果工具层不存在,OpenClaw 就只能退回到“看页面、猜页面、操作页面”的通用模式。这个模式当然灵活,但它也意味着高 Token 消耗、高不确定性,以及很差的工程沉淀效率。你当然可以不断换更强的模型、接受更高的账单,但结果未必线性变好。因为真正的问题未必是“模型不够聪明”,而可能是“任务根本没有被工具化”。
开发者通常会更愿意做这些事情:
从这个意义上说,OpenClaw 对开发者当然不是完全没用。它仍然可以是一个不错的交互层、调度层,甚至是原型验证工具。你可以先让 Agent 帮你跑通一个流程,再观察哪些地方值得被固化成真正的程序。
但如果一个开发者长期依赖 OpenClaw 去做所有事情,而不是把高频能力沉淀成工具,那么最后很可能得到的是一个“看起来什么都能做,实际上哪里都不够经济”的系统。
所以我的观点还是那句:OpenClaw 更适合小白用户,而不是开发者。
对小白用户来说,它最大的价值是降低门槛。哪怕背后过程不够优雅,只要能把事情做完,就是价值。
但对开发者来说,OpenClaw 更适合扮演“外层入口”,而不是“最终执行层”。开发者真正应该投入精力的,不是让 Agent 在浏览器里多走几步,而是尽快把高频场景抽象成稳定的 API、CLI 或服务。
Skills 很重要,但它不应该是能力本身。它更像是能力的索引、说明书和调度接口。真正决定效率上限的,仍然是你背后有没有一个足够好的工具系统。
未来也许会不一样。也许有一天,Token 会便宜到几乎可以忽略不计,浏览器式 Agent 的高消耗不再值得在意。到了那个时候,也许今天很多批评都会失效。
但至少在 2026 年第一季度,我不认为现实已经走到那一步。今天的开发者仍然需要在效果、稳定性、速度和成本之间做平衡。而在这个平衡里,盲目消耗更多 Token,通常不是最优解。
对于开发者来说,这部分 Token 预算,很多时候已经足够拿来创造一个全新的工具了。
2026-03-02 04:22:30
I finally replaced my old comment setup and moved everything to a new system built by myself.
The result is simple: my blog is now fully running on Cloudflare.
This post explains why I migrated from Artalk, what I built, and how the migration worked.
Artalk is a great project, and it worked well for me for a long time. I used it as a reference while redesigning my own system.
But I wanted tighter control over:
So instead of extending Artalk, I built a focused API-first comment service for my own use case.
The current architecture is intentionally minimal.
The frontend is custom, integrated into my Hugo theme, and styled to keep the previous reading experience close to what I had before.
No separate admin panel or heavy UI dependency in the backend. The Worker exposes clean endpoints for posting comments, listing comments, and stats.
Each comment keeps parent_id, root_id, and depth, and public listing supports page-based pagination.
AUTO_APPROVE controls default behavior:
AUTO_APPROVE=false: new comments are pendingAUTO_APPROVE=true: new comments are approved immediatelyIn both modes, Telegram notifications are sent.
Approve / Spam / Delete
Spam / Delete
Reserved admin emails are blocked from public submission, so regular users cannot pretend to be the site owner.
Avatar URLs are generated from email via Gravatar hash.
For network metadata, the system uses api.ipinfo.es and stores country, ASN, and related fields in D1. Country display uses full country name and a separate country code for flags.
API timestamps are normalized to include timezone offsets, so old imported comments and new comments use a consistent format.
I migrated historical comments from an Artalk export file (.artrans) into D1.
High-level process:
.artrans to D1-compatible SQL with a converter script.This gave me a smooth transition without losing old threads.
I wanted one platform for everything.
Now the entire blog stack is inside Cloudflare:
No extra VM, no extra database vendor, no mixed ops stack.
This system is built for my blog first, but the architecture is reusable.
The most important part for me is that I now control the full comment pipeline end to end: data model, moderation workflow, frontend behavior, and deployment.
Migrating from Artalk was straightforward once the converter and D1 migrations were in place.
2026-02-14 14:46:19
现在正在 湘南新宿ライン 的 Green Car,前段时间从「上野(御徒町)」去「房総半島」玩,奇怪的发现我来回支付的价格不一样,而且最关键的是完全违背常理。
其中在「錦糸町」出站,支付了 ¥167,之后从「錦糸町」入站直接到「富浦」出站,支付了 ¥1980,合计 ¥2147。
直接从「富浦」入站,到「御徒町」出站,支付了 ¥2310。
细心的朋友已经发现问题了。我连续计费从头坐到尾的价格竟然比出站之后重新入站更贵。也就是说你坐的路程越长,单价并不一定更低,这完全违背了基本常识。
这是一个非常经典的 JR 运费计算"Bug"(其实是由于运费区间的阶梯定价机制造成的)。
简单来说,你"出站再进站"的操作,正好让你避开了一个昂贵的运费跳档。
这里是具体的数学拆解:
1. 核心原因:运费的"阶梯"跳得太高了
JR 东日本的运费是按里程分段计价的。随着距离增加,每一段的价格会跳涨。你正好处于一个临界点上:
锦糸町 > 富浦 的距离大约是 118 km
御徒町 > 锦糸町 的距离大约是 4.4 km
2. 连续计费的陷阱
当你不出站,直接从 富浦 > 御徒町 时,里程是累加的:
3. 算一笔账
| 方式 | 价格计算 | 总价 |
|---|---|---|
| 分段买 | 1,980 (长途) + 167 (短途) | 2,147 日元 |
| 连续买 | 升级到下一档运费 | 2,310 日元 |
差价原因:
JR 的运费表里,从"101-120km"升级到"121-140km"这一档,价格一口气涨了 330 日元 (2,310 - 1,980)。
而你实际多坐的那段路(锦糸町-御徒町)单独买只需要 167 日元。
因为 330 > 167,所以被系统"自动升级"到下一档反而更贵,手动拆开反而便宜。这在 JR 的运费体系中属于一种已知现象,通常发生在长途旅行刚好卡在某个运费区间边缘,再多坐几公里就会触发"大额跳档"的时候。
2026-01-05 21:48:57
日本的 SAKURA Internet Inc. (AS9370) 即使在近些年大不如前,但仍然因为其 IP 质量(接近日本家庭宽带),再加上无限流量,备受玩家喜爱。当然这家的机子也并不好买,需要日本的真实地址,以及日本的手机号。
主播在大概半年之前注册了一个 SAKURA 和 WebARENA Indigo 帐号,一直在使用 SAKURA VPS,一直存在的问题就是从中国到日本根本跑不满限速的 100Mbps。因为存在国际 QoS 的问题。
这个方案也一样适用于 Indigo。简单来说,就是用一台主流的商宽 VPS (比如 GreenCloudVPS) 和 SAKURA 建立 GRE 隧道,然后将国际入站的流量先到 GreenCloudVPS,再从 GreenCloudVPS 的 GRE Tunnel 到 SAKURA,这样就能绕过 SAKURA 的国际 QoS 了。
玩 GRE Tunnel 的前提是你的云服务商没有禁用 Protocol 47。
在两个服务器上加载 GRE module:
sudo modprobe ip_gre
echo "ip_gre" | sudo tee -a /etc/modules
例如服务器 A 公网 IP:23.191.8.1,服务器 B 公网 IP:23.191.8.2。内网地址:10.0.0.1 和 10.0.0.2。
接下来在服务器 A 上添加一个 GRE 接口:
nano /etc/network/interfaces
auto tun-gre
iface tun-gre inet static
address 10.0.0.1
netmask 255.255.255.252
pre-up ip tunnel add tun-gre mode gre remote 23.191.8.2 local 23.191.8.1 ttl 255
post-up ip link set dev tun-gre mtu 1450
post-down ip tunnel del tun-gre
在服务器 B 上同样添加 GRE 接口:
nano /etc/network/interfaces
auto tun-gre
iface tun-gre inet static
address 10.0.0.2
netmask 255.255.255.252
pre-up ip tunnel add tun-gre mode gre remote 23.191.8.1 local 23.191.8.2 ttl 255
post-up ip link set dev tun-gre mtu 1450
post-down ip tunnel del tun-gre
测试 GRE Tunnel 是否成功:
在服务器 A 上:
ping 10.0.0.2
像我这样就是成功了,而且两个服务器之间有着非常优秀的网络质量。
ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=1.79 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=1.80 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=1.89 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=1.83 ms
64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=1.77 ms
64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=1.88 ms
64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=1.68 ms
64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=1.87 ms
64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=1.81 ms
64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=1.92 ms
64 bytes from 10.0.0.2: icmp_seq=11 ttl=64 time=1.71 ms
64 bytes from 10.0.0.2: icmp_seq=12 ttl=64 time=1.77 ms
64 bytes from 10.0.0.2: icmp_seq=13 ttl=64 time=1.99 ms
64 bytes from 10.0.0.2: icmp_seq=14 ttl=64 time=1.71 ms
^C
--- 10.0.0.2 ping statistics ---
14 packets transmitted, 14 received, 0% packet loss, time 13021ms
rtt min/avg/max/mdev = 1.680/1.814/1.987/0.083 ms
最后只要配置 nftables 将流量从服务器 A 的 GRE Tunnel 转发到服务器 B 的 GRE Tunnel 即可。
nano /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table ip my_proxy_forward {
# 处理入站 DNAT
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
# 将发往 A:32767 的流量转发到 B 的隧道地址 10.0.0.2
tcp dport 32767 dnat to 10.0.0.2
udp dport 32767 dnat to 10.0.0.2
# 将发往 A:26002 的流量转发到 B 的隧道地址 10.0.0.2
tcp dport 26002 dnat to 10.0.0.2
udp dport 26002 dnat to 10.0.0.2
}
# 处理出站 SNAT (Masquerade)
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
# 确保回程流量通过隧道:
# 当流量发往 B 的隧道 IP 时,将源地址改为 A 的隧道 IP (10.0.0.1)
ip daddr 10.0.0.2 oifname "tun-gre" masquerade
}
}
最后启动 nftables 即可
sudo nft -f /etc/nftables.conf
2025-11-19 20:27:50
To prevent my server IP from being blocked by the GFW (Great Firewall), I wanted to ensure that my server is only accessible from outside mainland China. The most effective way to achieve this is by adding firewall rules to block all inbound traffic from Chinese IP addresses.
While iptables with xt_geoip has been a popular choice for years, nftables is the modern replacement in the Linux ecosystem. However, nftables lacks built-in support for GeoIP or MMDB (MaxMind Database) lookups out of the box. To bridge this gap, we need a way to generate nftables-compatible IP sets from a GeoIP database.
In this post, I’ll share a tool I built to automate this process: Auto Update MMDB. It automatically fetches the latest GeoLite2 data, extracts Chinese network ranges, and generates the necessary nftables configuration files.
I created a simple Go utility called auto-update-mmdb. It performs the following tasks:
GeoLite2-Country.mmdb.nftables set files (cn4.nft and cn6.nft).nftables to apply the changes.You can find the source code on GitHub: missuo/auto-update-mmdb.
First, we need to install the tool. You can build it from source using Go:
git clone https://github.com/missuo/auto-update-mmdb.git
cd auto-update-mmdb
go build -o /usr/local/bin/auto-update-mmdb
Once installed, you can run it manually to generate the initial IP sets:
sudo /usr/local/bin/auto-update-mmdb
This will create the following files:
/usr/share/GeoIP/GeoLite2-Country.mmdb/etc/nftables.d/cn4.nft/etc/nftables.d/cn6.nftIP addresses change over time, so it’s important to keep the database updated. We can use a systemd timer to run the update daily.
Create a service file /etc/systemd/system/auto-update-mmdb.service:
[Unit]
Description=Auto Update GeoLite2 MMDB
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/auto-update-mmdb
And a timer file /etc/systemd/system/auto-update-mmdb.timer:
[Unit]
Description=Auto Update GeoLite2 MMDB Daily
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the timer:
sudo systemctl daemon-reload
sudo systemctl enable --now auto-update-mmdb.timer
Now that we have the IP sets ready, we can use them in our nftables configuration.
Edit your /etc/nftables.conf. You need to include the generated files and then reference the sets (@cn4 and @cn6) in your rules.
Here is a complete example that blocks traffic from China on a specific port (e.g., 2333), while allowing other traffic:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
# Import the generated IP sets
include "/etc/nftables.d/cn4.nft"
include "/etc/nftables.d/cn6.nft"
chain input {
type filter hook input priority 0;
# Allow loopback and established connections
iifname "lo" accept
ct state established,related accept
# Block SSH (port 22) from China
tcp dport 22 ip saddr @cn4 drop
tcp dport 22 ip6 saddr @cn6 drop
# Block China IPs on port 2333 (TCP & UDP)
tcp dport 2333 ip saddr @cn4 drop
udp dport 2333 ip saddr @cn4 drop
tcp dport 2333 ip6 saddr @cn6 drop
udp dport 2333 ip6 saddr @cn6 drop
# Allow everything else by default
accept
}
}
If you want to block all inbound traffic from China, you can simplify the rules:
# Drop all traffic from China
ip saddr @cn4 drop
ip6 saddr @cn6 drop
After modifying the configuration, restart nftables to apply the rules:
sudo systemctl restart nftables
By combining nftables with a simple automation tool, we can effectively manage geolocation-based firewall rules without relying on legacy tools or complex dependencies. This setup ensures your server remains inaccessible from specific regions while keeping the IP database up-to-date automatically.
2025-09-29 16:40:43
IDP 是 International Driver’s Permit 的缩写,也就是我们常说的“国际驾照”。它被全世界范围内的大部分国家认可,也就是说你有了 IDP 就可以在全世界大部分国家租车和开车。然而中国人几乎无法获得 IDP,原因稍后我会说。淘宝上常见的 IAA 严格意义上只不过是一个高级的翻译件而已,并没有什么用,另外请注意大部分的代办 IDP 都是给你办的假的,请不要浪费钱,更不要使用假的 IDP。
存在两种 IDP 的原因是因为存在两种道路交通公约,分别是 1949 年的《日内瓦道路交通公约》和 1968 年的《维也纳道路交通公约》。大部分国家都加入了 1949 年的公约,中国没有加入,中华民国(台湾)加入了。
大部分国家只承认 1949 年的日内瓦公约的 IDP,而 1968 年的维也纳公约的 IDP 认可度比较低,1949 年的 IDP 有效期为一年,而 1968 年的 IDP 有效期为三年。
目前可知的情况是使用 1968 年的 IDP 并不能在日本开车,但是在韩国可以。
If you plan to drive in Japan, you will need an international driver’s license based on the Road Traffic Convention of September 19, 1949 (Geneva Convention).
以上来自 NIPPON RENT A CAR 的官网。
原因其实也很简单,当初中国并没有加入日内瓦道路公约,只有签约国才有资格签发 IDP。而中华民国(台湾)加入了日内瓦道路公约,所以台湾人可以获得 IDP。更有趣的是中华民国(台湾)加入了两个公约,可以任意选择需要有效期更长的 1968 年 IDP 或是有效期一年的 1949 年 IDP。更特别的是台湾驾照在日本租车开车仅需日文翻译件。
中国人获得 IDP 的方式只有去海外,比如之前的去济州岛考韩国驾照换 IDP,现在已经走不通了。又或者在中国驾照换香港驾照,香港驾照再换澳洲驾照,澳洲驾照再换 IDP,现在似乎也已经走不通的。目前可行的是,中国驾照在美国的部分州换美国驾照,再去 AAA 换 IDP(似乎只能签发 1949 年版本),仅需 $20。有些国家对于 IDP 的签发有身份要求,好在 AAA 只是一个协会,并不在乎你是什么身份,另外值得一提的是 NJ 的 MVC 也并不关心你是什么身份,即使是非法移民也拥有同等的获得驾照的权利。

灰色部分是不承认 IDP 的国家和地区。(非洲和南美洲部分地区以及中国大陆不能使用 IDP 开车)