Skip to main content

Goal

Create a custom trigger type that fires functions in response to events iii doesn’t handle out of the box — for example incoming webhooks, file-system changes, or third-party service callbacks.

Steps

1. Implement the trigger handler

A trigger handler is an object (Node) or class/trait (Python, Rust) with two callbacks:
  • registerTrigger — called when a function binds to your trigger type. Set up whatever listener or subscription is needed.
  • unregisterTrigger — called when the binding is removed. Tear down the listener.
Both callbacks receive a TriggerConfig containing the trigger id, the bound function_id, and the caller-supplied config.
webhook-trigger-type.ts
import { registerWorker, TriggerHandler } from 'iii-sdk'
import express from 'express'

type WebhookConfig = { path: string }

const iii = registerWorker(process.env.III_URL ?? 'ws://localhost:49134')

const app = express()
app.use(express.json())

const routes = new Map<string, string>()

const webhookHandler: TriggerHandler<WebhookConfig> = {
  registerTrigger: async ({ function_id, config }) => {
    routes.set(config.path, function_id)
    app.post(config.path, async (req, res) => {
      const result = await iii.trigger({ function_id, payload: req.body })
      res.json(result)
    })
  },
  unregisterTrigger: async ({ config }) => {
    routes.delete(config.path)
  },
}

2. Register the trigger type

Call registerTriggerType with an id, a description, and the handler from above. The id is the string other workers will reference when they call registerTrigger.
webhook-trigger-type.ts
iii.registerTriggerType(
  { id: 'webhook', description: 'External webhook trigger' },
  webhookHandler,
)

app.listen(4000)

3. Bind functions to the custom trigger

From any worker — including one written in a different language — functions can now bind to the webhook trigger type with registerTrigger. The config you pass in config is forwarded directly to your handler’s registerTrigger callback.
github-webhook.ts
import { registerWorker, Logger } from 'iii-sdk'

const iii = registerWorker(process.env.III_URL ?? 'ws://localhost:49134')

iii.registerFunction({ id: 'github::push' }, async (payload) => {
  const logger = new Logger()
  logger.info('Push event received', { repo: payload.repository?.full_name })
  return { ok: true }
})

iii.registerTrigger({
  type: 'webhook',
  function_id: 'github::push',
  config: { path: '/hooks/github' },
})

4. Unregister the trigger type

When the worker that owns the trigger type shuts down, call unregisterTriggerType to remove it from the engine. Any triggers still bound to the type will stop firing.
teardown.ts
iii.unregisterTriggerType({ id: 'webhook', description: 'External webhook trigger' })

Result

Your custom webhook trigger type is registered with the engine. Any function in any worker can bind to it with registerTrigger({ type: 'webhook', ... }), and the engine routes registration and teardown calls to your handler. The same pattern works for any event source — file watchers, message brokers, hardware signals, or anything else you can subscribe to in code.
Before creating a custom type, check the built-in trigger typeshttp, cron, queue, subscribe, state, and stream cover the most common event sources.