Iii iii-functions-and-triggers
install
source · Clone the upstream repo
git clone https://github.com/iii-hq/iii
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/iii-hq/iii "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/iii-functions-and-triggers" ~/.claude/skills/iii-hq-iii-iii-functions-and-triggers && rm -rf "$T"
manifest:
skills/iii-functions-and-triggers/SKILL.mdsource content
Functions & Triggers
Comparable to: Serverless function runtimes, Lambda, Cloud Functions
Key Concepts
Use the concepts below when they fit the task. Not every worker needs all of them.
- A Function is an async handler registered with a unique ID
- A Trigger binds an event source to a function — types include http, durable:subscriber, cron, state, stream, and subscribe
- Functions invoke other functions via
regardless of language or worker locationtrigger() - The engine handles serialization, routing, and delivery automatically
- HTTP-invoked functions wrap external endpoints as callable function IDs
- Functions can declare request/response formats for documentation and discovery — auto-generated from types in Rust (via
) and Python (via type hints / Pydantic), or manually provided in Node.jsschemars::JsonSchema
Architecture
registerWorker() connects the worker to the engine, registerFunction defines handlers, registerTrigger binds event sources to those handlers, and the engine routes incoming events to the correct function. Functions can invoke other functions across workers and languages via trigger().
iii Primitives Used
| Primitive | Purpose |
|---|---|
| Connect worker to engine |
| Define a function handler |
| Bind an event source to a function |
| Invoke a function synchronously |
| Fire-and-forget invocation |
| Durable async invocation via queue |
Reference Implementation
- TypeScript: ../references/functions-and-triggers.js
- Python: ../references/functions-and-triggers.py
- Rust: ../references/functions-and-triggers.rs
Each reference shows the same patterns (function registration, trigger binding, cross-function invocation) in its respective language.
Common Patterns
Code using this pattern commonly includes, when relevant:
— connect to the engineregisterWorker('ws://localhost:49134', { workerName: 'my-worker' })
— register a handlerregisterFunction('namespace::name', async (input) => { ... })
— HTTP trigger (with optional middleware)registerTrigger({ type: 'http', function_id, config: { api_path, http_method, middleware_function_ids? } })
— queue triggerregisterTrigger({ type: 'durable:subscriber', function_id, config: { topic } })
— cron triggerregisterTrigger({ type: 'cron', function_id, config: { expression } })
— state change triggerregisterTrigger({ type: 'state', function_id, config: { scope, key } })
— stream triggerregisterTrigger({ type: 'stream', function_id, config: { stream } })
— pubsub subscriberregisterTrigger({ type: 'subscribe', function_id, config: { topic } })- Cross-language invocation: a TypeScript function can trigger a Python or Rust function by ID
— optional trigger metadataregisterTrigger({ ..., metadata: { owner: 'team', priority: 'high' } })
Request/Response Format (Auto-Registration)
Functions can declare their input/output schemas for documentation and discovery:
- Rust: Derive
on handler input/output types —schemars::JsonSchema
auto-generates JSON Schema (Draft 7) from the typeRegisterFunction::new() - Python: Use type hints (Pydantic models or primitives) on handler parameters and return types —
auto-extracts JSON Schema (Draft 2020-12)register_function() - Node.js: Pass
/request_format
manually in the registration message (e.g., via Zod'sresponse_format
)toJSONSchema()
Adapting This Pattern
Use the adaptations below when they apply to the task.
- Replace placeholder handler logic with real business logic (API calls, DB queries, LLM calls)
- Use
convention for function IDs to group related functionsnamespace::name - For HTTP endpoints, configure
andapi_path
in the trigger confighttp_method - For durable async work, use
instead of synchronous triggerTriggerAction.Enqueue({ queue }) - For fire-and-forget side effects, use
TriggerAction.Void() - Multiple workers in different languages can register functions that invoke each other by ID
Pattern Boundaries
- For HTTP endpoint specifics (request/response format, path params), prefer
.iii-http-endpoints - For queue processing details (retries, concurrency, FIFO), prefer
.iii-queue-processing - For cron scheduling details (expressions, timezones), prefer
.iii-cron-scheduling - For invocation modes (sync vs void vs enqueue), prefer
.iii-trigger-actions - Stay with
when the primary problem is registering functions, binding triggers, or cross-language invocation.iii-functions-and-triggers
When to Use
- Use this skill when the task is primarily about
in the iii engine.iii-functions-and-triggers - Triggers when the request directly asks for this pattern or an equivalent implementation.
Boundaries
- Never use this skill as a generic fallback for unrelated tasks.
- You must not apply this skill when a more specific iii skill is a better fit.
- Always verify environment and safety constraints before applying examples from this skill.