καιρός — reactive world-model harness (OpenProse/Reactor pattern, in Go). Re-renders facets on change, not on a clock. The noesis scheduler/supervisor.
Find a file
2026-06-03 08:04:53 +02:00
README.md kairos: design — reactive world-model harness (OpenProse/Reactor in Go) 2026-06-03 08:04:53 +02:00

kairos

καιρός — the opportune moment, the right time to act. Classically opposed to chronos (clock time). The whole point of this block in one word: cost scales with kairos, not chronos — work happens when something material moves, not on a timer.

A noesis building block that keeps a declared world-model continuously true. It is the Go, noesis-native realization of the OpenProse/Reactor pattern: you declare the outcomes you want kept true in markdown contracts; kairos builds a DAG of agent sessions, memoizes them, and re-renders only the facets whose upstream inputs actually changed — leaving an append-only receipt behind every decision.

Status: design. The reference implementation we mirror behavior against lives at ../op/prose/ (the TS @openprose/reactor, v0.3). We adopt the idea and the contract language, not the code.

Module: github.com/sistemica/kairos · binary: kairos


The noesis fit

kairos is the scheduler/supervisor the noesis README named as the next missing piece ("nothing launches agents on a schedule or restarts them on crash"). It is pure orchestration over syscalls that already exist — it adds no new agent loop and no new I/O. Same CLI shape as pgf / ergon / memo: self-describing actions, JSON in / JSON out, per-instance vault, optional serve.

   kairos  —  the reactive harness (this block)
   parses *.prose.md → builds the DAG (forme) → decides what re-renders
        │
        │  render a facet  =  run one agent session
        ▼
     ergon      ← the render backend (markdown → plan → skills → structured out)
        │ uses
        ├── pgf      ← all I/O a render performs  + INGRESS (pgf watch/webhooks = external wakes)
        ├── shellac  ← any exec a render needs
        └── memo     ← world-model store + append-only receipt ledger + facet fingerprints

Concept → realization, one-for-one:

Reactor concept kairos realization
contract (*.prose.md) OpenProse markdown, parsed in Go (interop with the reference)
render backend (agent session) ergon — already "markdown/NL task → plan → skills → structured output"
world-model store / receipts memo (history + kv); content-addressed facets
I/O a render performs pgf
exec shellac
ingress / external wake pgf watch + webhooks (the inbound side already exists)
DAG, memoization, continuity scheduler kairos's own Go core — deterministic, no model in the decision
reactor serve kairos serve — same shape as memo serve / shellac serve

The model (adopted from OpenProse, kept as the contract language)

  • Responsibility — a standing goal in a *.prose.md file. Sections: ### Goal, ### Maintains (the world-model schema; #### sub-headings are facets), ### Requires (upstream facet dependencies), ### Continuity (wake policy).
  • Facet — a named, independently-subscribable part of a node's truth. One fingerprint per facet. Subscriptions wire Requires.<facet>Maintains.<facet>.
  • DAG (forme) — match requires↔maintains across all contracts, draw edges, enforce acyclicity. Frozen at compile, fingerprinted on the contract set.
  • Memoization — memo key is exactly (contract_fingerprint, input_fingerprints). Key unchanged → skip at zero cost. Either half moved → render. No clock, no judge step.
  • Wake sourcesinput (an upstream facet moved), self (declared freshness valid_until lapsed), external (ingress / manual trigger).
  • Receipts — append-only ledger; records what fingerprints moved, the wake cause, status, and cost. Chain-verifiable.

Two deliberate improvements over upstream v1

These are the exact gaps we fed back to the Reactor author. Because we own this implementation, we bake the fixes in for the agentic case:

  1. Effect-idempotency for facets with hands. A render that acts on the world (sends an email, books an invoice, writes to the CRM) records an idempotency key in its receipt. A re-render that already produced an effect does not re-fire it. Upstream's at-least-once ingress + memo-skip absorbs a duplicate render, not a duplicate effect; kairos closes that gap.
  2. Human as a first-class event source. An interactive chat (from a cockpit UI) is an external wake on a node; the transcript becomes evidence the DAG renders from. This makes "drop into a cron-driven topic and chat, no re-onboarding" native — the requirement behind op.

Action surface (self-describing, like pgf actions)

kairos actions                       # list actions + params as JSON (self-describing)
kairos compile -p dir=contracts/     # parse *.prose.md, build + validate the DAG, print topology
kairos topology -p dir=contracts/    # nodes, edges, entry points
kairos run     -p dir=contracts/     # reconcile once: render moved facets, skip memoized
kairos status                        # per-node dispositions + cost rollup by surprise cause
kairos receipts [-p verify=true]     # list / chain-verify the ledger
kairos trigger -p node=<id> [-p data=<json>]   # external wake a node
kairos serve   -p http=:PORT [-p host=127.0.0.1]   # continuity scheduler + ingress + HTTP

Per-instance vault (~/.config/kairos/instances/<name>) binds the swappable backends — credential fields, not action fields, per the noesis philosophy:

  • render → which ergon instance fulfills facets (and thus which model)
  • store → where the world-model + receipts live (a memo instance or fs path)
  • ingress → which pgf watch/webhook instances feed external wakes

Worker brain is therefore a config field (an ergon/llm instance), decided per deployment — local models via the proxy for unattended nodes, a stronger model where it matters. Not an architecture decision.


Build plan (smallest slice first)

  1. Parse + compile*.prose.md → contracts → forme DAG → topology JSON. Deterministic, no model. (compile, topology)
  2. Fingerprint + memo — content-address facets; the (contract, inputs) memo key; skip vs render decision; receipt ledger in memo. (run, receipts)
  3. Render via ergon — one facet render = one ergon session; capture output into the world-model; cost into the receipt.
  4. Continuity + ingress + servevalid_until scheduler; pgf watch as external wakes; HTTP status/cost/trigger. (serve, trigger)
  5. The two improvements — effect-idempotency keys; interactive-chat wake.

Verify the thesis the way the reference does: a ledger where unchanged keys cost zero and rendered nodes trace to a named upstream change.


See ../op/DESIGN.md for how kairos is the engine under op (session=state, topic contracts, ephemeral renders), and ../op/prose/ for the reference impl.