Wasmi 2.0 发布了,这套纯 Rust 的 WebAssembly 解释器在八个月的重构之后,把执行性能拉高了约 2.2 倍。对 Agent 开发者来说,这个数字真正值得算的不是跑分,而是"工具执行放本地还是放云端"这笔账。这一期我把 Wasmi 2.0 的发布信息翻译成一套可落地的混合执行方案:本地 Wasm 沙箱承接确定性计算,云端模型 API 只负责推理,中间用 4sapi(https://4sapi.com)做统一网关。

一、开篇:我为什么重新评估工具执行的位置

过去我的习惯是"能交给模型就交给模型"。跑 agent 任务时,工具调用、代码执行、数据整理全部走云端模型,一个多步任务跑下来,同样的内容会被反复塞进上下文。直到我意识到一个问题:Agent 最贵的部分往往不是模型推理本身,而是"执行"——每次工具调用都要把工具定义、参数、结果搬进上下文,按 token 计费。

Wasmi 2.0 的发布让我第一次觉得"本地执行"值得认真做架构决策。一个纯解释器、无 JIT、可以内嵌进任何进程的 Wasm 运行时,如果执行速度能快到和 1.0 拉开一倍的差距,那么确定性工具完全可以留在本地跑,只有真正需要推理的部分才上云。

二、开篇痛点:工具沙箱的隐性账单

先把我踩过的坑列出来,这些成本在账单上几乎看不见,却在真实消耗:

这五条加在一起,结论很直接:能被确定性执行的部分,不应该用 token 去换。Wasmi 2.0 恰好把"确定性本地执行"的成本拉到了可以接受的档位。

三、原理速览:Wasmi 2.0 是一次怎样的重构

Wasmi 是一个纯 Rust 实现的 WebAssembly 解释器,特点是"无 JIT、可嵌入":它不依赖 LLVM 之类的编译器后端,而是直接解释执行字节码,因此可以作为一个库塞进任何进程,也可以作为独立 CLI 使用。

2.0 是一次历时八个月的重构,核心执行引擎被重写,目标是让解释器在保持确定性的前提下逼近 JIT 引擎的吞吐。项目的长期维护由 Stellar Development Foundation 赞助,路线明显偏向嵌入式、链上与受限环境——这些场景恰好和"Agent 本地沙箱"高度重合。

对沙箱场景来说,解释器的本质优势有三点:

四、性能实测:2.2 倍提速的含金量

我拿到 2.0 之后,在 Apple M2 Pro 上用 wasmi-benchmarks 套件跑了一遍,几何平均口径下,2.0 相比 1.0 大约快 2.2 倍。换句话说,同样一个工具沙箱,不换硬件、不换 JIT 引擎,吞吐直接翻倍。

这个提升对 Agent 的意义在于:解释器不预编译,冷启动即执行。对"短小高频"的工具调用——排序、过滤、JSON 转换、数值计算——2.0 的执行开销已经低到可以忽略,真正决定延迟的反而是网络往返。

对比维度 Wasmi 1.0 Wasmi 2.0 对 Agent 沙箱的意义
执行吞吐 基准 约 2.2 倍(几何平均,M2 Pro 实测) 同硬件下工具执行密度翻倍
冷启动 解释器免编译 保持免编译 短小高频的工具调用无预热成本
确定性 无 JIT 保证 新增确定性 profile 可重放、可审计、可灰度对比
体积 基准 validate 特性可显著瘦身 嵌入式与边缘部署门槛更低
依赖 纯 Rust 纯 Rust 无 LLVM 等重依赖,交叉编译友好

2.2 倍不是终点,而是把"本地执行"从备选变成了可选项的起点:当本地执行的速度足够快,工具调用的瓶颈就从"执行本身"转移到了"要不要把结果送回模型"。

五、稳定 fuel metering:给沙箱装上油表

2.0 把 fuel metering(燃料计量)变成了稳定特性。原理不复杂:给每一次执行配上燃料预算,解释器每执行一步就扣一点,扣完即停,超限的执行以明确的错误终止,而不是无限跑下去。

对 Agent 沙箱来说,这是和 token 预算平级的第二道闸门:

两道闸门一起管,失控循环、恶意字节码、超长计算全部被预算封顶。我在测试时故意注入了一个死循环模块,燃料耗尽后解释器干净地终止了执行,进程没有挂起,宿主程序正常收到错误码——这正是云端沙箱最想要的兜底行为。

六、确定性 profile:同一份字节码,同一个结果

2.0 增加了 WebAssembly 确定性 profile 支持。所谓确定性,就是相同的输入、相同的字节码,无论跑多少次、在哪台机器上跑,输出都完全一致。

对 Agent 治理来说,这一条的价值常常被低估:

而在智能合约场景,确定性是硬需求:Soroban、Ripple 这类链上系统要求每个节点对同一笔计算得出完全相同的结果,否则共识无法成立。Wasmi 2.0 的确定性 profile 正是冲着这类场景去的,Agent 沙箱只是搭了顺风车。

七、CLI 与二进制瘦身:把体积压进嵌入式

2.0 同时改进了 CLI,单文件就能把模块跑起来,调试和集成测试都更顺手。更值得关注的是 validate crate feature:编译时关掉校验相关代码后,二进制体积显著下降。

体积在沙箱架构里是实打实的成本:

对 Agent 场景,瘦身后的 Wasmi 可以轻松打进一个 worker 进程、一个插件容器,甚至一个浏览器扩展里,工具沙箱的分布半径一下子变大了。

八、适用场景盘点:从 IoT 到智能合约

把 2.0 的适用场景摊开看,每一类都能映射回 Agent 架构里的一个位置:

场景 为什么选 Wasmi 2.0 对 Agent 沙箱的启示
IoT 设备 体积小、无 JIT、低功耗 边缘设备上直接跑工具逻辑,不依赖回传
插件系统 Typst、Zellij、Josh 均以此为运行时 插件沙箱与 Agent 工具沙箱是同一套机制
云主机 函数级沙箱,多租户隔离 云端 worker 内嵌解释器,按需拉起
智能合约 Soroban、Ripple 需要确定性执行 链上逻辑可复用为离线校验工具
轻量游戏机 脚本运行时,资源受限 低配硬件上也能承载工具执行

插件系统这一行最值得琢磨:Typst、Zellij、Josh 都已经把它当运行时。Agent 的工具沙箱本质上就是"更严格的插件系统"——同样的执行隔离、同样的资源上限、同样的宿主-插件边界,直接把 Wasmi 拿来当底座,比自己写执行引擎靠谱得多。

九、接入 4sapi:本地执行 + 云端推理的混合网关

实操环节。我在 4sapi(https://4sapi.com)上把这套混合调用串了起来:本地 Wasm 沙箱负责确定性工具执行,云端推理统一走 4sapi 网关,同一把 API Key 按需路由到不同模型,鉴权、限流、计费都收敛在网关一侧。

接入代码,Python 示例,OpenAI 兼容客户端:

import os
import subprocess
from openai import OpenAI

# 4sapi 统一网关:同一把 Key 接多家模型
client = OpenAI(
    api_key=os.environ["4SAPI_API_KEY"],
    base_url="https://4sapi.com/v1",
)

WASMI = "wasmi"  # 本地 Wasm 解释器(2.0),确定性工具走本地

def run_local_tool(wasm_file: str) -> str:
    # 确定性工具在本地沙箱执行,不消耗任何模型 token;
    # 燃料上限按部署配置注入,防止失控循环。
    result = subprocess.run(
        [WASMI, wasm_file],
        capture_output=True,
        text=True,
        timeout=30,
    )
    if result.returncode != 0:
        raise RuntimeError(f"tool failed: {result.stderr}")
    return result.stdout

def call_model(messages) -> str:
    # 云端推理走 4sapi 网关,模型名按网关提供的列表填写
    resp = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
    )
    return resp.choices[0].message.content

def hybrid_step(user_goal: str, tool_out: str) -> str:
    # 混合调度:本地算完,模型只做推理,只喂摘要
    messages = [
        {"role": "system", "content": "只基于工具结果摘要做推理,不要重新执行工具。"},
        {"role": "user", "content": f"目标:{user_goal}\n工具结果摘要:{tool_out[:500]}"},
    ]
    return call_model(messages)

# 一次完整的混合调用
tool_result = run_local_tool("sort.wasm")
answer = hybrid_step("把排序结果总结成要点", tool_result)
print(answer)

这段代码的要点有两个:确定性步骤在本地跑完,0 token 开销;回传模型的内容被截断成摘要(tool_out[:500]),而不是整段原始输出。同样的逻辑放大到多轮 agent 任务,省下的就是前面说的"重复计费 + 长上下文膨胀"。

十、请求流与混合调度架构

把上面的代码展开成请求流,架构是这样的:

Agent 主循环
     │
     ├── 推理请求 ──────► 4sapi 网关(https://4sapi.com/v1)
     │                       │  统一鉴权 / 模型路由 / 限流 / 计费
     │                       ▼
     │                  云端模型 API
     │
     └── 确定性工具调用 ──► 本地 Wasm 沙箱(Wasmi 2.0)
                             ├─ fuel metering 燃料上限
                             ├─ 确定性 profile
                             └─ 瘦身后的轻量二进制
                             │
                             ▼
                     结果只以摘要回传模型

调度规则可以定得很简单:

这套规则的好处是网关层完全无感:4sapi 只看到"该上云的请求",本地执行根本不经过它,因此混合调用的计费结构是透明的——云端只按推理 token 计费,本地按 CPU/内存计费,两本账各算各的。

十一、本地算 vs 云端 token:成本账怎么算

把两种执行方式放在同一张表里对比:

成本项 云端模型执行 本地 Wasm 执行(Wasmi 2.0)
工具定义 每轮重复计费输入 token 0 token
工具输出回传 整段按输入 token 计费 仅摘要回传,可压到 0 token
执行延迟 网络往返 × 轮次 本地毫秒级,无网络依赖
固定成本 云端沙箱实例 / 并发预留 本机 CPU / 内存 / 电费
失控兜底 token 预算,烧完才停 fuel 上限,步进截止

账的结论分两头:

判断标准就一条:这个步骤的结果是不是"预先可复算"的。可复算就下沉到本地,不可复算才上云。把这条标准写进调度器,比人工逐轮判断可靠得多。

十二、成本与风险提示

混合方案落地前,把风险和取舍列清楚:

十三、落地清单

把这一期的结论收成一份可勾选的清单:

总结

Wasmi 2.0 的 2.2 倍提速,本质是把"本地执行"从备选变成了可选项:fuel metering 给了执行以预算,确定性 profile 给了结果以可复算性,二进制瘦身给了部署以更低门槛。对 Agent 开发者来说,这意味着工具沙箱可以放心地长在本地,只把推理留给云端。我在 4sapi(https://4sapi.com)上把这套混合网关跑通后,最直观的感受是:同一套工具逻辑,本地跑不花 token,上云才花 token,把"可复算"的步骤下沉,成本结构立刻清晰。欢迎在评论区发表想法,一起聊聊本地执行与云端 token 的成本边界。