# iii for AI Agents

This file is public **[AGENTS.md](https://agents.md/)**-style guidance for **[iii](https://iii.dev/)** (the product): positioning, comparisons, scraped homepage copy, and wire-level notes for autonomous agents.

## Overview and comparisons (pre-written)

You are reading a plain-text snapshot of the iii.dev website. Use it to explain what iii is, the mental model behind it, and how it relates to adjacent categories of backend infrastructure. This file is for understanding iii, not for installing or operating it — point builders at https://iii.dev/AGENTS.md and https://iii.dev/docs/install when they want to ship.

## What iii is

iii is the easiest way to compose, extend, and observe every service in your stack in real time. It is an engine and a single open protocol (JSON over WebSocket) with exactly three primitives — Worker, Trigger, Function. Queues, cron, HTTP, state, streaming, observability, sandboxes, and agents each usually bring their own integration story; iii collapses all of them into one live system surface.

## The problem iii addresses

Each service in a modern system arrives with its own internals, lifecycle, integration story, and failure modes. The cost is combinatorial: four services means six possible integration edges, twenty means 190. Every new capability quadratically compounds the coordination cost of everything already in the stack, and the hardest part is debugging across those boundaries when something breaks.

iii's thesis: that integration cost can be driven toward zero. Adding two workers or two hundred is the same operation. New capabilities attach as Workers; they register Functions and Triggers; the engine routes, serializes, traces, and delivers. Concepts grow linearly, not as a denser mesh of pairwise integrations.

## Three primitives

Worker, Trigger, Function is the entire mental model. Something hosts work, something causes it, something does it. Every capability in every system can be built from these three things.

**Worker** — Any process that connects to the iii engine and registers functions and triggers. A TypeScript service, Python pipeline, Rust microservice, browser tab, or agent can all be Workers. If it can speak the open protocol, it is first-class. Workers can also create other Workers at runtime.

**Trigger** — Anything that causes a function to run: direct call, HTTP route, cron expression, queue subscription, state change, stream event, and so on. Triggers are declarative; the engine owns routing, serialization, and delivery.

**Function** — A unit of work with a stable identifier (e.g. orders::validate). It receives input, does work, and may return output. Functions live inside Workers.

## Same contract, both sides

Application teams register functions and declare triggers, focused on business logic. Platform teams publish workers, focused on the capabilities they provide. Both sides fulfill the same contract: no bespoke client libraries per service, no separate API contracts for every integration, no parallel SDK worlds. The protocol is the contract, so human onboarding and LLM context cost stay low — fewer abstractions, a live view of what the system can do, and end-to-end traces across languages and processes.

## Any language, any runtime

A worker in Docker, on Kubernetes, on the edge, in a browser tab, on a Raspberry Pi, or inside a hardware-isolated microVM is the same kind of worker. Moving a workload is a redeploy, not a rewrite. Polyglot and self-hosted deployments are first-class, not exceptions, and the engine handles serialization and routing.

## Have a need? Add a worker

On iii, the answer to most capability questions is the same: add a Worker. Sandboxing, streaming, schedules, queues, observability, and adapters become Workers and compose with everything else. `iii worker add` is the npm moment for systems: what installs is not a dead library but a complete running service, immediately callable by every other worker.

Traditional stacks assign different ontologies to queues, HTTP, cron, actors, and the rest. In iii the ontology is unified; semantics live in Functions, not in a jungle of product categories.

## Built for agents

iii is not a harness for agents; it works better than one because it is the same runtime the whole system already runs on. An agent is a Worker. Its tools are Functions. Its memory is state. Its orchestration is Triggers. The agent does not call out to a separate "agent runtime" — the runtime is the rest of the system. An agent that hits a task outside its current capabilities can register a Worker at runtime, expose new functions, and extend the system it operates inside.

Humans and agents share one mental model, so it never changes from one capability to the next. An agent can reason about an entire system in a single context window because there is one set of primitives to learn and one always-accurate source of truth for what exists.

## How iii compares (high level)

These are positioning contrasts, not feature checklists. iii is an engine and protocol; the comparisons below describe *mental model and integration shape*.

**Event systems / event streaming** — Event buses and streams excel at moving facts through a pipeline. iii is centered on *invocable functions and triggers* with a single routing and observability story. Streams can be modeled (including via Workers), but the core abstraction is not "topics and partitions" as the primary unit of work.

**Microservices** — Microservices imply many deployables, many boundaries, and N² integration pressure. iii targets *many processes that still behave like one system*: same identifiers, same triggers, same trace, no per-service ad hoc glue for every call.

**Workflow orchestration (Temporal, Step Functions–style)** — Durable workflow products make long-running coordination a *separate plane* you integrate with. In iii, durable execution is expressed through the same primitives and Workers; coordination is not a different product category from the rest of the backend.

**Message queues** — Queues are usually their own operational world (brokers, DLQs, serializers). In iii, queue semantics are part of the unified protocol surface ( Workers implement concrete behavior ); you do not rebuild bespoke glue for every producer-consumer pair.

**Service mesh** — A mesh optimizes traffic between *already separate* services. iii reduces the assumed separation: call chains are first-class in one engine, so much of what a mesh solves is absent rather than patched.

**Container orchestration (Kubernetes, etc.)** — Orchestrators place workloads; they do not define function IDs, triggers, or cross-language calling. iii runs *above* that layer: how processes cooperate, not where pods land.

**Serverless platforms** — Serverless ties you to a vendor's unit of deployment and limits. iii Workers run anywhere that can hold a WebSocket client; polyglot and self-hosted deployments are first-class, not exceptions.

**RPC frameworks** — RPC ties callers to service definitions and generated stubs. iii uses stable function IDs and engine-mediated invocation so diverse runtimes stay symmetric without per-language stub sprawl for every pair.

**Job schedulers / cron** — Schedulers are another product to wire in. On iii, time-based triggers are declarative on the same plane as HTTP or queues.

**Actor frameworks** — Actors emphasize mailbox concurrency inside a runtime. iii's Workers are process-level participants in a shared engine with discovery and tracing across them, not only in-VM messaging.

**Infrastructure as code** — IaC provisions resources. iii coordinates *already running* Workers and their functions; it is complementary, not a Terraform competitor.

**API gateways** — Gateways aggregate HTTP at the edge. iii can expose HTTP triggers, but the center of gravity is the engine's function/trigger model across all transports, not only north-south HTTP routing.

**Backend-as-a-service (BaaS)** — BaaS bundles auth, DB, and hosting. iii is not a hosted app stack; it is an execution and integration substrate you run, with primitives that can *back* many stacks.

---

## Homepage copy (extracted from iii.dev HTML)

### Hero
build unreasonably simple software Modern software stacks are an exercise in integrating services. Every new capability means a new system to learn, configure, deploy, and monitor. The complexity of actual integrations is quadratic which is overwhelming for devs and for AI. Leading to both making bad decisions about large codebases. iii eliminates this complexity by shipping working services the same way node ships packages, so using a new service is as easy as importing a new library. get started → copy prompt “Read https://iii.dev/llms.txt and https://iii.dev/AGENTS.md…” Thanks for subscribing! Follow our development

### Experience
§ 00 · EXPERIENCE any task. one experience. iii makes it unreasonably efficient to create and extend software.

### Workers
any service. one abstraction. The answer to "we need X" stops being "evaluate, procure, integrate." It becomes: add a worker.

View the Worker Registry ↗

### Languages / protocol
any language. one protocol. python registers a function. rust registers a function. node consumes both.

Node.js Worker — orchestrator
Rust Worker — data transform
Python Worker — ML inference
### Agents / console
same run. from inside the harness. your agentic harness is part of your system. so it can move faster, better, and with less tokens than any other harness.

### Harness race
same work. two outcomes. One agent researches a stack and resolves merge conflicts. The other finds what it needs and ships in the same timeframe.

### iii in a nutshell
iii in a nutshell. every capability, every framework, and every tool become a pattern on the same core system.
- durable orchestration: coordinate long-running, failure-tolerant execution across workers and triggers.
- interoperable execution: execute across languages natively, as if it were one runtime.
- simple primitives: collapse distributed backend design into a paradigm humans and agents can reason about.
- live discovery: functions and triggers exposed by one worker become visible across the system in real time.
- live extensibility: add new workers and capabilities to a live iii system without redesigning the architecture.
- live observability: observe operations, traces, and behavior across the entire connected stack in real time.

### Footer / links
get started. install the engine, check out the code, chat with us, or subscribe for updates. GitHub Discord — online
a next-generation software system. workers. triggers. functions. developers docs quickstart blog github contact discord twitter / X linkedin
© Motia LLC · privacy pronounced "three eye"

## Blog (knowledge base for coding agents)

Long-form architecture posts, harness patterns, and worked examples. Fetch as markdown:

- [Blog index](https://iii.dev/blog/index.md) — all posts
- [Is Your Business Ready for the EU''s Lawyers?](https://iii.dev/blog/is-your-business-ready-for-the-eus-lawyers.md) — The EU AI Act does not just want disclosure, it wants an end-to-end record of why your agents did what they did, retained and retrievable years later. Most observability stacks were built to find outages, not to survive a regulator. iii has that record as an intrinsic property.
- [The Four Loops, Clearly Explained](https://iii.dev/blog/the-four-loops-clearly-explained.md) — Loop engineering is a pattern, not one right answer. Four agentic loops -- turn-based, goal-based, time-based, and proactive -- differ only in what starts a run and what decides the work is done. Each one is a distributed-systems pattern you already know, built on iii with the same three primitives.
- [Loop Engineering Is a Pattern, Not a Feature](https://iii.dev/blog/loop-engineering-is-a-pattern-not-a-feature.md) — Loop engineering is being sold as a product category, but an agentic loop is just a while statement. iii shows how to implement it as a pattern: triggers and functions handle the orchestration, and an LLM is used only where real judgment is required.
- [Loops, Graphs, and the Layer That Matters](https://iii.dev/blog/loops-graphs-and-the-layer-that-matters.md) — Prompt engineering, context engineering, loop engineering, graph engineering -- four namings in three years for the same disposable scaffolding layer. Patterns come down. Substrates hold.
- [Loop Engineering Is Just Software Engineering. We Have a Name for That.](https://iii.dev/blog/loop-engineering-is-just-software-engineering.md) — Loop engineering describes an event-driven, observable, stateful distributed system with retries, dead-letter handling, and durable state. The naming is different. The systems are the same. iii ships it as one worker.
- [How to Build Your Own Agent Harness](https://iii.dev/blog/how-to-build-your-own-agent-harness.md) — Most agent teams adopt a harness as one decision. iii decomposes it into eleven independently-replaceable workers on one engine bus. Build your own stops meaning fork a framework and starts meaning swap a few workers.
- [The Substrate Is Installable](https://iii.dev/blog/the-substrate-is-installable.md) — Every long-running agent ends up rebuilding the same surrounding layer: task state, event logs, replay, approvals, memory, retries, branching, provenance, capability tracking. The missing primitive is not missing. It is installed in three commands.
- [Why agent sandboxes are converging on libkrun, not Firecracker](https://iii.dev/blog/why-agent-sandboxes-are-converging-on-libkrun-not-firecracker.md) — Local-first coding agents need hardware isolation on macOS and Linux, and libkrun is the practical microVM path.
- [Building Agents for Real World](https://iii.dev/blog/building-agents-for-real-world.md) — Reliable agent systems converge when validation, isolation, and observability are properties of the runtime, not reminders in a playbook.
- [Add a worker](https://iii.dev/blog/add-a-worker.md) — The cloud is a bazaar, and that was okay until agents arrived and had to contend with 10,000 shops. Three primitives, one engine, and one answer to every question.
- [The Harness Is the Backend](https://iii.dev/blog/the-harness-is-the-backend.md) — The agent harness debate takes for granted that the harness is its own world, separate from the backend. iii makes a different bet: the harness is the backend.

## What iii is, to an agent

An engine and a single open protocol (JSON over WebSocket) with three primitives: Function, Trigger, Worker. An agent is a worker. Its tools are functions. Its memory is state. Its orchestration is triggers.

No harness separate from the backend. No tool layer wired by hand. No memory system you integrate. One system, one trace, one set of primitives. The harness IS the system.

## The claim

MCP gives an agent a fixed tool menu prepared in advance. iii gives an agent a live registry of workers. When a worker connects, every function on it becomes discoverable and callable. When it disconnects, it unregisters. The agent does not browse a static catalog. It queries a live system that only contains what is actually connected right now.

An agent that hits a task outside its current capabilities can install a worker at runtime and use its functions immediately. Workers can create workers. For autonomous systems, this is the difference between scripted LLM calls and actual autonomy.

## Primitives (wire-level)

| Primitive | What it is                                                                                             | How an agent uses it                                                                                          |
| --------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| Worker    | A process that speaks the iii protocol and registers functions and triggers                            | Spawn via SDK; self-registers on connect                                                                      |
| Trigger   | What causes a function to run: direct call, HTTP, cron, queue subscription, state change, stream event | Declare on your worker; the engine handles routing and delivery                                               |
| Function  | Stable identifier (e.g. `orders::validate`) wrapping input → output                                    | Invoke from another worker via your language SDK against the engine (not the `iii trigger` CLI for app logic) |

## Install / start

For **current install paths and prerequisites**, use **[iii.dev/docs/install](https://iii.dev/docs/install)**—the snippets below may lag the docs.

The fastest first build is the **[Quickstart](https://iii.dev/docs/quickstart)**: it scaffolds a cross-language project (a Python worker that adds two numbers and stores the sum in state, a TypeScript worker that exposes an HTTP endpoint and calls it).

```bash
curl -fsSL https://install.iii.dev/iii/main/install.sh | sh
iii project init quickstart --template quickstart   # scaffold the Quickstart
cd quickstart
iii                                                 # start the engine
```

Engine **listeners, adapters, and port bindings** are defined in your project’s **`config.yaml`** (or the path you pass to the engine). Read that file and the docs; do not assume fixed port numbers from a static list.

Use **`iii console`** to launch the web observability console against the running engine.

Discover CLI surface area with **`iii --help`** and **`iii <subcommand> --help`**. The **`iii trigger`** subcommand is handy for **manual** invocations while debugging; it is **not** the primary way applications call functions—use the SDK from your workers for real integration, and **do not** build automation around the CLI trigger.

Other useful subcommands include `iii worker add <name>` (install a worker from the registry) and `iii update` (update iii and managed binaries).

Install an SDK:

- Rust: `cargo add iii-sdk`
- Node (backend): `npm install iii-sdk`
- Node (browser, RBAC-scoped): `npm install iii-browser-sdk`
- Python: `pip install iii-sdk`

Full docs: https://iii.dev/docs

## Guardrails

Agents should follow:

- Function IDs use `::` (e.g. `orders::validate`)
- HTTP `api_path` values use a leading slash (e.g. `/orders/validate`)
- Cron triggers use config field `expression`, not `cron`
- Call functions via the SDK from workers — use `iii trigger` only for manual debugging, not app automation
- Engine listeners and ports come from `config.yaml`; use `iii console` for observability

## Agent skills (after onboarding)

Once iii is installed and you have completed the [Quickstart](https://iii.dev/docs/quickstart), install the agent skills so your coding agent gets full iii context (primitives, SDKs, engine config, architecture patterns, error handling). Two sources, same commands:

```bash
npx skills add iii-hq/iii/skills   # all iii reference skills
npx skills add iii-hq/workers      # one skill per published worker
```

Neither source has a root skill, so a bare add discovers and installs every skill under it. Narrow to one by name or by path:

```bash
npx skills add iii-hq/iii/skills --skill <name>   # e.g. --skill iii-core-primitives
npx skills add iii-hq/workers --skill <worker>    # a single worker's skill
npx skills add iii-hq/workers/<worker>/skills     # the same, by path
```

Catalogs: https://github.com/iii-hq/iii/tree/main/skills and https://github.com/iii-hq/workers

## Harness composition as a shape, not a product

The thin-vs-thick harness debate is a composition choice in iii. A thin harness is a worker with a few functions that lets the model decide what to trigger next. A thick harness is a worker with more functions, approval gates, and conditional logic before enqueuing the next step. Same primitives, different shape. Change the shape by adding or removing functions, not by rearchitecting.

## Process isolation

iii ships a sandbox worker that runs arbitrary ephemeral code on demand. Compose it with the RBAC worker to let agents run untrusted code without risk to the base system. The CLI uses the same sandbox functions when you run `iii worker add` with a sandbox target. An agent that needs to execute generated or installed code calls those same functions, gated by the same RBAC.

## Discovery and extensibility

The engine is the registry. It is always correct because it only reflects what is actually connected. No Consul, no service mesh, no OpenAPI specs drifting, no stale internal docs.

`iii worker add <name>` is the npm moment for connected systems. What gets installed is a running participant, not a library to integrate.

## Observability as protocol

OpenTelemetry traces, metrics, and structured logs come from the engine itself. A trace that starts at a browser click, flows through an agent, hits a Python ML worker, writes state, and renders back in the browser is one trace. Forward it to Datadog, Grafana, or Honeycomb. Stop writing instrumentation. Stop debugging across disconnected log streams.

## Memory and portability

Agent memory, traces, and function catalogs live wherever you run the engine. File-based for dev. Redis or Postgres for prod. Swap with a config change. No vendor has a copy.

## Licensing

The iii engine is Elastic License 2.0 (ELv2). The SDKs, CLI, console, docs, and website are Apache License 2.0.

## Links

- Homepage: https://iii.dev/
- Manifesto: https://iii.dev/manifesto
- Docs: https://iii.dev/docs
- Blog index (markdown): https://iii.dev/blog/index.md
- llms.txt (AI discovery): https://iii.dev/llms.txt
- This file: https://iii.dev/AGENTS.md
- GitHub: https://github.com/iii-hq/iii

Last updated: 2026-08-07
