Skip to content

JSON Schemas

reflexr publishes two JSON Schemas, generated from its Pydantic models, which are the source of truth, and checked in under schemas/:

Schema What it describes Use it to
reflexr.rules.v1.json A rule: its condition, scope, action and policies Validate rules written as JSON, by people or by agents
reflexr.v1.json Every frame of the stream protocol: client is any frame a client sends, and server any frame a server sends; $defs holds every frame, command, outcome and envelope they refer to Generate a client's types

A test fails if either checked-in file drifts from the models. Regenerate both with make schema, which runs:

uv run python -m reflexr.core.schema rules > schemas/reflexr.rules.v1.json
uv run python -m reflexr.core.schema protocol > schemas/reflexr.v1.json

Validating rules

A rule serializes to plain JSON, with durations as ISO 8601 strings. Rule.model_validate reads it back, and any JSON Schema validator can check it against reflexr.rules.v1.json first, which is how an application can accept rules from an agent or a form:

from reflexr import Rule
from reflexr.core import DEFAULT_REGISTRY

rule = Rule.model_validate_json(text)  # raises pydantic.ValidationError if it does not fit
rule.check(events=DEFAULT_REGISTRY)  # raises InvalidRule for unknown types or fields

Names are qualified: an event type or a rule name without its namespace fails validation, and an event type's error names the qualified one it may mean.

Generating client types

Frontends generate their types from the protocol schema rather than writing them by hand. For TypeScript, for example, with json-schema-to-typescript:

npx json-schema-to-typescript schemas/reflexr.v1.json > src/reflexr.d.ts

Within reflexr.v1, changes are additive only: new optional fields and new event types. Clients should ignore fields they do not know, and keep an event of an unknown type as an opaque envelope, since it still carries a seq. Application events appear in the schema as objects with a type and any other fields, because the application defines them.

The schemas

schemas/reflexr.rules.v1.json
{
  "$defs": {
    "AbsencePattern": {
      "additionalProperties": false,
      "description": "Fire once when nothing has passed the filter for ``within`` since the last envelope did.\n\nOnly scopes that have been seen can go quiet. Time passes with every envelope in the log,\nwhether or not it passes the filter.",
      "properties": {
        "kind": {
          "const": "absence",
          "default": "absence",
          "title": "Kind",
          "type": "string"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "within"
      ],
      "title": "AbsencePattern",
      "type": "object"
    },
    "ActionRef": {
      "additionalProperties": false,
      "description": "The action a rule runs, by name, and the params the rule passes it.",
      "properties": {
        "action": {
          "minLength": 1,
          "title": "Action",
          "type": "string"
        },
        "params": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Params",
          "type": "object"
        }
      },
      "required": [
        "action"
      ],
      "title": "ActionRef",
      "type": "object"
    },
    "AllFilter": {
      "additionalProperties": false,
      "description": "Envelopes that match every filter in ``of``.",
      "properties": {
        "kind": {
          "const": "all",
          "default": "all",
          "title": "Kind",
          "type": "string"
        },
        "of": {
          "items": {
            "$ref": "#/$defs/Filter"
          },
          "minItems": 1,
          "title": "Of",
          "type": "array"
        }
      },
      "required": [
        "of"
      ],
      "title": "AllFilter",
      "type": "object"
    },
    "AnyFilter": {
      "additionalProperties": false,
      "description": "Envelopes that match at least one filter in ``of``.",
      "properties": {
        "kind": {
          "const": "any",
          "default": "any",
          "title": "Kind",
          "type": "string"
        },
        "of": {
          "items": {
            "$ref": "#/$defs/Filter"
          },
          "minItems": 1,
          "title": "Of",
          "type": "array"
        }
      },
      "required": [
        "of"
      ],
      "title": "AnyFilter",
      "type": "object"
    },
    "Condition": {
      "additionalProperties": false,
      "description": "A rule's ``when``: a filter, and optionally dedupe, a pattern and a throttle.",
      "properties": {
        "dedupe": {
          "anyOf": [
            {
              "$ref": "#/$defs/Dedupe"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "filter": {
          "$ref": "#/$defs/Filter"
        },
        "pattern": {
          "$ref": "#/$defs/Pattern",
          "default": {
            "kind": "each"
          }
        },
        "throttle": {
          "anyOf": [
            {
              "$ref": "#/$defs/Throttle"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "filter"
      ],
      "title": "Condition",
      "type": "object"
    },
    "CountPattern": {
      "additionalProperties": false,
      "description": "Fire when ``at_least`` envelopes pass within ``within``. A firing consumes them.",
      "properties": {
        "at_least": {
          "minimum": 1,
          "title": "At Least",
          "type": "integer"
        },
        "kind": {
          "const": "count",
          "default": "count",
          "title": "Kind",
          "type": "string"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "at_least",
        "within"
      ],
      "title": "CountPattern",
      "type": "object"
    },
    "Dedupe": {
      "additionalProperties": false,
      "description": "Drop an envelope whose ``key`` fields were already seen within ``within``.",
      "properties": {
        "key": {
          "items": {
            "type": "string"
          },
          "minItems": 1,
          "title": "Key",
          "type": "array"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "key",
        "within"
      ],
      "title": "Dedupe",
      "type": "object"
    },
    "EachPattern": {
      "additionalProperties": false,
      "description": "Fire for every envelope that passes the filter.",
      "properties": {
        "kind": {
          "const": "each",
          "default": "each",
          "title": "Kind",
          "type": "string"
        }
      },
      "title": "EachPattern",
      "type": "object"
    },
    "Filter": {
      "discriminator": {
        "mapping": {
          "all": "#/$defs/AllFilter",
          "any": "#/$defs/AnyFilter",
          "not": "#/$defs/NotFilter",
          "on": "#/$defs/OnFilter",
          "predicate": "#/$defs/PredicateFilter",
          "where": "#/$defs/WhereFilter"
        },
        "propertyName": "kind"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/OnFilter"
        },
        {
          "$ref": "#/$defs/WhereFilter"
        },
        {
          "$ref": "#/$defs/AllFilter"
        },
        {
          "$ref": "#/$defs/AnyFilter"
        },
        {
          "$ref": "#/$defs/NotFilter"
        },
        {
          "$ref": "#/$defs/PredicateFilter"
        }
      ]
    },
    "JsonValue": {},
    "NotFilter": {
      "additionalProperties": false,
      "description": "Envelopes that do not match ``filter``.",
      "properties": {
        "filter": {
          "$ref": "#/$defs/Filter"
        },
        "kind": {
          "const": "not",
          "default": "not",
          "title": "Kind",
          "type": "string"
        }
      },
      "required": [
        "filter"
      ],
      "title": "NotFilter",
      "type": "object"
    },
    "OnFilter": {
      "additionalProperties": false,
      "description": "Envelopes whose event is one of ``types``.",
      "properties": {
        "kind": {
          "const": "on",
          "default": "on",
          "title": "Kind",
          "type": "string"
        },
        "types": {
          "items": {
            "pattern": "^[a-z][a-z0-9_]*:[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$",
            "type": "string"
          },
          "minItems": 1,
          "title": "Types",
          "type": "array"
        }
      },
      "required": [
        "types"
      ],
      "title": "OnFilter",
      "type": "object"
    },
    "Pattern": {
      "discriminator": {
        "mapping": {
          "absence": "#/$defs/AbsencePattern",
          "count": "#/$defs/CountPattern",
          "each": "#/$defs/EachPattern",
          "sequence": "#/$defs/SequencePattern"
        },
        "propertyName": "kind"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/EachPattern"
        },
        {
          "$ref": "#/$defs/CountPattern"
        },
        {
          "$ref": "#/$defs/SequencePattern"
        },
        {
          "$ref": "#/$defs/AbsencePattern"
        }
      ]
    },
    "PredicateFilter": {
      "additionalProperties": false,
      "description": "Envelopes whose event the registered Python predicate ``name`` accepts.\n\nAn escape hatch for what the other filters cannot express. Predicates must be pure.",
      "properties": {
        "kind": {
          "const": "predicate",
          "default": "predicate",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "minLength": 1,
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "PredicateFilter",
      "type": "object"
    },
    "RetryPolicy": {
      "additionalProperties": false,
      "description": "How a failed run is retried: exponential backoff, up to ``max_attempts`` attempts.",
      "properties": {
        "backoff": {
          "default": "PT1S",
          "format": "duration",
          "title": "Backoff",
          "type": "string"
        },
        "max_attempts": {
          "default": 5,
          "minimum": 1,
          "title": "Max Attempts",
          "type": "integer"
        },
        "max_backoff": {
          "default": "PT5M",
          "format": "duration",
          "title": "Max Backoff",
          "type": "string"
        },
        "multiplier": {
          "default": 2.0,
          "minimum": 1.0,
          "title": "Multiplier",
          "type": "number"
        }
      },
      "title": "RetryPolicy",
      "type": "object"
    },
    "RuleName_a-z__a-z0-9____a-z0-9___-_____": {
      "maxLength": 100,
      "pattern": "^[a-z][a-z0-9_]*:[a-z0-9][a-z0-9._-]*$",
      "type": "string"
    },
    "Scope": {
      "additionalProperties": false,
      "description": "The event fields that partition a rule's state and ordering. None: the whole workspace.",
      "properties": {
        "fields": {
          "default": [],
          "items": {
            "type": "string"
          },
          "title": "Fields",
          "type": "array"
        }
      },
      "title": "Scope",
      "type": "object"
    },
    "SequencePattern": {
      "additionalProperties": false,
      "description": "Fire when envelopes match ``steps`` in order, all within ``within`` of the first.\n\nAn envelope that matches the first step while a sequence is in progress (but not the step\nit is waiting for) starts the sequence again from it, so the latest start counts.",
      "properties": {
        "kind": {
          "const": "sequence",
          "default": "sequence",
          "title": "Kind",
          "type": "string"
        },
        "steps": {
          "items": {
            "$ref": "#/$defs/Filter"
          },
          "minItems": 2,
          "title": "Steps",
          "type": "array"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "steps",
        "within"
      ],
      "title": "SequencePattern",
      "type": "object"
    },
    "Throttle": {
      "additionalProperties": false,
      "description": "Allow at most ``at_most`` firings per scope in any period of ``per``.",
      "properties": {
        "at_most": {
          "minimum": 1,
          "title": "At Most",
          "type": "integer"
        },
        "per": {
          "format": "duration",
          "title": "Per",
          "type": "string"
        }
      },
      "required": [
        "at_most",
        "per"
      ],
      "title": "Throttle",
      "type": "object"
    },
    "WhereFilter": {
      "additionalProperties": false,
      "description": "Envelopes whose event field ``field`` compares with ``value`` by ``op``.\n\nA missing field matches nothing, except ``exists`` with ``value=False``.",
      "properties": {
        "field": {
          "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$",
          "title": "Field",
          "type": "string"
        },
        "kind": {
          "const": "where",
          "default": "where",
          "title": "Kind",
          "type": "string"
        },
        "op": {
          "enum": [
            "eq",
            "ne",
            "lt",
            "le",
            "gt",
            "ge",
            "in",
            "contains",
            "matches",
            "exists"
          ],
          "title": "Op",
          "type": "string"
        },
        "value": {
          "$ref": "#/$defs/JsonValue",
          "default": null
        }
      },
      "required": [
        "field",
        "op"
      ],
      "title": "WhereFilter",
      "type": "object"
    }
  },
  "$id": "https://github.com/alexnodeland/reflexr/schemas/reflexr.rules.v1.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "When ``when`` holds for a scope, run ``then``.",
  "properties": {
    "description": {
      "default": "",
      "title": "Description",
      "type": "string"
    },
    "enabled": {
      "default": true,
      "title": "Enabled",
      "type": "boolean"
    },
    "name": {
      "$ref": "#/$defs/RuleName_a-z__a-z0-9____a-z0-9___-_____"
    },
    "on_dead_letter": {
      "default": "continue",
      "enum": [
        "continue",
        "block"
      ],
      "title": "On Dead Letter",
      "type": "string"
    },
    "ordering": {
      "default": "scope",
      "enum": [
        "scope",
        "none"
      ],
      "title": "Ordering",
      "type": "string"
    },
    "retry": {
      "$ref": "#/$defs/RetryPolicy",
      "default": {
        "backoff": "PT1S",
        "max_attempts": 5,
        "max_backoff": "PT5M",
        "multiplier": 2.0
      }
    },
    "scope": {
      "$ref": "#/$defs/Scope",
      "default": {
        "fields": []
      }
    },
    "start": {
      "default": "now",
      "enum": [
        "now",
        "beginning"
      ],
      "title": "Start",
      "type": "string"
    },
    "then": {
      "$ref": "#/$defs/ActionRef"
    },
    "timeout": {
      "anyOf": [
        {
          "format": "duration",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Timeout"
    },
    "when": {
      "$ref": "#/$defs/Condition"
    }
  },
  "required": [
    "name",
    "when",
    "then"
  ],
  "title": "Rule",
  "type": "object"
}
schemas/reflexr.v1.json
{
  "$defs": {
    "AbsencePattern": {
      "additionalProperties": false,
      "description": "Fire once when nothing has passed the filter for ``within`` since the last envelope did.\n\nOnly scopes that have been seen can go quiet. Time passes with every envelope in the log,\nwhether or not it passes the filter.",
      "properties": {
        "kind": {
          "const": "absence",
          "default": "absence",
          "title": "Kind",
          "type": "string"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "within"
      ],
      "title": "AbsencePattern",
      "type": "object"
    },
    "ActionRef": {
      "additionalProperties": false,
      "description": "The action a rule runs, by name, and the params the rule passes it.",
      "properties": {
        "action": {
          "minLength": 1,
          "title": "Action",
          "type": "string"
        },
        "params": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Params",
          "type": "object"
        }
      },
      "required": [
        "action"
      ],
      "title": "ActionRef",
      "type": "object"
    },
    "AgentActor": {
      "description": "An agent or graph running an action for one firing of a rule.",
      "properties": {
        "kind": {
          "const": "agent",
          "default": "agent",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "title": "Name",
          "type": "string"
        },
        "rule": {
          "$ref": "#/$defs/RuleName"
        },
        "run_id": {
          "$ref": "#/$defs/RunId"
        }
      },
      "required": [
        "rule",
        "run_id",
        "name"
      ],
      "title": "AgentActor",
      "type": "object"
    },
    "AllFilter": {
      "additionalProperties": false,
      "description": "Envelopes that match every filter in ``of``.",
      "properties": {
        "kind": {
          "const": "all",
          "default": "all",
          "title": "Kind",
          "type": "string"
        },
        "of": {
          "items": {
            "$ref": "#/$defs/Filter"
          },
          "minItems": 1,
          "title": "Of",
          "type": "array"
        }
      },
      "required": [
        "of"
      ],
      "title": "AllFilter",
      "type": "object"
    },
    "AnyFilter": {
      "additionalProperties": false,
      "description": "Envelopes that match at least one filter in ``of``.",
      "properties": {
        "kind": {
          "const": "any",
          "default": "any",
          "title": "Kind",
          "type": "string"
        },
        "of": {
          "items": {
            "$ref": "#/$defs/Filter"
          },
          "minItems": 1,
          "title": "Of",
          "type": "array"
        }
      },
      "required": [
        "of"
      ],
      "title": "AnyFilter",
      "type": "object"
    },
    "ArchiveRule": {
      "additionalProperties": false,
      "description": "Archive a stored rule, and cancel its unfinished runs.",
      "properties": {
        "expected_version": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Expected Version"
        },
        "reason": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Reason"
        },
        "rule": {
          "$ref": "#/$defs/RuleName"
        },
        "type": {
          "const": "archive_rule",
          "default": "archive_rule",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "rule"
      ],
      "title": "ArchiveRule",
      "type": "object"
    },
    "CancelRun": {
      "additionalProperties": false,
      "description": "Cancel a run that has not finished, stopping its action if it is running.",
      "properties": {
        "reason": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Reason"
        },
        "run_id": {
          "$ref": "#/$defs/RunId"
        },
        "type": {
          "const": "cancel_run",
          "default": "cancel_run",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "CancelRun",
      "type": "object"
    },
    "Causation": {
      "description": "What caused an event that a run emitted, and how deep its causal chain is.",
      "properties": {
        "depth": {
          "minimum": 1,
          "title": "Depth",
          "type": "integer"
        },
        "firing_id": {
          "$ref": "#/$defs/FiringId"
        },
        "run_id": {
          "$ref": "#/$defs/RunId"
        }
      },
      "required": [
        "firing_id",
        "run_id",
        "depth"
      ],
      "title": "Causation",
      "type": "object"
    },
    "ChainTarget": {
      "additionalProperties": false,
      "description": "Feedback on a causal chain: everything one triggering event led to.",
      "properties": {
        "correlation_id": {
          "title": "Correlation Id",
          "type": "string"
        },
        "kind": {
          "const": "chain",
          "default": "chain",
          "title": "Kind",
          "type": "string"
        }
      },
      "required": [
        "correlation_id"
      ],
      "title": "ChainTarget",
      "type": "object"
    },
    "ClientFrame": {
      "discriminator": {
        "mapping": {
          "command": "#/$defs/CommandFrame",
          "hello": "#/$defs/Hello"
        },
        "propertyName": "type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/Hello"
        },
        {
          "$ref": "#/$defs/CommandFrame"
        }
      ]
    },
    "Command": {
      "discriminator": {
        "mapping": {
          "archive_rule": "#/$defs/ArchiveRule",
          "cancel_run": "#/$defs/CancelRun",
          "give_feedback": "#/$defs/GiveFeedback",
          "install_rule": "#/$defs/InstallRule",
          "publish": "#/$defs/Publish",
          "replay_rule": "#/$defs/ReplayRule",
          "retry_run": "#/$defs/RetryRun",
          "skip_run": "#/$defs/SkipRun",
          "update_rule": "#/$defs/UpdateRule"
        },
        "propertyName": "type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/Publish"
        },
        {
          "$ref": "#/$defs/GiveFeedback"
        },
        {
          "$ref": "#/$defs/RetryRun"
        },
        {
          "$ref": "#/$defs/SkipRun"
        },
        {
          "$ref": "#/$defs/CancelRun"
        },
        {
          "$ref": "#/$defs/ReplayRule"
        },
        {
          "$ref": "#/$defs/InstallRule"
        },
        {
          "$ref": "#/$defs/UpdateRule"
        },
        {
          "$ref": "#/$defs/ArchiveRule"
        }
      ]
    },
    "CommandFrame": {
      "additionalProperties": false,
      "description": "A client's command, with an id that correlates it with its result.\n\n``command_id`` is also an idempotency key: the server deduplicates repeated ids.",
      "properties": {
        "command": {
          "$ref": "#/$defs/Command"
        },
        "command_id": {
          "minLength": 1,
          "title": "Command Id",
          "type": "string"
        },
        "type": {
          "const": "command",
          "default": "command",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "command_id",
        "command"
      ],
      "title": "CommandFrame",
      "type": "object"
    },
    "CommandResult": {
      "additionalProperties": false,
      "description": "The result of one command frame.",
      "properties": {
        "command_id": {
          "title": "Command Id",
          "type": "string"
        },
        "ok": {
          "title": "Ok",
          "type": "boolean"
        },
        "outcome": {
          "anyOf": [
            {
              "$ref": "#/$defs/Outcome"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "rejection": {
          "anyOf": [
            {
              "additionalProperties": {
                "$ref": "#/$defs/JsonValue"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Rejection"
        },
        "type": {
          "const": "command_result",
          "default": "command_result",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "command_id",
        "ok"
      ],
      "title": "CommandResult",
      "type": "object"
    },
    "Condition": {
      "additionalProperties": false,
      "description": "A rule's ``when``: a filter, and optionally dedupe, a pattern and a throttle.",
      "properties": {
        "dedupe": {
          "anyOf": [
            {
              "$ref": "#/$defs/Dedupe"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "filter": {
          "$ref": "#/$defs/Filter"
        },
        "pattern": {
          "$ref": "#/$defs/Pattern",
          "default": {
            "kind": "each"
          }
        },
        "throttle": {
          "anyOf": [
            {
              "$ref": "#/$defs/Throttle"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "filter"
      ],
      "title": "Condition",
      "type": "object"
    },
    "CountPattern": {
      "additionalProperties": false,
      "description": "Fire when ``at_least`` envelopes pass within ``within``. A firing consumes them.",
      "properties": {
        "at_least": {
          "minimum": 1,
          "title": "At Least",
          "type": "integer"
        },
        "kind": {
          "const": "count",
          "default": "count",
          "title": "Kind",
          "type": "string"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "at_least",
        "within"
      ],
      "title": "CountPattern",
      "type": "object"
    },
    "Dedupe": {
      "additionalProperties": false,
      "description": "Drop an envelope whose ``key`` fields were already seen within ``within``.",
      "properties": {
        "key": {
          "items": {
            "type": "string"
          },
          "minItems": 1,
          "title": "Key",
          "type": "array"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "key",
        "within"
      ],
      "title": "Dedupe",
      "type": "object"
    },
    "EachPattern": {
      "additionalProperties": false,
      "description": "Fire for every envelope that passes the filter.",
      "properties": {
        "kind": {
          "const": "each",
          "default": "each",
          "title": "Kind",
          "type": "string"
        }
      },
      "title": "EachPattern",
      "type": "object"
    },
    "ErrorFrame": {
      "additionalProperties": false,
      "description": "A frame the server could not understand.",
      "properties": {
        "message": {
          "title": "Message",
          "type": "string"
        },
        "type": {
          "const": "error",
          "default": "error",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "message"
      ],
      "title": "ErrorFrame",
      "type": "object"
    },
    "EvaluatorActor": {
      "description": "An evaluator: a judge or decision model whose verdicts are recorded as feedback.",
      "properties": {
        "kind": {
          "const": "evaluator",
          "default": "evaluator",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "title": "Name",
          "type": "string"
        },
        "version": {
          "title": "Version",
          "type": "string"
        }
      },
      "required": [
        "name",
        "version"
      ],
      "title": "EvaluatorActor",
      "type": "object"
    },
    "EventFrame": {
      "description": "An envelope from the log.",
      "properties": {
        "actor": {
          "discriminator": {
            "mapping": {
              "agent": "#/$defs/AgentActor",
              "evaluator": "#/$defs/EvaluatorActor",
              "external_agent": "#/$defs/ExternalAgentActor",
              "source": "#/$defs/SourceActor",
              "system": "#/$defs/SystemActor",
              "user": "#/$defs/UserActor"
            },
            "propertyName": "kind"
          },
          "oneOf": [
            {
              "$ref": "#/$defs/UserActor"
            },
            {
              "$ref": "#/$defs/AgentActor"
            },
            {
              "$ref": "#/$defs/ExternalAgentActor"
            },
            {
              "$ref": "#/$defs/SystemActor"
            },
            {
              "$ref": "#/$defs/SourceActor"
            },
            {
              "$ref": "#/$defs/EvaluatorActor"
            }
          ],
          "title": "Actor"
        },
        "causation": {
          "anyOf": [
            {
              "$ref": "#/$defs/Causation"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "correlation_id": {
          "title": "Correlation Id",
          "type": "string"
        },
        "event": {
          "additionalProperties": true,
          "properties": {
            "type": {
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "title": "Event",
          "type": "object"
        },
        "id": {
          "$ref": "#/$defs/EventId"
        },
        "seq": {
          "minimum": 1,
          "title": "Seq",
          "type": "integer"
        },
        "traceparent": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Traceparent"
        },
        "ts": {
          "format": "date-time",
          "title": "Ts",
          "type": "string"
        },
        "type": {
          "const": "event",
          "default": "event",
          "title": "Type",
          "type": "string"
        },
        "workspace_id": {
          "$ref": "#/$defs/WorkspaceId"
        }
      },
      "required": [
        "seq",
        "id",
        "ts",
        "workspace_id",
        "actor",
        "correlation_id",
        "event"
      ],
      "title": "EventFrame",
      "type": "object"
    },
    "EventId": {
      "type": "string"
    },
    "ExternalAgentActor": {
      "description": "An agent outside reflexr, connected over MCP.",
      "properties": {
        "client_id": {
          "title": "Client Id",
          "type": "string"
        },
        "kind": {
          "const": "external_agent",
          "default": "external_agent",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        }
      },
      "required": [
        "client_id"
      ],
      "title": "ExternalAgentActor",
      "type": "object"
    },
    "FeedbackTarget": {
      "discriminator": {
        "mapping": {
          "chain": "#/$defs/ChainTarget",
          "firing": "#/$defs/FiringTarget",
          "run": "#/$defs/RunTarget"
        },
        "propertyName": "kind"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/RunTarget"
        },
        {
          "$ref": "#/$defs/FiringTarget"
        },
        {
          "$ref": "#/$defs/ChainTarget"
        }
      ]
    },
    "Filter": {
      "discriminator": {
        "mapping": {
          "all": "#/$defs/AllFilter",
          "any": "#/$defs/AnyFilter",
          "not": "#/$defs/NotFilter",
          "on": "#/$defs/OnFilter",
          "predicate": "#/$defs/PredicateFilter",
          "where": "#/$defs/WhereFilter"
        },
        "propertyName": "kind"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/OnFilter"
        },
        {
          "$ref": "#/$defs/WhereFilter"
        },
        {
          "$ref": "#/$defs/AllFilter"
        },
        {
          "$ref": "#/$defs/AnyFilter"
        },
        {
          "$ref": "#/$defs/NotFilter"
        },
        {
          "$ref": "#/$defs/PredicateFilter"
        }
      ]
    },
    "FiringId": {
      "type": "string"
    },
    "FiringTarget": {
      "additionalProperties": false,
      "description": "Feedback on one firing: whether the rule should have fired.",
      "properties": {
        "firing_id": {
          "$ref": "#/$defs/FiringId"
        },
        "kind": {
          "const": "firing",
          "default": "firing",
          "title": "Kind",
          "type": "string"
        }
      },
      "required": [
        "firing_id"
      ],
      "title": "FiringTarget",
      "type": "object"
    },
    "GiveFeedback": {
      "additionalProperties": false,
      "description": "Give typed feedback on a run, a firing or a causal chain.",
      "properties": {
        "feedback_type": {
          "title": "Feedback Type",
          "type": "string"
        },
        "target": {
          "$ref": "#/$defs/FeedbackTarget"
        },
        "type": {
          "const": "give_feedback",
          "default": "give_feedback",
          "title": "Type",
          "type": "string"
        },
        "value": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Value",
          "type": "object"
        }
      },
      "required": [
        "feedback_type",
        "target",
        "value"
      ],
      "title": "GiveFeedback",
      "type": "object"
    },
    "Hello": {
      "additionalProperties": false,
      "description": "The first frame a client sends on a connection.",
      "properties": {
        "from_head": {
          "default": false,
          "title": "From Head",
          "type": "boolean"
        },
        "protocol": {
          "title": "Protocol",
          "type": "string"
        },
        "resume_after_seq": {
          "default": 0,
          "minimum": 0,
          "title": "Resume After Seq",
          "type": "integer"
        },
        "type": {
          "const": "hello",
          "default": "hello",
          "title": "Type",
          "type": "string"
        },
        "types": {
          "anyOf": [
            {
              "items": {
                "pattern": "^[a-z][a-z0-9_]*:[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$",
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Types"
        }
      },
      "required": [
        "protocol"
      ],
      "title": "Hello",
      "type": "object"
    },
    "InstallRule": {
      "additionalProperties": false,
      "description": "Install a stored rule: its first version, or the next version of an archived one.",
      "properties": {
        "provenance": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "default": {},
          "title": "Provenance",
          "type": "object"
        },
        "rule": {
          "$ref": "#/$defs/Rule"
        },
        "type": {
          "const": "install_rule",
          "default": "install_rule",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "rule"
      ],
      "title": "InstallRule",
      "type": "object"
    },
    "JsonValue": {},
    "NotFilter": {
      "additionalProperties": false,
      "description": "Envelopes that do not match ``filter``.",
      "properties": {
        "filter": {
          "$ref": "#/$defs/Filter"
        },
        "kind": {
          "const": "not",
          "default": "not",
          "title": "Kind",
          "type": "string"
        }
      },
      "required": [
        "filter"
      ],
      "title": "NotFilter",
      "type": "object"
    },
    "OnFilter": {
      "additionalProperties": false,
      "description": "Envelopes whose event is one of ``types``.",
      "properties": {
        "kind": {
          "const": "on",
          "default": "on",
          "title": "Kind",
          "type": "string"
        },
        "types": {
          "items": {
            "pattern": "^[a-z][a-z0-9_]*:[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$",
            "type": "string"
          },
          "minItems": 1,
          "title": "Types",
          "type": "array"
        }
      },
      "required": [
        "types"
      ],
      "title": "OnFilter",
      "type": "object"
    },
    "Outcome": {
      "discriminator": {
        "mapping": {
          "published": "#/$defs/PublishedOutcome",
          "recorded": "#/$defs/RecordedOutcome",
          "rule": "#/$defs/RuleOutcome",
          "rule_version": "#/$defs/RuleVersionOutcome",
          "run": "#/$defs/RunOutcome"
        },
        "propertyName": "type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/PublishedOutcome"
        },
        {
          "$ref": "#/$defs/RecordedOutcome"
        },
        {
          "$ref": "#/$defs/RunOutcome"
        },
        {
          "$ref": "#/$defs/RuleOutcome"
        },
        {
          "$ref": "#/$defs/RuleVersionOutcome"
        }
      ]
    },
    "Pattern": {
      "discriminator": {
        "mapping": {
          "absence": "#/$defs/AbsencePattern",
          "count": "#/$defs/CountPattern",
          "each": "#/$defs/EachPattern",
          "sequence": "#/$defs/SequencePattern"
        },
        "propertyName": "kind"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/EachPattern"
        },
        {
          "$ref": "#/$defs/CountPattern"
        },
        {
          "$ref": "#/$defs/SequencePattern"
        },
        {
          "$ref": "#/$defs/AbsencePattern"
        }
      ]
    },
    "PredicateFilter": {
      "additionalProperties": false,
      "description": "Envelopes whose event the registered Python predicate ``name`` accepts.\n\nAn escape hatch for what the other filters cannot express. Predicates must be pure.",
      "properties": {
        "kind": {
          "const": "predicate",
          "default": "predicate",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "minLength": 1,
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "PredicateFilter",
      "type": "object"
    },
    "Publish": {
      "additionalProperties": false,
      "description": "Publish an event. Publishing an ``id`` already in the log appends nothing.",
      "properties": {
        "correlation_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Correlation Id"
        },
        "event": {
          "additionalProperties": true,
          "properties": {
            "type": {
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "title": "Event",
          "type": "object"
        },
        "id": {
          "anyOf": [
            {
              "$ref": "#/$defs/EventId"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "type": {
          "const": "publish",
          "default": "publish",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "event"
      ],
      "title": "Publish",
      "type": "object"
    },
    "PublishedOutcome": {
      "additionalProperties": false,
      "description": "What publishing did: the event's position, and whether it was already there.",
      "properties": {
        "duplicate": {
          "default": false,
          "title": "Duplicate",
          "type": "boolean"
        },
        "id": {
          "$ref": "#/$defs/EventId"
        },
        "seq": {
          "title": "Seq",
          "type": "integer"
        },
        "type": {
          "const": "published",
          "default": "published",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "seq",
        "id"
      ],
      "title": "PublishedOutcome",
      "type": "object"
    },
    "RecordedOutcome": {
      "additionalProperties": false,
      "description": "Where a fact the command recorded, such as feedback, was appended.",
      "properties": {
        "id": {
          "$ref": "#/$defs/EventId"
        },
        "seq": {
          "title": "Seq",
          "type": "integer"
        },
        "type": {
          "const": "recorded",
          "default": "recorded",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "seq",
        "id"
      ],
      "title": "RecordedOutcome",
      "type": "object"
    },
    "ReplayComplete": {
      "additionalProperties": false,
      "description": "Every event up to ``up_to_seq`` has been replayed; what follows is live.",
      "properties": {
        "type": {
          "const": "replay_complete",
          "default": "replay_complete",
          "title": "Type",
          "type": "string"
        },
        "up_to_seq": {
          "title": "Up To Seq",
          "type": "integer"
        }
      },
      "required": [
        "up_to_seq"
      ],
      "title": "ReplayComplete",
      "type": "object"
    },
    "ReplayRule": {
      "additionalProperties": false,
      "description": "Reset a rule to evaluate the log again, rebuilding its state or firing again.",
      "properties": {
        "from_seq": {
          "default": 0,
          "minimum": 0,
          "title": "From Seq",
          "type": "integer"
        },
        "mode": {
          "default": "rebuild",
          "enum": [
            "rebuild",
            "refire"
          ],
          "title": "Mode",
          "type": "string"
        },
        "rule": {
          "$ref": "#/$defs/RuleName"
        },
        "type": {
          "const": "replay_rule",
          "default": "replay_rule",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "rule"
      ],
      "title": "ReplayRule",
      "type": "object"
    },
    "RetryPolicy": {
      "additionalProperties": false,
      "description": "How a failed run is retried: exponential backoff, up to ``max_attempts`` attempts.",
      "properties": {
        "backoff": {
          "default": "PT1S",
          "format": "duration",
          "title": "Backoff",
          "type": "string"
        },
        "max_attempts": {
          "default": 5,
          "minimum": 1,
          "title": "Max Attempts",
          "type": "integer"
        },
        "max_backoff": {
          "default": "PT5M",
          "format": "duration",
          "title": "Max Backoff",
          "type": "string"
        },
        "multiplier": {
          "default": 2.0,
          "minimum": 1.0,
          "title": "Multiplier",
          "type": "number"
        }
      },
      "title": "RetryPolicy",
      "type": "object"
    },
    "RetryRun": {
      "additionalProperties": false,
      "description": "Make a run runnable now.",
      "properties": {
        "run_id": {
          "$ref": "#/$defs/RunId"
        },
        "type": {
          "const": "retry_run",
          "default": "retry_run",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "RetryRun",
      "type": "object"
    },
    "Rule": {
      "additionalProperties": false,
      "description": "When ``when`` holds for a scope, run ``then``.",
      "properties": {
        "description": {
          "default": "",
          "title": "Description",
          "type": "string"
        },
        "enabled": {
          "default": true,
          "title": "Enabled",
          "type": "boolean"
        },
        "name": {
          "$ref": "#/$defs/RuleName_a-z__a-z0-9____a-z0-9___-_____"
        },
        "on_dead_letter": {
          "default": "continue",
          "enum": [
            "continue",
            "block"
          ],
          "title": "On Dead Letter",
          "type": "string"
        },
        "ordering": {
          "default": "scope",
          "enum": [
            "scope",
            "none"
          ],
          "title": "Ordering",
          "type": "string"
        },
        "retry": {
          "$ref": "#/$defs/RetryPolicy",
          "default": {
            "backoff": "PT1S",
            "max_attempts": 5,
            "max_backoff": "PT5M",
            "multiplier": 2.0
          }
        },
        "scope": {
          "$ref": "#/$defs/Scope",
          "default": {
            "fields": []
          }
        },
        "start": {
          "default": "now",
          "enum": [
            "now",
            "beginning"
          ],
          "title": "Start",
          "type": "string"
        },
        "then": {
          "$ref": "#/$defs/ActionRef"
        },
        "timeout": {
          "anyOf": [
            {
              "format": "duration",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Timeout"
        },
        "when": {
          "$ref": "#/$defs/Condition"
        }
      },
      "required": [
        "name",
        "when",
        "then"
      ],
      "title": "Rule",
      "type": "object"
    },
    "RuleName": {
      "type": "string"
    },
    "RuleName_a-z__a-z0-9____a-z0-9___-_____": {
      "maxLength": 100,
      "pattern": "^[a-z][a-z0-9_]*:[a-z0-9][a-z0-9._-]*$",
      "type": "string"
    },
    "RuleOutcome": {
      "additionalProperties": false,
      "description": "A rule's progress after the command reset it.",
      "properties": {
        "progress": {
          "$ref": "#/$defs/RuleProgress"
        },
        "rule": {
          "$ref": "#/$defs/RuleName"
        },
        "type": {
          "const": "rule",
          "default": "rule",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "rule",
        "progress"
      ],
      "title": "RuleOutcome",
      "type": "object"
    },
    "RuleProgress": {
      "additionalProperties": false,
      "description": "Where a rule is in a workspace's log, stored with its cursor.",
      "properties": {
        "cursor": {
          "default": 0,
          "minimum": 0,
          "title": "Cursor",
          "type": "integer"
        },
        "deadlines": {
          "additionalProperties": {
            "format": "date-time",
            "type": "string"
          },
          "default": {},
          "propertyNames": {
            "$ref": "#/$defs/ScopeKey"
          },
          "title": "Deadlines",
          "type": "object"
        },
        "definition": {
          "default": "",
          "title": "Definition",
          "type": "string"
        },
        "generation": {
          "default": 0,
          "minimum": 0,
          "title": "Generation",
          "type": "integer"
        },
        "silent_through": {
          "default": 0,
          "minimum": 0,
          "title": "Silent Through",
          "type": "integer"
        }
      },
      "title": "RuleProgress",
      "type": "object"
    },
    "RuleVersionOutcome": {
      "additionalProperties": false,
      "description": "A stored rule's version after the command changed it, or found it changed already.",
      "properties": {
        "duplicate": {
          "default": false,
          "title": "Duplicate",
          "type": "boolean"
        },
        "rule": {
          "$ref": "#/$defs/RuleName"
        },
        "seq": {
          "title": "Seq",
          "type": "integer"
        },
        "type": {
          "const": "rule_version",
          "default": "rule_version",
          "title": "Type",
          "type": "string"
        },
        "version": {
          "title": "Version",
          "type": "integer"
        }
      },
      "required": [
        "rule",
        "version",
        "seq"
      ],
      "title": "RuleVersionOutcome",
      "type": "object"
    },
    "Run": {
      "additionalProperties": false,
      "description": "One firing's action: its status, attempts, and a graph's latest checkpoint.",
      "properties": {
        "attempts": {
          "default": 0,
          "title": "Attempts",
          "type": "integer"
        },
        "checkpoint": {
          "$ref": "#/$defs/JsonValue",
          "default": null
        },
        "checkpoints": {
          "default": 0,
          "title": "Checkpoints",
          "type": "integer"
        },
        "correlation_id": {
          "title": "Correlation Id",
          "type": "string"
        },
        "created_at": {
          "format": "date-time",
          "title": "Created At",
          "type": "string"
        },
        "depth": {
          "default": 0,
          "title": "Depth",
          "type": "integer"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "fired_seq": {
          "title": "Fired Seq",
          "type": "integer"
        },
        "id": {
          "$ref": "#/$defs/RunId"
        },
        "matched": {
          "items": {
            "type": "integer"
          },
          "title": "Matched",
          "type": "array"
        },
        "next_attempt_at": {
          "format": "date-time",
          "title": "Next Attempt At",
          "type": "string"
        },
        "output": {
          "$ref": "#/$defs/JsonValue",
          "default": null
        },
        "reason": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Reason"
        },
        "rule": {
          "$ref": "#/$defs/RuleName"
        },
        "scope": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Scope",
          "type": "object"
        },
        "scope_key": {
          "$ref": "#/$defs/ScopeKey"
        },
        "status": {
          "default": "pending",
          "enum": [
            "pending",
            "running",
            "retrying",
            "succeeded",
            "dead",
            "cancelled",
            "skipped"
          ],
          "title": "Status",
          "type": "string"
        },
        "step": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Step"
        },
        "trace_ids": {
          "default": [],
          "items": {
            "$ref": "#/$defs/TraceId"
          },
          "title": "Trace Ids",
          "type": "array"
        },
        "updated_at": {
          "format": "date-time",
          "title": "Updated At",
          "type": "string"
        }
      },
      "required": [
        "id",
        "rule",
        "scope_key",
        "scope",
        "fired_seq",
        "matched",
        "correlation_id",
        "next_attempt_at",
        "created_at",
        "updated_at"
      ],
      "title": "Run",
      "type": "object"
    },
    "RunId": {
      "type": "string"
    },
    "RunOutcome": {
      "additionalProperties": false,
      "description": "A run after the command changed it.",
      "properties": {
        "run": {
          "$ref": "#/$defs/Run"
        },
        "type": {
          "const": "run",
          "default": "run",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "run"
      ],
      "title": "RunOutcome",
      "type": "object"
    },
    "RunTarget": {
      "additionalProperties": false,
      "description": "Feedback on one run: a workflow execution.",
      "properties": {
        "kind": {
          "const": "run",
          "default": "run",
          "title": "Kind",
          "type": "string"
        },
        "run_id": {
          "$ref": "#/$defs/RunId"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "RunTarget",
      "type": "object"
    },
    "Scope": {
      "additionalProperties": false,
      "description": "The event fields that partition a rule's state and ordering. None: the whole workspace.",
      "properties": {
        "fields": {
          "default": [],
          "items": {
            "type": "string"
          },
          "title": "Fields",
          "type": "array"
        }
      },
      "title": "Scope",
      "type": "object"
    },
    "ScopeKey": {
      "type": "string"
    },
    "SequencePattern": {
      "additionalProperties": false,
      "description": "Fire when envelopes match ``steps`` in order, all within ``within`` of the first.\n\nAn envelope that matches the first step while a sequence is in progress (but not the step\nit is waiting for) starts the sequence again from it, so the latest start counts.",
      "properties": {
        "kind": {
          "const": "sequence",
          "default": "sequence",
          "title": "Kind",
          "type": "string"
        },
        "steps": {
          "items": {
            "$ref": "#/$defs/Filter"
          },
          "minItems": 2,
          "title": "Steps",
          "type": "array"
        },
        "within": {
          "format": "duration",
          "title": "Within",
          "type": "string"
        }
      },
      "required": [
        "steps",
        "within"
      ],
      "title": "SequencePattern",
      "type": "object"
    },
    "ServerFrame": {
      "discriminator": {
        "mapping": {
          "command_result": "#/$defs/CommandResult",
          "error": "#/$defs/ErrorFrame",
          "event": "#/$defs/EventFrame",
          "replay_complete": "#/$defs/ReplayComplete",
          "welcome": "#/$defs/Welcome"
        },
        "propertyName": "type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/Welcome"
        },
        {
          "$ref": "#/$defs/EventFrame"
        },
        {
          "$ref": "#/$defs/ReplayComplete"
        },
        {
          "$ref": "#/$defs/CommandResult"
        },
        {
          "$ref": "#/$defs/ErrorFrame"
        }
      ]
    },
    "SkipRun": {
      "additionalProperties": false,
      "description": "Give up on a waiting or dead-lettered run.",
      "properties": {
        "reason": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Reason"
        },
        "run_id": {
          "$ref": "#/$defs/RunId"
        },
        "type": {
          "const": "skip_run",
          "default": "skip_run",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "SkipRun",
      "type": "object"
    },
    "SourceActor": {
      "description": "A system that publishes events, such as a monitoring service or a webhook.",
      "properties": {
        "kind": {
          "const": "source",
          "default": "source",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "SourceActor",
      "type": "object"
    },
    "SystemActor": {
      "description": "reflexr itself (the reactor, schedules), or the application acting on its own behalf.",
      "properties": {
        "kind": {
          "const": "system",
          "default": "system",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "default": "reflexr",
          "title": "Name",
          "type": "string"
        }
      },
      "title": "SystemActor",
      "type": "object"
    },
    "Throttle": {
      "additionalProperties": false,
      "description": "Allow at most ``at_most`` firings per scope in any period of ``per``.",
      "properties": {
        "at_most": {
          "minimum": 1,
          "title": "At Most",
          "type": "integer"
        },
        "per": {
          "format": "duration",
          "title": "Per",
          "type": "string"
        }
      },
      "required": [
        "at_most",
        "per"
      ],
      "title": "Throttle",
      "type": "object"
    },
    "TraceId": {
      "type": "string"
    },
    "UpdateRule": {
      "additionalProperties": false,
      "description": "Replace an active stored rule with a new version, reset if its condition or scope changed.",
      "properties": {
        "expected_version": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Expected Version"
        },
        "provenance": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "default": {},
          "title": "Provenance",
          "type": "object"
        },
        "rule": {
          "$ref": "#/$defs/Rule"
        },
        "type": {
          "const": "update_rule",
          "default": "update_rule",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "rule"
      ],
      "title": "UpdateRule",
      "type": "object"
    },
    "UserActor": {
      "description": "A person, identified by the host application's user id.",
      "properties": {
        "id": {
          "title": "Id",
          "type": "string"
        },
        "kind": {
          "const": "user",
          "default": "user",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        }
      },
      "required": [
        "id"
      ],
      "title": "UserActor",
      "type": "object"
    },
    "Welcome": {
      "additionalProperties": false,
      "description": "The server's answer to ``hello``.",
      "properties": {
        "head_seq": {
          "title": "Head Seq",
          "type": "integer"
        },
        "protocol": {
          "default": "reflexr.v1",
          "title": "Protocol",
          "type": "string"
        },
        "reset": {
          "default": false,
          "title": "Reset",
          "type": "boolean"
        },
        "type": {
          "const": "welcome",
          "default": "welcome",
          "title": "Type",
          "type": "string"
        },
        "workspace_id": {
          "$ref": "#/$defs/WorkspaceId"
        }
      },
      "required": [
        "workspace_id",
        "head_seq"
      ],
      "title": "Welcome",
      "type": "object"
    },
    "WhereFilter": {
      "additionalProperties": false,
      "description": "Envelopes whose event field ``field`` compares with ``value`` by ``op``.\n\nA missing field matches nothing, except ``exists`` with ``value=False``.",
      "properties": {
        "field": {
          "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$",
          "title": "Field",
          "type": "string"
        },
        "kind": {
          "const": "where",
          "default": "where",
          "title": "Kind",
          "type": "string"
        },
        "op": {
          "enum": [
            "eq",
            "ne",
            "lt",
            "le",
            "gt",
            "ge",
            "in",
            "contains",
            "matches",
            "exists"
          ],
          "title": "Op",
          "type": "string"
        },
        "value": {
          "$ref": "#/$defs/JsonValue",
          "default": null
        }
      },
      "required": [
        "field",
        "op"
      ],
      "title": "WhereFilter",
      "type": "object"
    },
    "WorkspaceId": {
      "type": "string"
    }
  },
  "$id": "https://github.com/alexnodeland/reflexr/schemas/reflexr.v1.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "Frames of the reflexr.v1 workspace protocol: `client` is any frame a client sends, `server` any frame a server sends.",
  "properties": {
    "client": {
      "$ref": "#/$defs/ClientFrame"
    },
    "server": {
      "$ref": "#/$defs/ServerFrame"
    }
  },
  "title": "reflexr.v1",
  "type": "object"
}