/iii-core-primitives
Use when registering iii functions, calling them (call with sync, void, or enqueue), observing functions and event sources, creating workers, inspecting the live worker registry, installing registry workers, moving channel data, or adapting external HTTP functions across
Claude Code
$ npx -y skills add iii-hq/iii --skill iii-core-primitives --agent claude-code
Codex
$ npx skills add iii-hq/iii --skill iii-core-primitives -a codex -y
Cursor
$ npx skills add iii-hq/iii --skill iii-core-primitives -a cursor -y
Gemini CLI
$ npx skills add iii-hq/iii --skill iii-core-primitives -a gemini-cli -y
GitHub Copilot
$ npx skills add iii-hq/iii --skill iii-core-primitives -a github-copilot -y
OpenCode
$ npx skills add iii-hq/iii --skill iii-core-primitives -a opencode -y
Windsurf
$ npx skills add iii-hq/iii --skill iii-core-primitives -a windsurf -y
SKILL.md
iii-core-primitives.SKILL.mdname: iii-core-primitives
description: >-
Use when registering iii functions, calling them (call with sync, void, or enqueue), observing
functions and event sources, creating workers, inspecting the live worker registry, installing
registry workers, moving channel data, or adapting external HTTP functions across TypeScript,
Python, and Rust.
Core Primitives
iii has three primitives:
- **Worker**: a process that connects to the engine, registers functions, and calls them
- **Function**: a named unit of work such as `orders::validate`; any worker runs it with `call`
- **Observer**: `iii.observe(a, b)`: when `a` runs, `b` runs
Everything is reactive. An HTTP request, a cron tick, a queue message, and a state change are each a call of a source function (`http::on-request`, `cron::on-tick`, `queue::on-message`, `state::on-changed`), so observing that function is how work starts on the event. See `iii-observe`.
Use `::` in function IDs, leading slashes in HTTP `path` args, and `expression` for cron args.
Function Registration
Register local handlers when you control the implementation. To call an existing external endpoint, register a handler that makes the HTTP call. HTTP-invoked functions (`HttpInvocationConfig`, `iii-http-functions`) are deprecated and will be removed in an upcoming release.
| Shape | Use for | | --- | --- | | `registerFunction(id, handler, options?)` | Local worker code | | `registerFunction(id, HttpInvocationConfig, options?)` | Deprecated (iii-http-functions); use a handler that makes the HTTP call | | `observe(source, target, options?)` | Running `target` when `source` runs: another function, an HTTP route, a cron schedule, a queue topic, an engine event (`iii-observe`) | | `call({ function_id, payload, action?, timeoutMs? })` | Calling any function by ID |
Functions and observers can carry metadata for ownership, discovery, and generated skills. Do not put secrets in metadata.
Workers and Registry
A worker is any process that connects to the engine and registers functions. There are two common paths:
| Task | Use | | --- | --- | | Create your own worker | Write SDK code that calls `registerWorker`, `registerFunction`, `call`, and `observe` | | Add an existing capability | Browse `https://workers.iii.dev/`, then call `compose::add worker=<name>` | | Pin a worker version | `compose::add worker=<name>@<version>` | | Declare a local worker | Add `worker: path://./workers/my-worker` under `containers:` | | Reproduce a project | Commit the exact versions in `worker-compose.yaml` |
The public worker registry at `workers.iii.dev` is for installable workers such as HTTP, state, queue, pub/sub, cron, database, shell, console, rbac-proxy, and other capability workers. (`iii-sandbox` and `iii-observability` are engine-owned and are not added through the registry; the `sandbox-libkrun` adapter behind `iii-sandbox` is a registry worker that Compose installs.) Those workers may ship their own function-level skills; do not duplicate every capability as a top-level iii skill.
Worker Manifest
Use `iii.worker.yaml` when iii should start a local worker project:
name: math-worker
runtime:
kind: python
package_manager: pip
entry: math_worker.py
scripts:
install: "pip install -r requirements.txt"
start: "python math_worker.py"
The manifest describes how to start the process. Once running, the WebSocket connection and function registrations are what make the worker part of iii.
Live Engine Registry
The engine keeps a live registry of connected workers, registered functions, and observers. Read it through the built-in discovery functions:
| Function | Returns | | --- | --- | | `engine::workers::list` | Connected workers and metrics | | `engine::functions::list` | Registered functions, with `args_format`, `private`, `observable`, and `observer_count` | | `engine::observers::list` | Observers you may see (`function_id`, `namespace`, `worker` filters) |
For topology changes, observe the engine-hosted sources `engine::on-workers-changed`, `engine::on-functions-changed`, or `engine::on-observers-changed` with `capture: ['input']`: the event is the payload's `input` (see `iii-observe`).
Built-In Sources
Capability workers host these source functions, and the engine hosts `observability::on-log`. Add the worker, then observe the function with the args it takes; `iii-observe` has the full table and the other engine-hosted sources.
| Source function | `args` | What the target receives | | --- | --- | --- | | `http::on-request` | `{ method: "POST", path: "/orders/:id", middleware_function_ids? }` | `{ method, path, path_params, query_params, headers, body }`; its result is the response `{ status_code, headers?, body? }` | | `cron::on-tick` | `{ expression: "0 0 9 * * * *" }` | The payload; `input` is `{ expression, scheduled_time, actual_time }` | | `queue::on-message` | `{ topic: "payments", max_retries?, backoff_ms?, group? }` | The published data; returning acks the message | | `state::on-changed` | none; filter on `input.scope`, `input.key` | The payload; `input` is `{ event_type, scope, key, old_value, new_value }` | | `database::on-row-changed` | `{ db, table?, ops? }` | The payload; `input` is the row change | | `observability::on-log` | none; filter on `input.severity_text`; from a namespaced worker, observe with `namespace: "default"` | The payload; `input` is one log record |
A condition you can state over the call (its input, output, error, caller, or metadata) is a filter on the observer. A condition that needs code goes in the target.
Invocation Modes
| Mode | Shape | Use when | | --- | --- | --- | | Sync | `call({ function_id, payload })` | The caller needs the result | | Void | `CallAction.Void()` | Optional side effect, no result needed | | Enqueue | `CallAction.Enqueue({ queue })` | Reliable async work with queue policy |
Use enqueue for work that must complete with retries. Use void for analytics, n
Read more
name: iii-core-primitives description: >- Use when registering iii functions, calling them (call with sync, void, or enqueue), observing functions and event sources, creating workers, inspecting the live worker registry, installing registry workers, moving channel data, or adapting external HTTP functions across TypeScript, Python, and Rust.
Core Primitives
iii has three primitives:
- **Worker**: a process that connects to the engine, registers functions, and calls them
- **Function**: a named unit of work such as `orders::validate`; any worker runs it with `call`
- **Observer**: `iii.observe(a, b)`: when `a` runs, `b` runs
Everything is reactive. An HTTP request, a cron tick, a queue message, and a state change are each a call of a source function (`http::on-request`, `cron::on-tick`, `queue::on-message`, `state::on-changed`), so observing that function is how work starts on the event. See `iii-observe`.
Use `::` in function IDs, leading slashes in HTTP `path` args, and `expression` for cron args.
Function Registration
Register local handlers when you control the implementation. To call an existing external endpoint, register a handler that makes the HTTP call. HTTP-invoked functions (`HttpInvocationConfig`, `iii-http-functions`) are deprecated and will be removed in an upcoming release.
| Shape | Use for | | --- | --- | | `registerFunction(id, handler, options?)` | Local worker code | | `registerFunction(id, HttpInvocationConfig, options?)` | Deprecated (iii-http-functions); use a handler that makes the HTTP call | | `observe(source, target, options?)` | Running `target` when `source` runs: another function, an HTTP route, a cron schedule, a queue topic, an engine event (`iii-observe`) | | `call({ function_id, payload, action?, timeoutMs? })` | Calling any function by ID |
Functions and observers can carry metadata for ownership, discovery, and generated skills. Do not put secrets in metadata.
Workers and Registry
A worker is any process that connects to the engine and registers functions. There are two common paths:
| Task | Use | | --- | --- | | Create your own worker | Write SDK code that calls `registerWorker`, `registerFunction`, `call`, and `observe` | | Add an existing capability | Browse `https://workers.iii.dev/`, then call `compose::add worker=<name>` | | Pin a worker version | `compose::add worker=<name>@<version>` | | Declare a local worker | Add `worker: path://./workers/my-worker` under `containers:` | | Reproduce a project | Commit the exact versions in `worker-compose.yaml` |
The public worker registry at `workers.iii.dev` is for installable workers such as HTTP, state, queue, pub/sub, cron, database, shell, console, rbac-proxy, and other capability workers. (`iii-sandbox` and `iii-observability` are engine-owned and are not added through the registry; the `sandbox-libkrun` adapter behind `iii-sandbox` is a registry worker that Compose installs.) Those workers may ship their own function-level skills; do not duplicate every capability as a top-level iii skill.
Worker Manifest
Use `iii.worker.yaml` when iii should start a local worker project:
name: math-worker runtime: kind: python package_manager: pip entry: math_worker.py scripts: install: "pip install -r requirements.txt" start: "python math_worker.py"
The manifest describes how to start the process. Once running, the WebSocket connection and function registrations are what make the worker part of iii.
Live Engine Registry
The engine keeps a live registry of connected workers, registered functions, and observers. Read it through the built-in discovery functions:
| Function | Returns | | --- | --- | | `engine::workers::list` | Connected workers and metrics | | `engine::functions::list` | Registered functions, with `args_format`, `private`, `observable`, and `observer_count` | | `engine::observers::list` | Observers you may see (`function_id`, `namespace`, `worker` filters) |
For topology changes, observe the engine-hosted sources `engine::on-workers-changed`, `engine::on-functions-changed`, or `engine::on-observers-changed` with `capture: ['input']`: the event is the payload's `input` (see `iii-observe`).
Built-In Sources
Capability workers host these source functions, and the engine hosts `observability::on-log`. Add the worker, then observe the function with the args it takes; `iii-observe` has the full table and the other engine-hosted sources.
| Source function | `args` | What the target receives | | --- | --- | --- | | `http::on-request` | `{ method: "POST", path: "/orders/:id", middleware_function_ids? }` | `{ method, path, path_params, query_params, headers, body }`; its result is the response `{ status_code, headers?, body? }` | | `cron::on-tick` | `{ expression: "0 0 9 * * * *" }` | The payload; `input` is `{ expression, scheduled_time, actual_time }` | | `queue::on-message` | `{ topic: "payments", max_retries?, backoff_ms?, group? }` | The published data; returning acks the message | | `state::on-changed` | none; filter on `input.scope`, `input.key` | The payload; `input` is `{ event_type, scope, key, old_value, new_value }` | | `database::on-row-changed` | `{ db, table?, ops? }` | The payload; `input` is the row change | | `observability::on-log` | none; filter on `input.severity_text`; from a namespaced worker, observe with `namespace: "default"` | The payload; `input` is one log record |
A condition you can state over the call (its input, output, error, caller, or metadata) is a filter on the observer. A condition that needs code goes in the target.
Invocation Modes
| Mode | Shape | Use when | | --- | --- | --- | | Sync | `call({ function_id, payload })` | The caller needs the result | | Void | `CallAction.Void()` | Optional side effect, no result needed | | Enqueue | `CallAction.Enqueue({ queue })` | Reliable async work with queue policy |
Use enqueue for work that must complete with retries. Use void for analytics, n
Other skills on iii.
More skills from other plugins.
karpathy-guidelines
Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid…
agent-builder
Design and build AI agents for any domain. Use when users: (1) ask to "create an agent", "build an assistant", or "design an AI…
Questions about iii-core-primitives.
- Which coding agents can use iii-core-primitives?
- iii-core-primitives installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

