关于 iii
面向开发者的 iii 跨语言后端引擎技能指南,介绍函数注册与调用、触发器及引擎能力,并说明不同 SDK 版本的约定。
主要功能
- 01注册可调用函数
- 02跨服务调用函数
- 03支持 HTTP、cron、队列和日志触发器
- 04通过引擎模块使用状态与流
- 05说明 SDK 版本差异约定
适用场景
- 01连接以不同语言编写的服务
- 02将函数开放为 HTTP 端点
- 03定时运行函数或响应队列消息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ evolv3-ai/ vibe-skills --skill iii安装后在 Claude Code 中输入/iii确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-reference.mdcross-language.mddocker-deployment.mdengine-modules.md详细介绍
iii - 跨语言后端引擎
SDK 0.3.0-alpha 重大变更(已于 2026-02-18 验证):
registerTrigger字段为trigger_type(而非type)。HTTP 触发器使用trigger_type: "api"(而非"http")。使用type: "http"会导致所有路由静默返回 404。这一点已在 tac-4-go 从 motia 重写为直接使用 iii-sdk 的过程中得到确认。
SDK 说明:iii.dev 文档引用了带有
Bridge类的@iii-dev/sdk——该 npm 包并不存在(截至 2026-02-17 返回 404)。请始终安装iii-sdk(无作用域)。文档中的 SDK 使用不同约定(点分隔符、trigger_type、function_path)。有关转换指南,请参阅references/cross-language.md。
核心概念
iii 有两个基本原语:
- 注册 - 使引擎能够调用某个函数
- 调用 - 调用任何已注册函数,不受语言或进程限制
服务通过 WebSocket 连接到 iii 引擎。引擎负责路由、重试、可观测性、状态、流、cron 和 HTTP API 暴露。
快速入门
1. 安装引擎
curl -fsSL https://install.iii.dev/iii/main/install.sh | sh
iii --version
或者通过 Docker 运行:
docker pull iiidev/iii:latest
docker run -p 3111:3111 -p 49134:49134 \
-v ./iii-config.yaml:/app/config.yaml:ro \
iiidev/iii:latest
2. 创建引擎配置(iii-config.yaml)
modules:
- class: modules::api::RestApiModule
config:
port: 3111
host: 127.0.0.1
default_timeout: 30000
concurrency_request_limit: 1024
cors:
allowed_origins: ["*"]
allowed_methods: [GET, POST, PUT, DELETE, OPTIONS]
- class: modules::state::StateModule
config:
adapter:
class: modules::state::adapters::KvStore
config:
store_method: file_based
file_path: ./data/state_store.db
- class: modules::shell::ExecModule
config:
exec:
- bun run --enable-source-maps worker.js
有关完整的模块配置,请参阅
references/engine-modules.md,其中包括 StreamModule、OtelModule、QueueModule、PubSubModule、CronModule、KvServer、LoggingModule 和 BridgeClientModule。
3. 启动引擎
iii -c iii-config.yaml
4. 创建 TypeScript 服务
mkdir my-service && cd my-service
npm init -y
npm install iii-sdk
在 package.json 中设置 "type": "module"。
// src/worker.ts
import { init, getContext } from "iii-sdk";
const { registerFunction, registerTrigger, call, callVoid } = init(
process.env.III_BRIDGE_URL ?? "ws://localhost:49134"
);
// Register a function callable by any connected service
const health = registerFunction({ id: "my-service::health" }, async () => {
const { logger } = getContext();
logger.info("Health check OK");
return { status: 200, body: { healthy: true, timestamp: Date.now() } };
});
// Expose as HTTP endpoint via the engine's REST API module
registerTrigger({
trigger_type: "api",
function_id: health.id,
config: { api_path: "health", http_method: "GET" },
});
console.log("Service started - listening for calls");
运行:npx tsx src/worker.ts
测试:curl http://localhost:3111/health
重要规则
始终执行
- 函数 ID 使用
service-name::function-name约定(例如,"client::health"、"data-service::transform") - 在
package.json中设置"type": "module"(SDK 使用 ESM) - 引擎地址使用
process.env.III_BRIDGE_URL ?? "ws://localhost:49134" - 先启动 iii 引擎,再启动服务
- 在函数处理程序中使用
getContext()进行日志记录(提供结构化 OTEL 日志) - 并行调用多个远程函数时使用
Promise.allSettled()(支持优雅地处理部分失败) - 在连接服务之前,通过 3111 端口上的
GET /health检查引擎健康状态 - KV Server 函数参数使用
index(而非scope)——scope仅适用于 State 模块
切勿执行
- 切勿在没有环境变量回退值的情况下,将
ws://localhost:49134硬编码 - 切勿在函数 ID 中使用
process.env(函数 ID 必须是静态字符串) - 切勿假设所有服务都可用——要优雅地处理服务缺失的情况
- 切勿使用 6 段 cron 表达式——iii 支持 7 段(包含秒):
"*/30 * * * * * *" - iii-sdk 0.3.0-alpha:在
registerTrigger中使用trigger_type(而非type)。HTTP 触发器使用"api"(而非"http")。队列触发器使用"queue",cron 触发器使用"cron" - iii-sdk 0.2.0:使用
type(而非trigger_type)。HTTP 触发器使用"http" - 切勿为了基本状态操作而从
iii-sdk/state或iii-sdk/stream导入——请改用sdk.call("state::set", ...)。这些接口已在 0.3.0 中移除 - 切勿运行
npm install @iii-dev/sdk——该带作用域的 npm 包并不存在(返回 404)。请改用iii-sdk - 切勿在引擎函数路径中使用点分隔符——请使用
::(双冒号)。使用"kv_server::get",而不是"kv_server.get"
SDK 入口
| 导入 | 用途 |
|---|---|
iii-sdk | 核心:init、getContext、withContext、Logger(及类型)。init() 返回包含 registerFunction、registerTrigger、call、callVoid、shutdown 方法的 ISdk |
iii-sdk/state | 高级:直接使用 IState 接口(get/set/delete/list/update) |
iii-sdk/stream | 高级:直接使用带有组的 IStream 接口 |
iii-sdk/telemetry | OpenTelemetry:initOtel、withSpan、getTracer、getMeter |
对于大多数用例,请使用核心 SDK,并通过 call("state::set", ...) / call("state::get", ...) 操作状态。
函数注册
const fn = registerFunction(
{
id: "service::action", // Required: unique function ID
description: "What it does", // Optional: for discovery
request_format: { /* schema */ }, // Optional: input schema
response_format: { /* schema */ }, // Optional: output schema
metadata: { version: "1.0" }, // Optional: custom metadata
},
async (payload) => {
const { logger } = getContext();
logger.info("Processing", { payload });
return { result: "done" }; // Return value sent back to caller
}
);
// fn.id = "service::action"
// fn.unregister() - removes the function
调用函数
// Awaitable call (returns result)
const result = await call<InputType, OutputType>("other-service::action", { data: "hello" });
// Fire-and-forget (no return value)
callVoid("log-service::audit", { event: "user_login" });
// Parallel calls with graceful failure
const [a, b] = await Promise.allSettled([
call("service-a::process", payload),
call("service-b::process", payload),
]);
内置函数
// State management (uses 'scope')
await call("state::set", { scope: "shared", key: "VERSION", value: 1 });
const val = await call("state::get", { scope: "shared", key: "VERSION" });
const items = await call("state::list", { scope: "shared" });
// KV Server (uses 'index' — NOT 'scope')
await call("kv_server::set", { index: "default", key: "user:123", value: { name: "Alice" } });
const user = await call("kv_server::get", { index: "default", key: "user:123" });
await call("kv_server::delete", { index: "default", key: "user:123" });
const keys = await call("kv_server::list_keys_with_prefix", { prefix: "user:" });
// Queue — enqueue a message to a topic
await call("enqueue", { topic: "user.created", data: { id: "123", email: "[email protected]" } });
// Engine introspection
const functions = await call("engine::functions::list", {});
const workers = await call("engine::workers::list", {});
// Health check (HTTP, not via SDK)
// curl http://localhost:3111/health
// Graceful shutdown (new in 0.2.0)
await sdk.shutdown(); // Closes WebSocket, cleans up resources
注意:
shutdown()在 0.2.0 中新增。优雅终止进程时,务必调用它。
触发器
HTTP 触发器(API)
在引擎的 REST API 上将函数公开为 HTTP 端点(默认端口为 3111)。
// iii-sdk 0.3.0-alpha (current working — use this)
registerTrigger({
trigger_type: "api",
function_id: "service::handler",
config: {
api_path: "users/:id", // Path params supported
http_method: "POST", // GET, POST, PUT, DELETE, OPTIONS
},
});
// Accessible at: http://localhost:3111/users/123
警告:在 iii 引擎 0.4.0+ 中使用
type: "http"(0.2.0 语法)会导致所有路由静默返回 404。请务必在 0.3.0-alpha SDK 中使用trigger_type: "api"。
处理程序会接收一个 ApiRequest 对象:
registerFunction({ id: "service::handler" }, async (req: ApiRequest) => {
const { path_params, query_params, body, headers, method } = req;
return {
status_code: 200,
headers: { "Content-Type": "application/json" },
body: { id: path_params.id, data: body },
};
});
Cron 触发器
支持 7 字段 cron 表达式(秒级精度):
registerTrigger({
trigger_type: "cron",
function_id: "service::cleanup",
config: { expression: "*/30 * * * * * *" }, // Every 30 seconds
});
// Fields: seconds minutes hours day-of-month month day-of-week year
队列触发器
当消息被加入特定主题的队列时调用函数。需要在引擎配置中启用 QueueModule。
const consumer = registerFunction(
{ id: "events::on-user-created" },
async (data) => {
console.log("User created", data);
return { ok: true };
}
);
registerTrigger({
trigger_type: "queue",
function_id: consumer.id,
config: { topic: "user.created" },
});
// Enqueue from anywhere:
await call("enqueue", { topic: "user.created", data: { id: "123", email: "[email protected]" } });
日志触发器
当日志事件符合某个级别时调用函数。需要在引擎配置中启用 LoggingModule。
registerFunction({ id: "monitoring::on-error" }, async (logEntry) => {
// logEntry: { trace_id, message, level, function_name, date }
const { logger } = getContext();
logger.info("Error captured", logEntry);
// Send alert, store in database, etc.
});
registerTrigger({
trigger_type: "log",
function_id: "monitoring::on-error",
config: { level: "error" }, // Optional: info, warn, error, debug (omit for all)
});
参考资料
| 需求 | 文件 |
|---|---|
| 完整的 SDK 类型定义和状态/流 API | references/api-reference.md |
| 引擎模块配置架构 | references/engine-modules.md |
| 跨语言示例、OpenTelemetry、环境变量 | references/cross-language.md |
| Docker 部署和项目结构 | references/docker-deployment.md |
已知问题
- Alpha 软件:API 可能会在不同版本间变更
- 端口 49134 冲突:引擎的 WebSocket 端口固定为 49134;请确保没有其他程序占用该端口
- Docker 网络:在 Linux Docker <20.10 上,
host.docker.internal需要显式配置extra_hosts映射 - 重新连接:SDK 会以指数退避方式自动重新连接(初始间隔 1s,最长 30s,默认无限重试)
- CJS 支持:0.2.0 新增了与 ESM 并存的 CommonJS 导出;现在
import和require均可使用
0.3.0-alpha 破坏性变更(已于 2026-02-18 确认可用)
以下是 [email protected] 与 iii 引擎 0.4.0 搭配时的实际情况:
- 在
registerTrigger中,trigger_type取代type——使用trigger_type: "api"(不要使用type: "http") "api"取代"http",成为 HTTP 触发器类型名称iii-sdk/state导出已移除——使用call("state::set", ...)和call("state::get", ...)iii-sdk/stream重命名为iii-sdk/streams(复数形式)- 主入口不再导出
ISdk类型 - SDK 过渡情况:仅包含文档的
@iii-dev/sdk(Bridge 类,使用点号分隔符)可能会成为官方 SDK。请关注 npm 上@iii-dev/sdk是否可用
已验证:tac-4-go 项目使用直接依赖的 iii-sdk 0.3.0-alpha,配置了
trigger_type: "api";全部 4 个 HTTP 端点以及队列和 cron 均可正常工作。
故障排除
| 错误 | 原因 | 修复方法 |
|---|---|---|
ECONNREFUSED 127.0.0.1:49134 | 引擎未运行 | 使用 iii -c iii-config.yaml 启动 |
| 函数调用超时(30s) | 目标服务未连接 | 启动服务;检查 engine::workers::list |
Cannot find module 'iii-sdk' | 未安装 SDK | npm install iii-sdk |
| HTTP 端点返回 404 | 触发器字段或类型错误 | 使用 0.3.0-alpha 时:使用 trigger_type: "api"(不要使用 type: "http")。确认 api_path 与 URL 匹配 |
| Cron 未触发 | 表达式格式错误 | 使用 7 字段格式:sec min hour dom mon dow year |
| 状态返回 null | 作用域或键错误 | 检查作用域和键字符串是否完全匹配 |
trigger_type_not_found | SDK/引擎版本不匹配 | 0.2.0:使用 type。0.3.0-alpha:使用 trigger_type |
| 所有路由均返回 404(无提示) | 在 0.3.0-alpha SDK 中使用了 type: "http" | 改为 trigger_type: "api" — motia 发送 "http",iii engine 0.4.0 需要 "api" |
| KV Server 超时 | 配置中缺少 KV Server 模块 | 将 modules::kv_server::KvServer 添加到 iii-config.yaml |
module class not found | 单复数路径错误 | 尝试在类路径中使用 stream 或 streams;检查引擎版本 |
@iii-dev/sdk npm 404 | 软件包尚未发布 | 使用 iii-sdk(无作用域)。@iii-dev/sdk 仅用于文档 |
| 队列消息未处理 | 缺少队列触发器或主题错误 | 确认 registerTrigger({ type: "queue", config: { topic } }) 与入队主题一致 |