当 Agent 从“回答问题”走向“参与真实开发任务”,工具就不再是插件列表里的装饰品。它需要能搜索、能理解、能稳定调用的能力单元。MoonBit Skills Marketplace 的思路,是让开发者用 MoonBit 写工具,编译成 WebAssembly,再通过 mooncakes.io / Skills Marketplace 分发;用户和 Agent 则用统一方式发现、安装和调用这些工具。
这件事的重点不只是“多了一个市场”。它把工具从本地脚本、私有仓库、临时 HTTP 服务,推进到一种更像软件包的分发模型:有构建产物,有元数据,有调用边界,也有更清晰的运行环境。
工具从库变成 Agent 可调用的技能
传统开发者熟悉“安装一个库”:引入依赖,在代码里调用函数。但 Agent 面对的不是同一个问题。Agent 需要先知道一个工具做什么、输入是什么、输出是什么、失败时会怎样,然后才能在任务中选择它。
MoonBit Skills 的价值在于把这些信息显式化。一个 Skill 不只是 Wasm 文件,还应该包含名称、描述、参数 schema、能力边界等元数据。这样 Agent 不需要阅读源码,也能判断:这个技能适不适合用来格式化 JSON、解析日志、生成配置,或者调用某个内部规则检查器。
这里有一个关键变化:工具接口变成面向机器协作的契约。人类开发者仍然可以安装和运行它,但 Agent 也能用同一套描述来完成发现和调用。
为什么是 MoonBit + WebAssembly
MoonBit 面向现代工具开发,WebAssembly 则提供了适合分发工具的运行形态:体积可控、启动快、边界清晰,并且天然适合被宿主程序加载。
对于 Agent 工具来说,这些特性很实用:
- 工具不必常驻成一个服务,Agent 可以按需调用。
- Wasm 产物比“请在本机装一堆运行时”更容易复制和分发。
- 沙箱边界让文件、网络、环境变量等权限更容易被宿主控制。
- 同一个技能可以被 CLI、IDE、Agent runtime 或自动化流水线复用。
但边界也要说清楚:Wasm 不是万能隔离。真实系统里仍然要控制宿主授予的能力,比如文件系统访问、网络访问、密钥注入和执行超时。Marketplace 解决的是发现与分发问题,运行安全还需要调用方和平台共同设计。
可以这样实践:把一个小工具包装成 Skill
下面示例是一个最小化的“JSON 字符串清洗”技能项目。假设你的 MoonBit 工具链已经安装,并且实际 Marketplace 的 manifest schema 以 mooncakes.io 发布文档为准。这里的 skill.yaml 用来展示 Agent 需要理解的元数据结构,可以直接改造成你自己的工具描述。
mkdir json-clean-skill
cd json-clean-skill
moon new .
创建一个入口文件,例如 src/main/main.mbt。具体 MoonBit 标准库 API 可能随版本变化,下面保留为容易改造的工具骨架:读取字符串参数,返回清洗后的结果。
// src/main/main.mbt
// Assumption: adapt the exported function signature to the current MoonBit/Wasm host ABI.
pub fn clean_json_text(input : String) -> String {
input.trim()
}
添加一个技能描述文件:
# skill.yaml
name: json-clean
version: 0.1.0
runtime: wasm
entry: target/wasm/release/build/main/main.wasm
description: Trim and normalize JSON text before an Agent sends it to a parser.
inputs:
type: object
required:
- text
properties:
text:
type: string
description: Raw JSON-like text copied from logs, chat, or editor buffers.
outputs:
type: object
properties:
text:
type: string
description: Cleaned text ready for the next tool.
permissions:
filesystem: none
network: none
构建 Wasm 产物:
moon build --target wasm
ls target/wasm/release/build/main/
如果你的 Agent runtime 支持本地技能目录,可以把 manifest 和 Wasm 放到同一目录。一个调用方可以按下面的逻辑读取描述、选择工具、传入参数。这里用伪代码表达宿主侧流程,因为不同 Agent runtime 的 API 会不同:
# host_invoke.py
# Assumption: replace WasmSkillRuntime with your Agent/runtime's actual Wasm invoker.
import json
import yaml
class WasmSkillRuntime:
def __init__(self, wasm_path: str):
self.wasm_path = wasm_path
def call(self, function_name: str, payload: dict) -> dict:
# Wire this to your real Wasm host ABI.
text = payload["text"].strip()
return {"text": text}
with open("skill.yaml", "r", encoding="utf-8") as f:
skill = yaml.safe_load(f)
runtime = WasmSkillRuntime(skill["entry"])
result = runtime.call("clean_json_text", {"text": " {\"ok\": true} "})
print(json.dumps(result, ensure_ascii=False))
运行宿主示例:
python -m pip install pyyaml
python host_invoke.py
这段示例的重点不是绑定某个固定运行时,而是把 Skill 的三个层次拆开:MoonBit 代码负责能力实现,Wasm 负责可移植产物,skill.yaml 负责让 Agent 理解“何时该调用它”。
发布市场前要补齐的工程约束
把工具发布给 Agent 调用,比发布一个普通脚本更需要克制。建议至少检查这些点:
- 输入输出 schema 要小而明确,不要让 Agent 猜字段含义。
- 描述要写能力边界,例如“只清洗字符串,不校验 JSON 语义”。
- 默认权限尽量收紧,能不访问网络就不要申请网络。
- 错误返回要结构化,避免只抛出一段人类可读文本。
- 版本号要认真维护,Agent workflow 可能依赖旧行为。
- 测试样例要覆盖空输入、超长输入、非法输入和宿主超时。
采用建议
MoonBit Skills Marketplace 适合那些“足够通用、可重复调用、边界清楚”的工具:格式转换、配置生成、静态检查、日志提取、项目脚手架、内部规范校验等。它不适合把一整个复杂系统塞进 Agent 工具,也不应该绕过现有权限审计去执行高风险操作。
比较务实的落地方式,是先从团队已有的小脚本里挑一个:输入输出稳定、没有敏感权限、失败成本低。把它改成 MoonBit 实现,编译为 Wasm,补上 manifest 和测试,再发布到 Skills Marketplace。这样你得到的不只是一个可安装工具,而是一块 Agent 能发现、能理解、能安全组合的工程能力。