iii / worker
$worker

iii-state

v0.14.0-next.1

Distributed key-value state management with reactive change triggers.

engine module
baked into the iii engine; no separate install required.
agent-ready brief for v0.14.0-next.1
install + config + dependencies + readme + api reference, all in one place. fetch as agent-context.md for an llm to consume.
the same content rendered as discrete blocks below is exposed as a single markdown document at /workers/iii-state.md?version=0.14.0-next.1. paste it into an llm prompt or pipe it through curl from a worker.

install

install
$iii worker add iii-state@0.14.0-next.1

configuration

iii-config.yaml
- adapter:
    config:
      file_path: ./data/state_store.db
      store_method: file_based
    name: kv

dependencies

no dependencies for v0.14.0-next.1

readme

README.md

iii-state

Distributed key-value state storage with scope-based organization and reactive triggers that fire on any state change.

State is server-side key-value storage with trigger-based reactivity. Unlike streams, state does not push updates to WebSocket clients — it fires triggers that workers handle server-side.

Sample Configuration

- name: iii-state
  config:
    adapter:
      name: kv
      config:
        store_method: file_based
        file_path: ./data/state_store
        save_interval_ms: 5000

Configuration

Field Type Description
adapter Adapter Adapter for state persistence. Defaults to kv.

Adapters

kv

Built-in key-value store with in-memory or file-based persistence.

name: kv
config:
  store_method: file_based
  file_path: ./data/state_store
  save_interval_ms: 5000
Field Type Description
store_method string in_memory (lost on restart) or file_based (persisted to disk).
file_path string Directory path for file-based storage.
save_interval_ms number Interval in milliseconds between automatic disk saves. Defaults to 5000.

redis

Uses Redis as the state backend.

name: redis
config:
  redis_url: ${REDIS_URL:redis://localhost:6379}

bridge

Forwards state operations to a remote III Engine instance via the Bridge Client.

name: bridge

Functions

state::set

Set a value in state. Fires state:created if the key did not exist, or state:updated if it did.

Parameters: scope (string), key (string), value (any)

Returns: old_value (any), new_value (any)

state::get

Get a value from state.

Parameters: scope (string), key (string)

Returns: value (any), or null if the key does not exist.

state::delete

Delete a value from state. Fires a state:deleted trigger.

Parameters: scope (string), key (string)

Returns: value (the deleted value, or null)

state::update

Atomically update a value using one or more operations. Fires state:created or state:updated.

Parameters: scope (string), key (string), ops (UpdateOp[])

Operation Shape Description
set { "type": "set", "path": "status", "value": "active" } Set a field or replace the root value.
merge { "type": "merge", "path": "", "value": { "status": "active" } } Shallow-merge an object at the root.
increment { "type": "increment", "path": "count", "by": 1 } Add by to a numeric field.
decrement { "type": "decrement", "path": "count", "by": 1 } Subtract by from a numeric field.
append { "type": "append", "path": "events", "value": { "kind": "chunk" } } Push one element to an array or concatenate a string.
remove { "type": "remove", "path": "status" } Remove a field from the current object.

Returns: old_value (any), new_value (any)

state::list

List all values within a scope.

Parameters: scope (string)

Returns: a flat JSON array of all stored values within the scope.

state::list_groups

List all scopes that contain state data.

Returns: groups (string[]) — sorted, deduplicated array of all scope names.

Trigger Type: state

Fires when a state value is created, updated, or deleted.

Config Field Type Description
scope string Only fire for changes within this scope. When omitted, fires for all scopes.
key string Only fire for changes to this specific key. When omitted, fires for all keys.
condition_function_id string Function ID for conditional execution. If it returns false, the handler is skipped.

State Event Payload

Field Type Description
type string Always "state".
event_type string "state:created", "state:updated", or "state:deleted".
scope string The scope where the change occurred.
key string The key that changed.
old_value any The previous value, or null for newly created keys.
new_value any The new value. null for deleted keys.

Sample Code

const fn = iii.registerFunction(
  { id: 'state::onUserUpdated' },
  async (event) => {
    console.log('State changed:', event.event_type, event.key)
    console.log('Previous:', event.old_value)
    console.log('Current:', event.new_value)
    return {}
  },
)

iii.registerTrigger({
  type: 'state',
  function_id: fn.id,
  config: { scope: 'users', key: 'profile' },
})

api reference (json)

agent-api-reference.json
{
  "functions": [
    {
      "description": "Delete a value from state",
      "metadata": {},
      "name": "state::delete",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "key": {
            "description": "Identifier for the value to delete within the scope.",
            "type": "string"
          },
          "scope": {
            "description": "Namespace that groups related keys.",
            "type": "string"
          }
        },
        "required": [
          "key",
          "scope"
        ],
        "title": "StateDeleteInput",
        "type": "object"
      },
      "response_schema": {}
    },
    {
      "description": "Get a value from state",
      "metadata": {},
      "name": "state::get",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "key": {
            "description": "Identifier for the value within the scope.",
            "type": "string"
          },
          "scope": {
            "description": "Namespace that groups related keys.",
            "type": "string"
          }
        },
        "required": [
          "key",
          "scope"
        ],
        "title": "StateGetInput",
        "type": "object"
      },
      "response_schema": {}
    },
    {
      "description": "Get a group from state",
      "metadata": {},
      "name": "state::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "scope": {
            "description": "Namespace whose keys should be listed as a group.",
            "type": "string"
          }
        },
        "required": [
          "scope"
        ],
        "title": "StateGetGroupInput",
        "type": "object"
      },
      "response_schema": {}
    },
    {
      "description": "List all state groups",
      "metadata": {},
      "name": "state::list_groups",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "StateListGroupsInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "groups": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "groups"
        ],
        "title": "StateListGroupsResult",
        "type": "object"
      }
    },
    {
      "description": "Set a value in state",
      "metadata": {},
      "name": "state::set",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "key": {
            "description": "Identifier for the value within the scope.",
            "type": "string"
          },
          "scope": {
            "description": "Namespace that groups related keys (e.g. `users`, `orders`).",
            "type": "string"
          },
          "value": {
            "description": "Arbitrary JSON value to store. Replaces any existing value at `scope`/`key`."
          }
        },
        "required": [
          "key",
          "scope",
          "value"
        ],
        "title": "StateSetInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "new_value": {
            "description": "The value after the update"
          },
          "old_value": {
            "description": "The value before the update (None if key didn't exist)"
          }
        },
        "required": [
          "new_value"
        ],
        "title": "SetResult",
        "type": "object"
      }
    },
    {
      "description": "Update a value in state",
      "metadata": {},
      "name": "state::update",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "FieldPath": {
            "description": "Represents a path to a field in a JSON object",
            "type": "string"
          },
          "MergePath": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              }
            ],
            "description": "Path target for a [`UpdateOp::Merge`] operation. Accepts either a single string (legacy / first-level field) or an array of literal segments (nested path).\n\nPath normalization rules applied by the engine: - absent / `Single(\"\")` / `Segments(vec![])` → root merge - `Single(\"foo\")` is equivalent to `Segments(vec![\"foo\".into()])` - `Segments([\"a\", \"b\", \"c\"])` walks three literal keys, never interpreting dots specially. `Segments(vec![\"a.b\".into()])` is a single literal key named `\"a.b\"`.\n\n**Variant ordering is load-bearing.** `#[serde(untagged)]` tries variants in declaration order — `Single` MUST come before `Segments` so a JSON string deserializes into `Single` rather than failing the array match first."
          },
          "UpdateOp": {
            "description": "Operations that can be performed atomically on a stream value",
            "oneOf": [
              {
                "description": "Set a value at path (overwrite)",
                "properties": {
                  "path": {
                    "$ref": "#/definitions/FieldPath"
                  },
                  "type": {
                    "enum": [
                      "set"
                    ],
                    "type": "string"
                  },
                  "value": true
                },
                "required": [
                  "path",
                  "type"
                ],
                "type": "object"
              },
              {
                "description": "Merge object into existing value (object-only). Path may be omitted (root merge), a single first-level key, or an array of literal segments for nested merge. See [`MergePath`].",
                "properties": {
                  "path": {
                    "anyOf": [
                      {
                        "$ref": "#/definitions/MergePath"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "type": {
                    "enum": [
                      "merge"
                    ],
                    "type": "string"
                  },
                  "value": true
                },
                "required": [
                  "type",
                  "value"
                ],
                "type": "object"
              },
              {
                "description": "Increment numeric value",
                "properties": {
                  "by": {
                    "format": "int64",
                    "type": "integer"
                  },
                  "path": {
                    "$ref": "#/definitions/FieldPath"
                  },
                  "type": {
                    "enum": [
                      "increment"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "by",
                  "path",
                  "type"
                ],
                "type": "object"
              },
              {
                "description": "Decrement numeric value",
                "properties": {
                  "by": {
                    "format": "int64",
                    "type": "integer"
                  },
                  "path": {
                    "$ref": "#/definitions/FieldPath"
                  },
                  "type": {
                    "enum": [
                      "decrement"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "by",
                  "path",
                  "type"
                ],
                "type": "object"
              },
              {
                "description": "Append an element to an array or concatenate a string at the optional path. Path may be omitted (root append), a single first-level key, or an array of literal segments for nested append. See [`MergePath`] for the variant shape.",
                "properties": {
                  "path": {
                    "anyOf": [
                      {
                        "$ref": "#/definitions/MergePath"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "type": {
                    "enum": [
                      "append"
                    ],
                    "type": "string"
                  },
                  "value": true
                },
                "required": [
                  "type",
                  "value"
                ],
                "type": "object"
              },
              {
                "description": "Remove a field",
                "properties": {
                  "path": {
                    "$ref": "#/definitions/FieldPath"
                  },
                  "type": {
                    "enum": [
                      "remove"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "path",
                  "type"
                ],
                "type": "object"
              }
            ]
          }
        },
        "properties": {
          "key": {
            "description": "Identifier for the value to update within the scope.",
            "type": "string"
          },
          "ops": {
            "description": "Ordered list of update operations applied atomically to the existing value.",
            "items": {
              "$ref": "#/definitions/UpdateOp"
            },
            "type": "array"
          },
          "scope": {
            "description": "Namespace that groups related keys.",
            "type": "string"
          }
        },
        "required": [
          "key",
          "ops",
          "scope"
        ],
        "title": "StateUpdateInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "UpdateOpError": {
            "description": "Per-op error reported by an atomic update operation.",
            "properties": {
              "code": {
                "description": "Stable error code, e.g. `\"merge.path.too_deep\"`.",
                "type": "string"
              },
              "doc_url": {
                "description": "Optional documentation URL for this error class.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "message": {
                "description": "Human-readable description with concrete numbers when applicable.",
                "type": "string"
              },
              "op_index": {
                "description": "Index of the offending op within the original `ops` array.",
                "format": "uint",
                "minimum": 0,
                "type": "integer"
              }
            },
            "required": [
              "code",
              "message",
              "op_index"
            ],
            "type": "object"
          }
        },
        "description": "Result of an atomic update operation",
        "properties": {
          "errors": {
            "description": "Errors encountered while applying ops. Successfully applied ops are still reflected in `new_value`. Field is omitted from JSON when empty for backward compatibility.",
            "items": {
              "$ref": "#/definitions/UpdateOpError"
            },
            "type": "array"
          },
          "new_value": {
            "description": "The value after the update"
          },
          "old_value": {
            "description": "The value before the update (None if key didn't exist)"
          }
        },
        "required": [
          "new_value"
        ],
        "title": "UpdateResult",
        "type": "object"
      }
    }
  ],
  "triggers": [
    {
      "description": "State trigger",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "condition_function_id": {
            "description": "Optional function ID to evaluate before invoking handler",
            "type": [
              "string",
              "null"
            ]
          },
          "key": {
            "description": "State key to watch (exact match filter)",
            "type": [
              "string",
              "null"
            ]
          },
          "scope": {
            "description": "State scope to watch (exact match filter)",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "StateTriggerConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "state",
      "return_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "StateEventType": {
            "enum": [
              "state:created",
              "state:updated",
              "state:deleted"
            ],
            "type": "string"
          }
        },
        "properties": {
          "event_type": {
            "allOf": [
              {
                "$ref": "#/definitions/StateEventType"
              }
            ],
            "description": "Type of state change"
          },
          "key": {
            "description": "State key",
            "type": "string"
          },
          "new_value": {
            "description": "New value"
          },
          "old_value": {
            "description": "Previous value (null for created events)"
          },
          "scope": {
            "description": "State scope",
            "type": "string"
          },
          "type": {
            "description": "Always \"state\"",
            "type": "string"
          }
        },
        "required": [
          "event_type",
          "key",
          "new_value",
          "scope",
          "type"
        ],
        "title": "StateCallRequest",
        "type": "object"
      }
    }
  ]
}