}) ``` </Tab> <Tab title="Rust"> ```rust use iii_sdk::{InitOptions, TriggerAction, TriggerRequest, register_worker}; use serde_json::json; let url = std::env::var("III_URL").expect("III_URL must be set"); let worker = register_worker(&url, InitOptions::default()); let result = worker .trigger(TriggerRequest { function_id: "math::add".to_string(), payload: json!({ "a": 2, "b": 3 }), action: None, // action: Some(TriggerAction::Void), // fire-and-forget // actio...
Scanned 9/3/2026
Install to Claude Code
npx -y skills add iii-hq/iii --skill using-iii --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Using Iii?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/iii-hq-using-iii-287ee840)More formats (shields.io, HTML) on the badges page.
<!-- generated by iii-skill-render. DO NOT EDIT (changes here are overwritten on the next render). Edit docs/0-16-0/using-iii/triggers.mdx. -->
{/* TODO: Re-link worker references to https://workers.iii.dev/workers/<name> once the Worker Docs migration ships. */}
## Call a function directly
Call a function by its `function_id` from worker code (`worker.trigger(...)`) or from the terminal
(`iii trigger`). The engine routes the call to whatever worker registered the function; no trigger
registration is involved. The `action` field controls delivery: by default the call waits for the
function to return its result, or for the configured timeout to fire. Pass a different
`TriggerAction` to change that.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
import { registerWorker, TriggerAction } from "iii-sdk";
const url = process.env.III_URL;
if (!url) throw new Error("III_URL must be set");
const worker = registerWorker(url);
const result = await worker.trigger({
function_id: "math::add",
payload: { a: 2, b: 3 },
// action: TriggerAction.Void(), // fire-and-forget
// action: TriggerAction.Enqueue({ queue: "math" }), // route through iii-queue
});
```
</Tab>
<Tab title="Python">
```python
import os
from iii import register_worker, InitOptions, TriggerAction
worker = register_worker(
os.environ.get("III_URL"),
InitOptions(worker_name="caller"),
)
result = worker.trigger({
"function_id": "math::add",
"payload": {"a": 2, "b": 3},
# "action": TriggerAction.Void(), # fire-and-forget
# "action": TriggerAction.Enqueue(queue="math"), # route through iii-queue
})
# result = await worker.trigger_async({...}) # awaitable form for asyncio callers
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::{InitOptions, TriggerAction, TriggerRequest, register_worker};
use serde_json::json;
let url = std::env::var("III_URL").expect("III_URL must be set");
let worker = register_worker(&url, InitOptions::default());
let result = worker
.trigger(TriggerRequest {
function_id: "math::add".to_string(),
payload: json!({ "a": 2, "b": 3 }),
action: None,
// action: Some(TriggerAction::Void), // fire-and-forget
// action: Some(TriggerAction::Enqueue { queue: "math".to_string() }), // route through iii-queue
timeout_ms: None,
})
.await?;
```
</Tab>
<Tab title="CLI">
```bash
iii trigger math::add a=2 b=3
```
</Tab>
</Tabs>
Some common actions are:
- **Default (synchronous)**. No `action` set. The call waits for the function to return its result
or for the configured timeout to fire.
- **`TriggerAction.Void()`**. Fire-and-forget. The call returns immediately; the function still runs
but the caller doesn't see the result.
- **`TriggerAction.Enqueue({ queue })`**. Provided by
[iii-queue](https://workers.iii.dev/workers/iii-queue). Routes the invocation through a named
queue with retries; the call returns once the message is enqueued.
<Note>
Workers can provide their own `TriggerAction`s. Check each [worker's
documentation](https://workers.iii.dev) for the action types it offers.
</Note>
<Note>
In Python, every blocking method has an awaitable twin (`trigger_async`, `shutdown_async`,
`create_channel_async`) for use inside `asyncio`. See the [Python SDK
reference](../sdk-reference/python-sdk#trigger--trigger_async).
</Note>
## Register a trigger
<Note>
If you're authoring a worker, you'll want to refer to [Creating Workers /
Triggers](../creating-workers/triggers#bind-a-function-to-an-existing-trigger-type) to learn the
difference between registering a trigger, and registering a trigger type.
</Note>
Functions can also run when a trigger is satisfied. A trigger can be any event that happens such as
a request to an `http` endpoint, a `cron` job, a change in `state`, or any other trigger that a
worker supports. You can also [write your own](../creating-workers/triggers).
You bind triggers to functions via the `function_id`. The trigger declares its `type`, its `config`
(defined by each type), and the function to invoke.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
import { registerWorker } from "iii-sdk";
const url = process.env.III_URL;
if (!url) throw new Error("III_URL must be set");
const worker = registerWorker(url);
worker.registerTrigger({
type: "http",
function_id: "math::add",
config: { api_path: "/math/add", http_method: "POST" },
});
```
</Tab>
<Tab title="Python">
```python
import os
from iii import register_worker, InitOptions
worker = register_worker(
os.environ.get("III_URL"),
InitOptions(worker_name="my-worker"),
)
worker.register_trigger({
"type": "http",
"function_id": "math::add",
"config": {"api_path": "/math/add", "http_method": "POST"},
})
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::{InitOptions, RegisterTriggerInput, register_worker};
use serde_json::json;
let url = std::env::var("III_URL").expect("III_URL must be set");
let worker = register_worker(&url, InitOptions::default());
worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "math::add".into(),
config: json!({ "api_path": "/math/add", "http_method": "POST" }),
metadata: None,
})?;
```
</Tab>
</Tabs>
Per-type configuration is documented in each worker's Worker Docs (e.g.
[iii-http](https://workers.iii.dev/workers/iii-http) for the `http` type).
## Handling missing triggers
When the engine cannot register a trigger, most commonly because the trigger type's worker is not
active in the project, it sends a `TriggerRegistrationResult` with an `error` body back to the
worker that initiated the request and logs it.
For known trigger types (ex. `http`, `subscribe`, `state`, `durable:subscriber`, `stream`), the
error message will include the install command for the missing worker. If it doesn't you can find
the worker that exposes the needed type at [workers.iii.dev](https://workers.iii.dev)
## Bind multiple triggers to one function
It's valid to bind multiple triggers to the same `function_id` and this can be done across any
number of types. Register a second trigger with the same `function_id` and a different type or
config; the function runs unchanged whether the call arrives over HTTP, on a cron schedule, or from
a queue message.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
// Same handler runs for an HTTP POST and a weekly cron tick.
worker.registerTrigger({
type: "http",
function_id: "reports::generate",
config: { api_path: "/reports/generate", http_method: "POST" },
});
worker.registerTrigger({
type: "cron",
function_id: "reports::generate",
config: { expression: "0 0 9 * * 1" }, // Every Monday at 09:00
});
```
</Tab>
<Tab title="Python">
```python
worker.register_trigger({
"type": "http",
"function_id": "reports::generate",
"config": {"api_path": "/reports/generate", "http_method": "POST"},
})
worker.register_trigger({
"type": "cron",
"function_id": "reports::generate",
"config": {"expression": "0 0 9 * * 1"}, # Every Monday at 09:00
})
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::RegisterTriggerInput;
use serde_json::json;
worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "reports::generate".into(),
config: json!({ "api_path": "/reports/generate", "http_method": "POST" }),
metadata: None,
})?;
worker.register_trigger(RegisterTriggerInput {
trigger_type: "cron".into(),
function_id: "reports::generate".into(),
config: json!({ "expression": "0 0 9 * * 1" }), // Every Monday at 09:00
metadata: None,
})?;
```
</Tab>
</Tabs>
## Gate a trigger with a condition
A trigger can carry an optional `condition_function_id` (set inside the trigger's `config`). When
the trigger fires, the engine invokes the condition function first with the same payload the handler
would receive; the target `function_id` only runs when the condition returns truthy. The condition
is a regular registered function.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
worker.registerFunction(
"orders::is-priority",
async (payload: { customer_tier: string }) => payload.customer_tier === "gold",
);
worker.registerTrigger({
type: "http",
function_id: "orders::expedite",
config: {
api_path: "/orders/expedite",
http_method: "POST",
condition_function_id: "orders::is-priority",
},
});
```
</Tab>
<Tab title="Python">
```python
def is_priority(payload: dict) -> bool:
return payload.get("customer_tier") == "gold"
worker.register_function("orders::is-priority", is_priority)
worker.register_trigger({
"type": "http",
"function_id": "orders::expedite",
"config": {
"api_path": "/orders/expedite",
"http_method": "POST",
"condition_function_id": "orders::is-priority",
},
})
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::{RegisterFunction, RegisterTriggerInput};
use schemars::JsonSchema;
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize, JsonSchema)]
struct Payload { customer_tier: String }
worker.register_function(RegisterFunction::new(
"orders::is-priority",
|input: Payload| -> Result<bool, String> {
Ok(input.customer_tier == "gold")
},
));
worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "orders::expedite".into(),
config: json!({
"api_path": "/orders/expedite",
"http_method": "POST",
"condition_function_id": "orders::is-priority",
}),
metadata: None,
})?;
```
</Tab>
</Tabs>
## Unregister a trigger
Trigger registration returns a handle with an `unregister()` method. Call it to drop the trigger at
runtime; when the worker disconnects, all of its triggers are removed automatically.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
const trigger = worker.registerTrigger({
type: "http",
function_id: "math::add",
config: { api_path: "/math/add", http_method: "POST" },
});
trigger.unregister();
```
</Tab>
<Tab title="Python">
```python
trigger = worker.register_trigger({
"type": "http",
"function_id": "math::add",
"config": {"api_path": "/math/add", "http_method": "POST"},
})
trigger.unregister()
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::RegisterTriggerInput;
use serde_json::json;
let trigger = worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "math::add".into(),
config: json!({ "api_path": "/math/add", "http_method": "POST" }),
metadata: None,
})?;
trigger.unregister();
```
</Tab>
</Tabs>
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!