Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions acp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ binary, set the `IIIACP_*` env vars below.
`iii-acp` needs an iii engine plus a brain. Minimum stack:

```bash
# 1. Engine builtins iii-acp uses directly. iii-state holds session
# 1. Workers acp uses directly. state holds session
# records + history; iii-stream carries the agent::events tape;
# iii-queue backs durable cancel topics.
iii worker add iii-state iii-stream iii-queue
# queue backs durable cancel topics.
iii worker add state iii-stream queue

# 2. acp itself.
iii worker add acp
Expand Down
10 changes: 5 additions & 5 deletions approval-gate/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion approval-gate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name = "approval_gate"
path = "src/lib.rs"

[dependencies]
iii-sdk = "=0.21.6"
iii-sdk = "=0.21.8"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
2 changes: 1 addition & 1 deletion approval-gate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ cargo clippy --all-targets --all-features -- -D warnings
```

The integration suite spawns a real engine (`III_ENGINE_BIN` or `iii` on
PATH) with `configuration` + `iii-state`, registers the production surface
PATH) with `configuration` + `state`, registers the production surface
in-process, and fakes sibling RPCs where noted (`session::get`). With the
harness binary available, `tests/harness_integration.rs` additionally boots the
real harness worker for cross-worker hold / sweep / resolve checks.
Expand Down
2 changes: 1 addition & 1 deletion approval-gate/architecture/internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,6 @@ Verified against the engine source (`~/workspaces/personal/motia/iii`):
prior-art permission-matrix cases plus the fail-closed rows.
- **Integration** (`cargo test --test integration`): spawns a real engine
(`III_ENGINE_BIN` or `iii` on PATH; self-skips otherwise) with
`configuration` + `iii-state` real and the unbuilt siblings faked
`configuration` + `state` real and the unbuilt siblings faked
in-process. Verifies the no-tombstone invariant, exactly-once event
delivery through real engine fan-out, and reactive configuration reload.
12 changes: 6 additions & 6 deletions bridge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,25 @@ entry does not un-register its handler — the SDK has no unregister — so the
function id stays live but its handler returns `bridge_error` until the worker
is restarted.

## Requires removing the built-in `iii-bridge` worker
## Requires removing the legacy built-in bridge worker

The built-in `iii-bridge` worker registers the same function ids
The legacy built-in bridge worker registers the same function ids
(`bridge.invoke`, `bridge.invoke_async`, plus any configured forward/expose
names). Two workers registering the same function id on one engine collide —
whichever registers last wins — so this worker requires `iii-bridge` to be
whichever registers last wins — so this worker requires the legacy built-in to be
absent: omit it from the engine's `config.yaml` (a config that doesn't list a
worker won't run it). This is a duplicate-function-id collision, not a trigger
type conflict — `bridge` registers no trigger types.

On boot, this worker queries the engine for connected workers and refuses to
start with a clear error if `iii-bridge` is still active, so a stale config
start with a clear error if the legacy built-in is still active, so a stale config
fails loudly instead of silently racing the built-in worker for ownership of
`bridge.invoke`/`bridge.invoke_async`.

The engine's own state/queue/stream/configuration **bridge adapters** are
unaffected by this worker or by removing `iii-bridge`: those adapters open
unaffected by this worker or by removing the legacy built-in: those adapters open
their own direct SDK connections to bridge engine-internal subsystems and never
depended on the `iii-bridge` worker.
depended on the legacy built-in worker.

## Parity vs builtin

Expand Down
4 changes: 2 additions & 2 deletions bridge/skills/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ bridge-specific call shape. Two functions (`bridge.invoke`,
rare case where the remote function id is dynamic at runtime.

Install it with `iii worker add bridge`. This is a standalone replacement for
the engine builtin `iii-bridge`: the builtin must not be running on the same
the engine’s legacy built-in bridge service: it must not run on the same
engine, since both register the same `bridge.invoke` / `bridge.invoke_async`
ids (plus any forward/expose ids) — the worker refuses to boot while
`iii-bridge` is still connected.
the legacy built-in remains connected.

## When to Use

Expand Down
10 changes: 5 additions & 5 deletions cron/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Schedules registered functions with cron expressions. Any function bound to a
`cron` trigger is invoked by this worker at the next matching UTC time. The
worker replaces the built-in `iii-cron` worker while keeping the trigger type
worker replaces the legacy built-in cron worker while keeping the trigger type
and payload shape stable.

## Install
Expand Down Expand Up @@ -85,15 +85,15 @@ with:
All schedules use UTC. Missed fires while the worker is stopped are skipped;
there is no catch-up replay.

### Requires removing the built-in `iii-cron` worker
### Requires removing the legacy built-in cron worker

The built-in `iii-cron` worker also owns the `cron` trigger type. Two owners
The legacy built-in cron worker also owns the `cron` trigger type. Two owners
of the same trigger type on one engine collide - whichever registers last
wins - so this worker requires `iii-cron` to be absent: omit it from the
wins - so this worker requires it to be absent: omit it from the
engine's `config.yaml` (a config that doesn't list a worker won't run it).

On boot, this worker queries the engine for connected workers and refuses to
start with a clear error if `iii-cron` is still active, so a stale config
start with a clear error if the legacy built-in is still active, so a stale config
fails loudly instead of silently racing the built-in worker for ownership of
`cron`.

Expand Down
6 changes: 3 additions & 3 deletions cron/skills/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ expressions. It exposes no callable `cron::*` functions; its entire surface is
the `cron` trigger type, bound through a worker SDK trigger registration such
as `iii.registerTrigger({ type: 'cron', function_id, config })`.

Install it with `iii worker add cron`. The engine builtin `iii-cron` must not
run on the same engine because it also owns the `cron` trigger type. Remove
`iii-cron` from the engine config before starting this worker; the standalone
Install it with `iii worker add cron`. The legacy in-engine cron service must not
run on the same engine because it also owns the `cron` trigger type. Remove the
legacy built-in from the engine config before starting this worker; the standalone
worker refuses to boot when the builtin is active.

On every firing, the worker optionally evaluates a condition function, acquires
Expand Down
4 changes: 2 additions & 2 deletions docs/adr/0001-state-worker-store-location.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
Accepted (2026-07-06).

## Context
The engine builtin `iii-state` is not just a trigger handler: it owns a key-value
The legacy in-engine state service is not just a trigger handler: it owns a key-value
store that lives in the engine process (`engine/src/builtins/kv.rs`,
`BuiltinKvStore`, in_memory or file_based with a background flush loop).
Migrating `iii-state` to a standalone worker forces a decision about where that
Migrating that state service to the standalone `state` worker forces a decision about where that
store lives. Coupling analysis on the engine found ZERO inbound engine-internal
consumers of `state::*` (everything reaches state over the function bus), so the
functions can move; the question is only the store.
Expand Down
2 changes: 1 addition & 1 deletion docs/sops/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ by default in the engine.
### Boundaries

- Not a general-purpose key/value store — every entry needs a registered JSON
Schema. Use `iii-state` for free-form values.
Schema. Use `state` for free-form values.
- No partial updates: `set` always replaces the whole value. Build the new
value client-side and ship it in one call.
- Schemas are not version-checked across re-registrations — re-registering with
Expand Down
8 changes: 4 additions & 4 deletions hermes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ A real turn over the bus (`pong`) and a live discovery turn where Hermes enumera
The unique value over the other agent workers: Hermes is iii's gateway to 27+ chat platforms.

```text
27 platforms ─▶ Hermes gateway ─▶ hermes::inbound (iii-http) ─▶ republished
27 platforms ─▶ Hermes gateway ─▶ hermes::inbound (http) ─▶ republished
│ iii worker reacts,
│ drives the bus
▼
hermes::send --to <platform> ─▶ out
```

Point a Hermes webhook route / delivery target at the worker's `inbound_api_path` (default `/hermes/inbound`, served via iii-http). An inbound message flows in, an iii worker handles it against the full function registry, and the reply goes back out through `hermes::send`.
Point a Hermes webhook route / delivery target at the worker's `inbound_api_path` (default `/hermes/inbound`, served via http). An inbound message flows in, an iii worker handles it against the full function registry, and the reply goes back out through `hermes::send`.

## Configuration

Expand All @@ -88,7 +88,7 @@ events_stream: agent::events # translated AgentEvent frames
raw_events_stream: hermes::events # raw Hermes run output
iii_context: true # prepend the iii runtime context on a fresh session
hermes_executable: "" # path to the hermes CLI; empty = resolve on PATH
inbound_api_path: /hermes/inbound # iii-http path the gateway delivers inbound events to
inbound_api_path: /hermes/inbound # http path the gateway delivers inbound events to
```

## Scope
Expand All @@ -100,7 +100,7 @@ Exposes the agent loop, omnichannel send, and inbound events — not Hermes's du
Live-verified against a running engine with the Hermes CLI and an Anthropic key: the agent loop (`hermes::run` / `start` / `status` / `sessions::list`), real turns (`pong`), live iii discovery (the agent runs `iii trigger engine::workers::list` itself), and session continuity (`--resume`) all work end to end. Two parts remain to finalize against a live messaging gateway:

- **Events granularity** — Hermes one-shot (`hermes -z`) prints only the final response text, so `agent::events` carries `turn_end` + `agent_end` (the final message), not per-tool frames. A richer event stream depends on a Hermes mode that emits one.
- **Inbound trigger contract** — `hermes::inbound` republishes raw deliveries today and binds via `iii-http`; the exact gateway payload is mapped onto a dedicated `hermes::message` trigger type once verified against a running gateway.
- **Inbound trigger contract** — `hermes::inbound` republishes raw deliveries today and binds via `http`; the exact gateway payload is mapped onto a dedicated `hermes::message` trigger type once verified against a running gateway.

## Tool profile

Expand Down
8 changes: 4 additions & 4 deletions http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ Functions can stream their response: write to `req.response` (a
Returning a non-null value instead yields a regular buffered response built
from `{ status_code, headers, body }`.

### Requires removing the built-in `iii-http` worker
### Requires removing the legacy built-in HTTP service

The built-in `iii-http` worker also owns the `http` trigger type. Two owners
The legacy built-in HTTP service also owns the `http` trigger type. Two owners
of the same trigger type on one engine collide — whichever registers last
wins — so this worker requires `iii-http` to be absent: omit it from the
wins — so this worker requires it to be absent: omit it from the
engine's `config.yaml` (a config that doesn't list a worker won't run it).

On boot, this worker queries the engine for connected workers and refuses to
start with a clear error if `iii-http` is still active, so a stale config
start with a clear error if the legacy built-in is still active, so a stale config
fails loudly instead of silently racing the built-in worker for ownership of
`http`.
8 changes: 4 additions & 4 deletions http/skills/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ without using the iii SDK. It exposes no callable `http::*` functions; its
entire surface is the `http` trigger type, bound through a worker SDK trigger
registration such as `iii.registerTrigger({ type: 'http', function_id, config })`.

Install it with `iii worker add http`. The engine builtin `iii-http` must not
run on the same engine because it also owns the `http` trigger type. Remove
`iii-http` from the engine config before starting this worker; the standalone
Install it with `iii worker add http`. The legacy in-engine HTTP service must not
run on the same engine because it also owns the `http` trigger type. Remove the
legacy built-in from the engine config before starting this worker; the standalone
worker refuses to boot when the builtin is active.

Incoming requests are matched by HTTP method and path. The invoked handler
Expand Down Expand Up @@ -46,7 +46,7 @@ chunked streaming response.
- This is not a scheduler or event queue. For clock-based execution, use
`cron`; for data-change reactions, use the relevant state, stream, queue, or
database worker.
- The built-in `iii-http` worker cannot run beside this standalone worker on
- The legacy in-engine HTTP service cannot run beside this standalone worker on
the same engine because both own the `http` trigger type.
- Route shapes with the same method and equivalent path structure conflict:
`/orders/:id` and `/orders/:order_id` are the same shape.
Expand Down
2 changes: 1 addition & 1 deletion iii-directory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ native ids directly — every one takes the same filters
| `engine::triggers::info` | Single trigger-type detail: configuration schema, return schema. |
| `engine::registered-triggers::list` | List trigger INSTANCES (subscriber rows). |
| `engine::registered-triggers::info` | Single registered-trigger detail. |
| `engine::workers::list` | List workers with an open engine WS connection. Daemon-managed providers (`iii-http`, `iii-cron`, `iii-state`) won't appear — call `worker::list` from the supervisor to see those. |
| `engine::workers::list` | List workers with an open engine WS connection. Daemon-managed providers (`http`, `cron`, `state`) won't appear — call `worker::list` from the supervisor to see those. |
| `engine::workers::info` | One worker's detail by `name`. |

### `directory::registry::*` (workers registry HTTP proxy)
Expand Down
2 changes: 1 addition & 1 deletion iii-directory/skills/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ workers can appear without a manual download.

- Only installed workers are visible. If the engine daemon is unreachable at boot, filtering is skipped and everything on disk is shown instead.
- Downloading is the only write; every read function leaves disk untouched.
- Not the live-connection view. `directory::*` reflects what is on disk or in the registry, not what is connected right now. For that, call the engine directly (`engine::functions::list`, `engine::workers::list`, …); daemon-managed providers (`iii-http`, `iii-cron`, `iii-state`) open no WebSocket, so merge `worker::list` by `name`.
- Not the live-connection view. `directory::*` reflects what is on disk or in the registry, not what is connected right now. For that, call the engine directly (`engine::functions::list`, `engine::workers::list`, …); daemon-managed providers (`http`, `cron`, `state`) open no WebSocket, so merge `worker::list` by `name`.
- Do not put a skill id (`/`) in `agent_trigger`'s `function:` field, and do not pass a function id (`::`) to `directory::skills::get`.
- Prompt files without a `description:` in frontmatter are silently skipped by `directory::prompts::list`.
- Registry answers (`registry::workers::list` / `info`) are cached ~60 s per unique input by default (`registry_cache_ttl_ms`) — change a parameter to refresh.
Expand Down
2 changes: 1 addition & 1 deletion llm-router/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ within seconds — no restart.
another worker's environment shows up as `configured: false`.
- **Registration-token recovery.** Re-registering a provider id without its
original token is rejected (anti-takeover). If a provider durably lost its
token, delete the router's registry state (iii-state scope `llm-router`,
token, delete the router's registry state (state scope `llm-router`,
key `registry`) and restart the affected providers to re-bind; pasted
credentials in the configuration entry are unaffected.

Expand Down
2 changes: 1 addition & 1 deletion openwiki/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Builds and maintains a source-grounded, interlinked markdown wiki for a code
repository, and serves a browser UI to read and search it. Point it at a git
repo: an agent reads the source, plans a hierarchical index, writes one cited
page per topic, and keeps the wiki current from git diffs on a per-wiki
schedule. Pages persist in iii-state; the engine serves the UI and JSON API
schedule. Pages persist in state; the engine serves the UI and JSON API
under `/openwiki`.

## Install
Expand Down
4 changes: 2 additions & 2 deletions openwiki/skills/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: Generate and browse a source-grounded markdown wiki for a git repos
Builds and maintains a categorized, interlinked markdown wiki for a code
repository. A model reads the source, plans an outline, writes one page per
topic with file citations, and refreshes pages from git diffs. Wiki content is
stored in iii-state; a browser UI and JSON API are served under `/openwiki`.
stored in state; a browser UI and JSON API are served under `/openwiki`.

## When to Use

Expand All @@ -25,7 +25,7 @@ stored in iii-state; a browser UI and JSON API are served under `/openwiki`.
- Not a chatbot. It maintains structured pages rather than answering free-form
questions.
- Cloned repositories are ephemeral working copies on local disk; the wiki
itself lives in iii-state.
itself lives in state.

## Functions

Expand Down
2 changes: 1 addition & 1 deletion provider-anthropic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Anthropic ships new models; discovery only supplies bare ids.
(config slice → `ANTHROPIC_API_KEY` on the router → none). Both `api_key`
(x-api-key) and `oauth` (Bearer) shapes work; v1 performs no OAuth refresh.
- **Identity binding:** the router issues a `registration_token` on first
registration, persisted in iii-state (scope `provider-anthropic`). If that
registration, persisted in state (scope `provider-anthropic`). If that
state is lost the router rejects re-registration — clear the binding on
the router side to re-pair.

Expand Down
2 changes: 1 addition & 1 deletion provider-claude-code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ provider id `anthropic`.
- **Registration:** self-declares via `router::provider::register` with backoff,
and re-declares on the `router::ready` trigger. It advertises dynamic model
listing and `credential_env_var: None` (OAuth-only); identity binds via the
`registration_token` persisted in iii-state (scope `provider-claude-code`).
`registration_token` persisted in state (scope `provider-claude-code`).
- **Models:** attempts the authenticated `GET /v1/models` at startup, on
explicit refresh, after router readiness, and every ~15 minutes. Picker-visible
results become **namespaced** router ids (`claude-code/<upstream-id>`). If the
Expand Down
2 changes: 1 addition & 1 deletion provider-kimi/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading