iii create --template quickstart --directory quickstartcd quickstart
This creates the two workers that you’ll run: a Python worker that adds two numbers, and a TypeScript worker that calls the Python worker through the iii engine.
The engine is now listening on ws://localhost:49134. Keep this terminal open and open a second terminal in the quickstart directory for the remaining commands.
Workers only need a WebSocket connection to the iii engine. They can run locally, in the cloud, replicated in kubernetes, or anywhere else.
iii worker add ./workers/math-worker
You should see:
✓ Worker math-worker added to config.yamlPath /Users/tony/iii/projects/testing/quickstart/workers/math-worker✓ Using cached deps (use --force to reinstall)✓ math-worker started (pid: 12345)✓ Worker auto-started
This worker registered the function math::add with the engine. You could call this function right now using the command below.
iii trigger --function-id='math::add' --payload='{"a": 2, "b": 3}'
However this is not much different than running an equivalent script on its own. The utility of iii comes from being able to place
any functionality into a worker and then seamlessly compose that worker with other workers.
Workers need a moment to install their runtime dependencies after being added. If you see "message": "Function math::add not found", wait a few seconds and try again.
✓ Worker caller-worker added to config.yamlPath /Users/tony/iii/projects/testing/quickstart/workers/caller-worker✓ Using cached deps (use --force to reinstall)✓ caller-worker started (pid: 23456)✓ Worker auto-started
This worker registered the function math::add_two_numbers with the engine.
The iii worker add command incrementally adds built-in workers to your running system. Start by adding the state worker, which gives every function access to a persistent key-value store.From the folder containing iii’s config.yaml run:
iii worker add iii-state
Now open workers/math-worker/math_worker.py and uncomment the state block so the handler looks like this:
def add_handler(payload: dict) -> dict: a = payload.get("a", 0) b = payload.get("b", 0) logger.info(f"math::add called in Python with a={a}, b={b}") result = {"c": a + b} running_total = iii.trigger( { "function_id": "state::get", "payload": {"scope": "math", "key": "running_total"}, } ) new_total = (running_total or 0) + result["c"] iii.trigger( { "function_id": "state::set", "payload": {"scope": "math", "key": "running_total", "value": new_total}, } ) result["running_total"] = new_total return result
Save the file and call the function a few times:
iii trigger --function-id='math::add' --payload='{"a": 2, "b": 3}'
{ "c": 5, "running_total": 5 }
iii trigger --function-id='math::add' --payload='{"a": 10, "b": 20}'
{ "c": 30, "running_total": 35 }
The running total persists across every call — including calls that arrive through math::add_two_numbers.
import { registerWorker, Logger } from 'iii-sdk';const iii = registerWorker(process.env.III_URL ?? 'ws://localhost:49134');const logger = new Logger();iii.registerFunction( 'math::add_two_numbers', async (payload: { a: number; b: number }) => { logger.info('math::add_two_numbers called in TypeScript', payload); const result = await iii.trigger({ function_id: 'math::add', payload, }); return result; },);
registerWorker connects to the engine the same way the Python worker does. The iii.trigger() call inside the handler invokes
math::add on the Python worker through the engine. The TypeScript worker doesn’t need to know where the math::add function
is running, its language, or anything else.
Each worker has an iii.worker.yaml that describes how to run the worker. Here is the Python worker’s manifest.
While these workers are started with the iii worker add command they do not need to be running alongside the iii
instance. These workers can run anywhere and even be replicated. Every worker simply connects to iii over WebSocket.
iii then handles all routing.
iii contains an interactive web interface to help observe a iii system end to end. It’s particularly useful for debugging.The console can be started in a new terminal:
iii console
Open your browser to http://localhost:3113/ to see logs, traces, and runtime state for the running system.
See the full Console documentation for details on invoking functions, inspecting traces, viewing state, and more.
You scaffolded a project, started two workers in different languages, called functions across them, added persistent state, and exposed everything over HTTP — all by incrementally adding workers to a running system.
How to use Functions & Triggers
Learn how to register functions, trigger them, and bind them to events.
Concepts
Understand Functions, Triggers, and Workers from a conceptual point of view.