Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
iii-hq avatar

Iii Core Primitives

  • 1.3k installs
  • 18.6k repo stars
  • Updated August 5, 2026
  • iii-hq/iii

iii-core-primitives is an agent skill that teaches iii foundational primitives—Function, Trigger, and Worker—plus sessions and runtime objects so developers can architect agents and compose capabilities before adding mid

About

iii-core-primitives is the foundational iii-hq skill for the iii execution model. iii exposes three top-level primitives: Function as a named unit of work such as orders::validate, Trigger as an event source bound to a function, and Worker as a process connecting to the engine to execute functions. The skill covers registering functions, binding triggers, choosing sync, void, or enqueue invocation, creating workers, inspecting the live worker registry, installing registry workers, authoring custom triggers, moving channel data, and adapting external HTTP functions across TypeScript, Python, and Rust. Developers reach for it when starting iii agent or backend work and need correct IDs with :: namespaces, leading slashes in HTTP api_path, and cron expression config. Pair with iii-architecture-patterns for multi-step designs and iii-sdk-reference for package-level APIs.

  • Runtime primitives
  • Skills and tools
  • Agent composition
  • Session model
  • Framework foundations

Iii Core Primitives by the numbers

  • 1,334 all-time installs (skills.sh)
  • +48 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #879 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/iii-hq/iii --skill iii-core-primitives

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1.3k
repo stars18.6k
Last updatedAugust 5, 2026
Repositoryiii-hq/iii

How do iii Function, Trigger, and Worker primitives work?

Learn iii foundational primitives—tools, skills, sessions, and runtime objects—to architect agents and compose capabilities before adding middleware or SDK layers.

Who is it for?

Developers new to iii who must register functions, bind triggers, and run workers before building workflows or SDK integrations.

Skip if: Multi-pattern architecture decisions or language-specific SDK method lookups covered by other iii skills.

When should I use this skill?

The user registers iii functions, binds triggers, creates workers, inspects the worker registry, or configures HTTP or cron triggers.

What you get

Registered Functions and Triggers, running Workers, and correct invocation and channel configuration

  • Function and Trigger registrations
  • Worker configuration

By the numbers

  • Documents 3 top-level iii primitives: Function, Trigger, Worker
  • Supports 3 invocation modes: sync, void, enqueue

Files

SKILL.mdMarkdownGitHub ↗

Core Primitives

iii has three top-level primitives:

  • Function: a named unit of work such as orders::validate
  • Trigger: an event source bound to a function
  • Worker: a process that connects to the engine and executes functions

Use :: in function IDs, leading slashes in HTTP api_path, and expression for cron config.

Function Registration

Register local handlers when you control the implementation. Register HTTP-invoked functions when iii should call an existing external endpoint.

ShapeUse for
registerFunction(id, handler, options?)Local worker code
registerFunction(id, HttpInvocationConfig, options?)Existing HTTP services
registerTrigger({ type, function_id, config, metadata? })Binding an event source
trigger({ function_id, payload, action?, timeout? })Calling any function by ID

Functions and triggers 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 or trigger types. There are two common paths:

TaskUse
Create your own workerWrite SDK code that calls registerWorker, registerFunction, and registerTrigger
Add an existing capabilityBrowse https://workers.iii.dev/, then run iii worker add <name>
Pin a worker versioniii worker add <name>@<version>
Add an OCI workeriii worker add ghcr.io/org/worker:tag
Add a local worker during developmentiii worker add ./workers/my-worker
Replay installed workersCommit iii.lock, then run iii worker sync

The public worker registry at workers.iii.dev is for installable workers such as HTTP, state, queue, pub/sub, cron, observability, sandbox, database, shell, console, and other capability workers. 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, triggers, and trigger types. Read it through the built-in discovery functions:

FunctionReturns
engine::workers::listConnected workers and metrics
engine::functions::listRegistered functions
engine::triggers::listRegistered triggers
engine::trigger-types::listAdvertised trigger types and schemas

For topology changes, bind triggers to engine::workers-available or engine::functions-available.

Built-In Trigger Shapes

Trigger typeRegistration configHandler payload
http{ api_path: "/orders/:id", http_method: "POST" }{ query_params, path_params, headers, path, method, body }
cron{ expression: "0 0 9 * * * *" }{ trigger, job_id, scheduled_time, actual_time }
durable:subscriber{ topic: "payments" }The queued message payload
subscribe{ topic: "orders.created" }The published event payload
state{ scope: "orders", key?: "order-123" }{ event_type, scope, key, old_value, new_value }
stream{ stream_name, group_id, item_id? }Stream event details
log{ level: "warn" }OpenTelemetry-style log data

Add condition_function_id to built-in trigger config when the handler should only run if a boolean condition function returns true.

Invocation Modes

ModeShapeUse when
Synctrigger({ function_id, payload })The caller needs the result
VoidTriggerAction.Void()Optional side effect, no result needed
EnqueueTriggerAction.Enqueue({ queue })Reliable async work with queue policy

Use enqueue for work that must complete with retries. Use void for analytics, notifications, and other non-critical side effects.

Code Examples

TypeScript

import { registerWorker, TriggerAction } from "iii-sdk";

const iii = registerWorker("ws://localhost:49134", { workerName: "orders-worker" });

iii.registerFunction("orders::validate", async (order) => {
  if (!order.id) throw new Error("missing order id");
  return { ...order, valid: true };
});

iii.registerFunction("orders::process", async (order) => {
  const validated = await iii.trigger({ function_id: "orders::validate", payload: order });
  await iii.trigger({
    function_id: "orders::charge",
    payload: validated,
    action: TriggerAction.Enqueue({ queue: "payments" }),
  });
  return { accepted: true, orderId: validated.id };
});

iii.registerTrigger({
  type: "http",
  function_id: "orders::process",
  config: { api_path: "/orders", http_method: "POST" },
});

Python

from iii import register_worker

iii = register_worker("ws://localhost:49134")

def validate(order):
    if not order.get("id"):
        raise ValueError("missing order id")
    return {**order, "valid": True}

def process(order):
    validated = iii.trigger({"function_id": "orders::validate", "payload": order})
    iii.trigger({
        "function_id": "orders::charge",
        "payload": validated,
        "action": {"type": "enqueue", "queue": "payments"},
    })
    return {"accepted": True, "orderId": validated["id"]}

iii.register_function("orders::validate", validate)
iii.register_function("orders::process", process)
iii.register_trigger({
    "type": "http",
    "function_id": "orders::process",
    "config": {"api_path": "/orders", "http_method": "POST"},
})

Rust

use iii_sdk::{register_worker, InitOptions, RegisterFunction, TriggerAction};
use iii_sdk::protocol::{RegisterTriggerInput, TriggerRequest};
use serde_json::json;

let iii = register_worker("ws://127.0.0.1:49134", InitOptions::default());

iii.register_function(RegisterFunction::new("orders::validate", |order: serde_json::Value| {
    if order["id"].is_null() {
        return Err("missing order id".into());
    }
    Ok(json!({ "valid": true, "order": order }))
}))?;

let process_client = iii.clone();
iii.register_function(RegisterFunction::new_async("orders::process", move |order: serde_json::Value| {
    let iii = process_client.clone();
    async move {
        let validated = iii.trigger(TriggerRequest::new("orders::validate", order)).await?;
        iii.trigger(TriggerRequest {
            function_id: "orders::charge".into(),
            payload: validated.clone(),
            action: Some(TriggerAction::Enqueue { queue: "payments".into() }),
            timeout_ms: None,
        }).await?;
        Ok(json!({ "accepted": true, "order": validated }))
    }
}))?;

iii.register_trigger(RegisterTriggerInput {
    trigger_type: "http".into(),
    function_id: "orders::process".into(),
    config: json!({ "api_path": "/orders", "http_method": "POST" }),
    metadata: None,
})?;

Advanced Primitive Patterns

  • Custom triggers: use registerTriggerType({ id, description }, handler) when the event source is

not built in. Keep listener setup in registerTrigger and cleanup in unregisterTrigger.

  • Channels: use createChannel() for binary or streaming data that should not be serialized into

JSON payloads. Pass readerRef or writerRef through a function payload.

  • HTTP-invoked functions: use HttpInvocationConfig for legacy APIs, third-party endpoints, or

immutable services. Use environment variable names for auth fields, not raw secrets.

  • Schemas: Rust can derive request/response schemas with schemars::JsonSchema; Python can use

type hints or Pydantic; Node can pass JSON Schema manually.

When to Use

  • Use this skill for function registration, trigger binding, trigger payload shapes, invocation mode

decisions, worker creation, worker registry access, trigger conditions, custom trigger types, channels, and HTTP-invoked functions.

  • Use this when a task spans TypeScript, Python, or Rust examples for the same iii primitive.

Boundaries

  • For engine ports, adapters, queue retry policy, worker manager, RBAC listeners, and deployment

config, use iii-engine-config.

  • For SDK-specific package exports and language caveats, use iii-sdk-reference.
  • For complete backend designs such as workflows, CQRS, agentic systems, and reactive apps, use

iii-architecture-patterns.

  • For failed invocations, timeouts, RBAC denials, and retryability, use iii-error-handling.
  • Worker-backed capability details live with the worker docs, not as top-level iii skills.

Related skills

FAQ

What are the three top-level iii primitives?

iii-core-primitives defines Function as named work like orders::validate, Trigger as an event source bound to a function, and Worker as a process that connects to the engine and executes functions.

Which invocation modes does iii support?

iii-core-primitives documents sync, void, and enqueue invocation when calling functions. Pick the mode based on whether the caller needs a response, fire-and-forget behavior, or queued execution.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.