state
The state worker is a server-side key/value store. Values are addressed by a scope (namespace) and a key, shared across every worker connected to the engine, and persisted through a pluggable adapter (kv or redis). Callers reach the store through six state::* functions invoked with iii.trigger({…
Works with
Agent Skills format with YAML frontmatter. Claude Code reads it as-is.
---
name: "state"
description: "The state worker is a server-side key/value store. Values are addressed by a scope (namespace) and a key, shared across every worker connected to the engine, and persisted through a pluggable adapter (kv or redis). Callers reach the store through six state::* functions invoked with iii.trigger({…"
license: "Apache-2.0"
---
# state
The `state` worker is a server-side key/value store. Values are addressed by a `scope` (namespace) and a `key`, shared across every worker connected to the engine, and persisted through a pluggable adapter (`kv` or `redis`). Callers reach the store through six `state::*` functions invoked with `iii.trigger({ function_id: 'state::...', payload })`. Install it with `iii worker add state`; it replaces the engine's built-in `iii-state` worker, which must be removed from the engine config first.
State does not push updates to SDK clients. Reactivity is delivered by a `state` trigger type that fires `state:created`, `state:updated`, or `state:deleted` after every successful mutation, so downstream functions can react to data changes without polling. The `kv` adapter (default) supports `in_memory` or `file_based` persistence; `redis` proxies to a Redis backend. The function surface is identical across adapters.
## When to Use
- Two or more functions need shared state without standing up a separate database.
- A counter or per-entity document needs atomic partial updates instead of read-modify-write.
- A write in one function should trigger side effects elsewhere (cache invalidation, audit logs, notifications, projections).
- You want a specific `scope`/`key` watched and reacted to only when that slot changes.
## Boundaries
- Schema-free by design — every value is opaque JSON. Use the `configuration` worker when entries need a registered JSON Schema and validation.
- Reads (`state::get`, `state::list`, `state::list_groups`) never fire triggers; only `set`/`update`/`delete` do.
- Trigger delivery is asynchronous and does not roll back the write on handler failure; a delete of a missing key still emits `state:deleted` with a null old value.
- Stream-shaped, broadcast-to-subscribers data belongs in the engine's stream surface, not here.
- The store lives in the worker process: the `kv` `in_memory` backend is lost when the worker stops. Use `file_based` or `redis` for data that must survive a restart.
## Functions
- `state::set` — write or replace the value at a `scope`/`key`; fires `state:created` or `state:updated`.
- `state::get` — read one value by `scope` and `key`.
- `state::delete` — remove a key and fire `state:deleted` with the prior value.
- `state::update` — apply ordered atomic ops (`set`, `merge`, `increment`, `decrement`, `append`, `remove`) to the stored value.
- `state::list` — enumerate every value stored in a scope.
- `state::list_groups` — enumerate which scopes currently contain data.
## Reactive triggers
Bind a `state` trigger when a function should run automatically after a value changes — without polling `state::get`. The worker evaluates every registered `state` trigger after a successful `state::set`, `state::update`, or `state::delete` and invokes matching handlers asynchronously.
Reach for it when:
- A write in one worker should drive side effects in another (audit logs, cache invalidation, notifications, projections).
- You want optional gating via `condition_function_id` so the handler only runs when a predicate on the event is truthy (only an explicit `false` blocks).
If you only need the new value inside the same function that wrote it, use the mutator's returned `old_value` / `new_value` instead of binding a trigger.
### How to bind
1. Register a handler: `iii.registerFunction('orders::on-status-change', handler)`.
2. Register the trigger:
```typescript
iii.registerTrigger({
type: 'state',
function_id: 'orders::on-status-change',
config: {
scope: 'orders', // optional. Omit to match every scope.
key: 'status', // optional. Omit to match every key in the scope.
// condition_function_id is also supported.
},
})
```
All `config` fields are optional; tighter filters reduce how often the handler runs. To watch several specific keys, register one trigger per `scope`/`key` pair. Mutations that fire the trigger: `state::set`, `state::update`, `state::delete`.
The handler receives the event payload `{ type: "state", event_type, scope, key, old_value, new_value }`, where `event_type` is one of `state:created`, `state:updated`, or `state:deleted`.More General & Other skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.

