Documentation Index
Fetch the complete documentation index at: https://motiadev-docs-phase-2.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
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.
Node / TypeScript
Python
Rust
CLI
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
});
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
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?;
iii trigger math::add a=2 b=3
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. Routes the invocation through a named
queue with retries; the call returns once the message is enqueued.
Workers can provide their own TriggerActions. Check each worker’s
documentation for the action types it offers.
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.
Register a trigger
If you’re authoring a worker, you’ll want to refer to Creating Workers /
Triggers to learn the
difference between registering a trigger, and registering a trigger type.
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.
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.
Node / TypeScript
Python
Rust
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" },
});
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"},
})
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,
})?;
Per-type configuration is documented in each worker’s Worker Docs (e.g.
iii-http for the http type).
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.
Node / TypeScript
Python
Rust
// 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
});
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
})
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,
})?;
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.
Node / TypeScript
Python
Rust
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",
},
});
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",
},
})
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,
})?;
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.
Node / TypeScript
Python
Rust
const trigger = worker.registerTrigger({
type: "http",
function_id: "math::add",
config: { api_path: "/math/add", http_method: "POST" },
});
trigger.unregister();
trigger = worker.register_trigger({
"type": "http",
"function_id": "math::add",
"config": {"api_path": "/math/add", "http_method": "POST"},
})
trigger.unregister()
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();