Iii iii-trigger-actions
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-trigger-actions" ~/.claude/skills/iii-hq-iii-iii-trigger-actions && rm -rf "$T"
manifest:
skills/iii-trigger-actions/SKILL.mdsource content
Trigger Actions
Comparable to: RPC vs message queue vs fire-and-forget patterns
Key Concepts
Use the concepts below when they fit the task. Not every invocation needs all three modes.
- Synchronous (default): caller blocks until the function returns a result or times out
- Void (
): fire-and-forget dispatch, returns immediately withTriggerAction.Void()
, no retry guaranteesnull - Enqueue (
): routes through a named queue with automatic retries and backoff, returns aTriggerAction.Enqueue({ queue })messageReceiptId - Decision guide: need the result? use sync. Must complete reliably? use enqueue. Optional side effect? use void.
Architecture
The caller invokes
trigger() with an optional action parameter. Synchronous mode waits for the handler result. Void mode dispatches and returns null immediately. Enqueue mode places the payload on a named queue where a consumer processes it with retry guarantees.
iii Primitives Used
| Primitive | Purpose |
|---|---|
| Synchronous invocation, blocks for result |
| Fire-and-forget, returns immediately with null |
| Durable async via named queue, returns receipt |
| CLI trigger (part of the engine binary) |
| CLI flag to set trigger timeout (default 30s) |
Reference Implementation
See ../references/trigger-actions.js for the full working example — a comparison of all three
Also available in Python: ../references/trigger-actions.py
Also available in Rust: ../references/trigger-actions.rs invocation modes showing when and how to use sync, void, and enqueue patterns.
Common Patterns
Code using this pattern commonly includes, when relevant:
— sync, get result directlyawait iii.trigger({ function_id: 'users::get', payload: { id } })
— fire-and-forgetiii.trigger({ function_id: 'analytics::track', payload: event, action: TriggerAction.Void() })
— durable enqueueiii.trigger({ function_id: 'orders::process', payload: order, action: TriggerAction.Enqueue({ queue: 'payments' }) })- Sync returns the function result directly
- Void returns
/nullNone - Enqueue returns
for tracking{ messageReceiptId: string }
— invoke via CLIiii trigger --function-id='users::get' --payload='{"id":"123"}'
— with custom timeoutiii trigger --function-id='users::get' --payload='{"id":"123"}' --timeout-ms=5000
Adapting This Pattern
Use the adaptations below when they apply to the task.
- Default to synchronous when the caller needs the result to proceed
- Use void for logging, analytics, or any side effect where failure is acceptable
- Use enqueue for anything that must complete reliably — payments, emails, notifications
- Combine modes in a single handler: sync call for validation, then enqueue for processing
- Named queues let you configure retries and concurrency per workload type
Pattern Boundaries
- For queue configuration (retries, concurrency, FIFO ordering), prefer
.iii-engine-config - For DLQ handling when enqueued jobs exhaust retries, prefer
.iii-dead-letter-queues - For function registration and trigger binding, prefer
.iii-functions-and-triggers - Stay with
when the primary problem is choosing the right invocation mode.iii-trigger-actions
When to Use
- Use this skill when the task is primarily about
in the iii engine.iii-trigger-actions - 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.