From tools
Build cross-language backends with the iii engine. Register functions in TypeScript, Python, or Rust callable from any connected service via WebSocket. Covers iii-sdk, state, KV Server, streams, triggers (HTTP/cron/queue/log), Bridge Client mesh, OpenTelemetry, Docker deployment, iii Console, and Prometheus metrics. Use when: setting up iii engine, cross-language function calls, iii-sdk integration, registerTrigger configuration, KV Server storage, queue/log triggers, Docker deploy, or debugging "ECONNREFUSED 49134", "type_not_found", "@iii-dev/sdk 404".
How this skill is triggered — by the user, by Claude, or both
Slash command
/tools:iiiThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **SDK 0.3.0-alpha Breaking Change (verified 2026-02-18)**: The `registerTrigger` field is `trigger_type` (NOT `type`). HTTP triggers use `trigger_type: "api"` (NOT `"http"`). Using `type: "http"` causes silent 404s on all routes. This was confirmed in the tac-4-go rewrite from motia to direct iii-sdk.
SDK 0.3.0-alpha Breaking Change (verified 2026-02-18): The
registerTriggerfield istrigger_type(NOTtype). HTTP triggers usetrigger_type: "api"(NOT"http"). Usingtype: "http"causes silent 404s on all routes. This was confirmed in the tac-4-go rewrite from motia to direct iii-sdk.
SDK Note: The iii.dev docs reference
@iii-dev/sdkwith aBridgeclass — this package does not exist on npm (404 as of 2026-02-17). Always installiii-sdk(no scope). The docs SDK uses different conventions (dot separators,trigger_type,function_path). Seereferences/cross-language.mdfor translation guide.
iii has two fundamental primitives:
Services connect to the iii engine over WebSocket. The engine handles routing, retries, observability, state, streams, cron, and HTTP API exposure.
curl -fsSL https://install.iii.dev/iii/main/install.sh | sh
iii --version
Or run via 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
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
See
references/engine-modules.mdfor full module configuration including StreamModule, OtelModule, QueueModule, PubSubModule, CronModule, KvServer, LoggingModule, and BridgeClientModule.
iii -c iii-config.yaml
mkdir my-service && cd my-service
npm init -y
npm install iii-sdk
Set "type": "module" in package.json.
// 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");
Run with: npx tsx src/worker.ts
Test: curl http://localhost:3111/health
service-name::function-name convention for function IDs (e.g., "client::health", "data-service::transform")"type": "module" in package.json (SDK uses ESM)process.env.III_BRIDGE_URL ?? "ws://localhost:49134" for the engine addressgetContext() for logging inside function handlers (provides structured OTEL logging)Promise.allSettled() when calling multiple remote functions in parallel (graceful partial failure)GET /health on port 3111 to check engine health before connecting servicesindex (not scope) for KV Server function parameters — scope is for the State module onlyws://localhost:49134 without env var fallbackprocess.env in function IDs (they must be static strings)"*/30 * * * * * *"trigger_type (NOT type) in registerTrigger. Use "api" (NOT "http") for HTTP triggers. Use "queue" for queue triggers, "cron" for cron triggerstype (NOT trigger_type). Use "http" for HTTP triggersiii-sdk/state or iii-sdk/stream for basic state operations - use sdk.call("state::set", ...) instead. Removed in 0.3.0npm install @iii-dev/sdk — this scoped package does not exist on npm (404). Use iii-sdk instead:: (double colon). "kv_server::get" not "kv_server.get"| Import | Purpose |
|---|---|
iii-sdk | Core: init, getContext, withContext, Logger (+ types). init() returns ISdk with registerFunction, registerTrigger, call, callVoid, shutdown methods |
iii-sdk/state | Advanced: Direct IState interface (get/set/delete/list/update) |
iii-sdk/stream | Advanced: Direct IStream interface with groups |
iii-sdk/telemetry | OpenTelemetry: initOtel, withSpan, getTracer, getMeter |
For most use cases, use the core SDK and call("state::set", ...) / call("state::get", ...) for state.
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
Note:
shutdown()was added in 0.2.0. Always call it during graceful process termination.
Exposes a function as an HTTP endpoint on the engine's REST API (default port 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
Warning: Using
type: "http"(0.2.0 syntax) with iii engine 0.4.0+ causes silent 404s on all routes. Always usetrigger_type: "api"with 0.3.0-alpha SDK.
The handler receives an ApiRequest object:
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 },
};
});
Supports 7-field cron expressions (seconds granularity):
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
Invokes a function when a message is enqueued to a specific topic. Requires QueueModule in engine config.
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]" } });
Invokes a function when log events match a level. Requires LoggingModule in engine config.
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)
});
| Need | File |
|---|---|
| Full SDK type definitions and state/stream APIs | references/api-reference.md |
| Engine module configuration schemas | references/engine-modules.md |
| Cross-language examples, OpenTelemetry, env vars | references/cross-language.md |
| Docker deployment and project structure | references/docker-deployment.md |
host.docker.internal requires explicit extra_hosts mappingimport and require now workThese are current reality with [email protected] + iii engine 0.4.0:
trigger_type replaces type in registerTrigger — use trigger_type: "api" (NOT type: "http")"api" replaces "http" as the HTTP trigger type nameiii-sdk/state export removed — use call("state::set", ...) and call("state::get", ...)iii-sdk/stream renamed to iii-sdk/streams (plural)ISdk type no longer exported from the main entry point@iii-dev/sdk (Bridge class, dot separators) may become the official SDK. Monitor npm for @iii-dev/sdk availabilityVerified: tac-4-go project uses direct iii-sdk 0.3.0-alpha with
trigger_type: "api"and all 4 HTTP endpoints + queue + cron work correctly.
| Error | Cause | Fix |
|---|---|---|
ECONNREFUSED 127.0.0.1:49134 | Engine not running | Start with iii -c iii-config.yaml |
| Function call times out (30s) | Target service not connected | Start the service; check engine::workers::list |
Cannot find module 'iii-sdk' | SDK not installed | npm install iii-sdk |
| HTTP endpoint returns 404 | Wrong trigger field or type | With 0.3.0-alpha: use trigger_type: "api" (NOT type: "http"). Verify api_path matches URL |
| Cron not firing | Wrong expression format | Use 7-field format: sec min hour dom mon dow year |
| State returns null | Wrong scope or key | Check scope/key strings match exactly |
trigger_type_not_found | SDK/engine version mismatch | 0.2.0: use type. 0.3.0-alpha: use trigger_type |
| All routes 404 (silent) | Used type: "http" with 0.3.0-alpha SDK | Change to trigger_type: "api" — motia sends "http", iii engine 0.4.0 expects "api" |
| KV Server timeout | KV Server module not in config | Add modules::kv_server::KvServer to iii-config.yaml |
module class not found | Wrong singular/plural path | Try stream vs streams in class path; check engine version |
@iii-dev/sdk npm 404 | Package not published | Use iii-sdk (no scope). @iii-dev/sdk is docs-only |
| Queue messages not processing | Missing queue trigger or wrong topic | Verify registerTrigger({ type: "queue", config: { topic } }) matches enqueue topic |
npx claudepluginhub p/evolv3-ai-tools-plugins-toolsBuilds and manages Inngest serverless background jobs, event-driven workflows, and durable execution patterns without managing queues or workers.
Builds production-grade backend code for API endpoints, server logic, webhooks, queues, and integrations with error handling, logging, validation, and reliability.
Guides building, deploying, and debugging CloudBase Event Functions and HTTP Functions. Use for application runtime code on CloudBase, not for calling platform APIs.