Self-hosted service
iii-hq/iii avatar
iii-hq/iii

iii-hq/iii: a shared runtime where workers, functions and triggers are the whole model

Effortlessly compose, extend, and observe every service in real-time for the first time ever.

18,752 stars1,261 forksRustLicense varies

At a glance

What is it?
iii collapses queues, cron, HTTP, state, observability and agents into one live system surface built on three primitives. Here is how the engine, Compose and the SDKs fit together, and where the approach still leaves you on your own.
Who is it for?
Adopt iii if you want a single runtime where services, schedules and agent tools register into one catalog and every call is traceable, and if you accept that the current release line is a 0.23.1 release candidate. Do not adopt it if you need a stable tagged release, a documented licence, or a guarantee that the CLI surface will not shift under you.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The integration tax iii is trying to remove

Most backends accumulate the same set of concerns before any business logic exists: a queue, a scheduler, an HTTP layer, state, tracing, and now an agent harness. Each one arrives with its own client library, retry policy, timeout configuration and trace format. The iii README frames this as a list of things you stop doing: a new observability tool no longer means an uncountable set of integrations, a new agent harness no longer means separate retry config, traces and timeouts, and a new queue no longer means vendor evaluation and weeks of integration.

The target reader is a platform team that publishes capabilities and an application team that registers functions and declares triggers. The README states that platform teams publish workers while application teams register functions and declare triggers, and that agents use the same catalog and the same function calls. That last sentence is the actual pitch: the interface a developer uses to extend the system is the same interface an agent uses, so an agent adding a capability is not a special code path.

It is not a framework for building a single application. It is a runtime that other processes register into. If you have one service and no plans for a second, the primitives add a layer without removing anything.

Workers, functions and triggers as the only mental model

The README calls Worker _ Function _ Trigger the entire mental model, and the repository layout backs that up. There is a crates/iii-worker crate, a crates/iii-compose crate, a crates/iii-supervisor crate, and an engine/ directory that builds the iii binary.

Workers are processes that register with the iii engine and then register triggers and functions. The README gives three examples of what a worker can be: a TypeScript API service, a Python data pipeline, a Rust microservice. Functions are units of work with a stable identifier, and the README's examples are content::classify and orders::validate. A function receives input, does work, and optionally returns output. Triggers are anything that causes a function to run: a direct call, an HTTP endpoint, a cron schedule, a queue subscription, a state change, a stream event. The README describes triggers as declarative, with the worker stating that a function runs when a given thing happens, and iii handling routing, serialization and delivery.

The design consequence is that a function's identity is a string, not a language-level symbol. Two workers written in different languages can call each other because the contract is the identifier plus serialized input. The cost is that nothing in the type system enforces the shape of that input across a language boundary, and the README does not describe a schema or validation step for function inputs.

Compose is the piece that makes this dynamic. Workers can be declared ahead of time or added to a running daemon, and each worker that joins the live catalog notifies every other worker, which can then call it immediately.

Installing iii and running a first project

The README's install path is a shell script served from install.iii.dev. It is a curl piped into sh, so read it before running it if that matters to you.

bash
curl -fsSL https://install.iii.dev/iii/main/install.sh | sh

After that, the Quick Start scaffolds a project and starts the engine together with the workers declared for that project. The README shows iii project init taking a directory name, then iii compose --up run from inside it.

bash
iii project init myapp
cd myapp
iii compose --up

The README notes that you declare project workers in worker-compose.yaml, so the file exists in the scaffold even though the README does not reproduce its contents. The full walkthrough lives at the Quickstart guide on iii.dev/docs/quickstart.

Adding a worker to a running system uses iii trigger with a namespace flag and the compose::add function. The README uses worker=queue and worker=agent as examples, and explicitly generalizes to worker=<anything>.

bash
iii trigger -n dev compose::add worker=queue
iii trigger -n dev compose::add worker=agent

What you should see, per the README, is the worker joining the live catalog and every other worker being notified. Browse available workers at workers.iii.dev before writing one.

If you are embedding iii in your own code rather than using the CLI, the SDKs install as ordinary packages: pnpm add iii-sdk or npm install iii-sdk for Node.js, pip install iii-sdk for Python, iii-sdk in Cargo.toml for Rust, and go get github.com/iii-hq/iii/sdk/packages/go/iii for Go. Note that the Makefile in the repository exports III_TELEMETRY_ENABLED := false for local development, and the engine defaults are not documented in the README.

What the repository does not tell you

The licence is the first gap. package.json carries "license": "SEE README.md and CONTRIBUTING.md", and the repository root holds a LICENSE.spdx file rather than a plain LICENSE. The README does not state a licence identifier, and it does not point at LICENSE.spdx. If you need to know whether you can ship iii inside a closed product, the answer is not in the README, and the SPDX file is the thing to open. The workspace authors field reads Motia LLC, and the Cargo.toml also lists a crates/motia-tools member, so the project and Motia share code and ownership.

Release maturity is the second. The recent releases are all release candidates: iii/v0.23.1-rc.4, rc.3 and rc.2, and the workspace version in Cargo.toml is 0.23.1-rc.6, which is ahead of the newest published tag. Three release candidates in six days is a fast cadence, and a 0.x version with rc tags means the CLI surface and the worker protocol can change between them. The last push to the default branch was on 2026-09-10, so the repository is being worked on, but the versioning tells you more about stability than the push date does.

Operational behaviour is the third gap. The README does not document rollback, does not describe what happens to in-flight calls when a worker is removed from a running system, and does not state a persistence model for state. The Makefile shows the local development engine listening on ws://localhost:49199 and http://localhost:3199 with fixture configs under sdk/fixtures, which tells you the engine is WebSocket-driven, but those are test fixtures rather than documented production defaults.

The wrong-tool case follows from all three. If your team needs a versioned release with a published licence before it can deploy anything, iii in its current state is not that. If your problem is a single queue with one consumer, adding a runtime to route it is more moving parts than the queue itself.

iii against a workflow engine like Motia

The comparison that matters is with the project's own lineage. The workspace authors are Motia LLC, the crates list includes motia-tools, and the related searches for this project are dominated by Motia queries, so anyone evaluating iii will have Motia on the same shortlist.

A workflow engine of that kind models a pipeline: you define steps and the edges between them, and the engine runs the graph. iii does not define a graph. It defines a registry. A worker joins, publishes functions with stable identifiers, and declares what triggers them. There is no top-level flow to read; the composition is whatever the registered triggers and calls produce at runtime. The README's own framing is that extending iii is adding a Compose worker, composing iii is calling functions, and observing iii is opening the trace.

That difference decides the fit. If your problem is a known sequence of steps that must run in order with retries at each stage, a graph-shaped tool expresses it directly and iii makes you encode the ordering yourself in function calls. If your problem is that capabilities keep appearing from different teams and languages and you want them callable the moment they register, iii's registry model is the one that scales, because nothing has to be rewired when a worker is added. The README's claim that every other worker is notified and can call a new worker immediately is the whole argument, and it is also the thing to verify in your own environment before you build on it.

Maintenance, upgrades and licence cost

The repository is not archived and the last push was on 2026-09-10, so this is a codebase under current work rather than an abandoned one. The README makes no statement about a support window or a release cadence commitment.

The upgrade cost is visible in the versioning. The workspace version is 0.23.1-rc.6 while the newest published release is 0.23.1-rc.4, and the three most recent releases are all release candidates. Upgrading means tracking a 0.x line where the engine, the CLI, the Compose worker format and four language SDKs all move together. The monorepo pins its own toolchain tightly: packageManager is [email protected] and engines requires node >=20, so building from source also pins your Node version. The workspace uses Rust edition 2024, which sets a minimum toolchain for anyone building the engine themselves.

Licence implications are unresolved from the README alone. The root has LICENSE.spdx, package.json defers to README.md and CONTRIBUTING.md, and no licence identifier appears in the README. Before adopting iii in anything you distribute, read LICENSE.spdx and the licence section of CONTRIBUTING.md and confirm the terms with whoever handles licensing on your side. Do not take the absence of a stated licence as permission.

Editorial conclusion

Adopt iii if you want a single runtime where services, schedules and agent tools register into one catalog and every call is traceable, and if you accept that the current release line is a 0.23.1 release candidate. Do not adopt it if you need a stable tagged release, a documented licence, or a guarantee that the CLI surface will not shift under you. Before committing, read LICENSE.spdx and the licence note in CONTRIBUTING.md, confirm which release candidate you are pinning, and check that the workers you need already exist at workers.iii.dev rather than assuming you can write them quickly.

Frequently asked questions

How do I install iii?

The README gives a shell installer: curl -fsSL https://install.iii.dev/iii/main/install.sh | sh. After that, iii project init myapp scaffolds a project and iii compose --up starts the engine with the project's workers.

What are workers, functions and triggers in iii?

The README calls Worker _ Function _ Trigger the entire mental model. Workers are processes that register with the iii engine and then register triggers and functions; functions are units of work with a stable identifier such as content::classify; triggers are anything that causes a function to run, including a direct call, an HTTP endpoint, a cron schedule, a queue subscription, a state change or a stream event.

Can I add a worker to iii while it is running?

Yes. The README shows iii trigger -n dev compose::add worker=queue and notes that each worker joining the live catalog notifies every other worker, which can call it immediately. The same command pattern generalizes to worker=agent and worker=<anything>.

Official sources

  1. iii-hq/iii on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/iii-hq-iii.svg)](https://hysenlabs.com/projects/iii-hq-iii)