OpenProse

OpenProse

One system, two layers. OpenProse is the paradigm you author in -- declare the outcomes you want kept true, in Markdown. Reactor is the harness that keeps them true, so cost scales with surprise, not the clock.

OpenProse

OpenProse is a programming paradigm: you declare the outcomes you want kept true -- an ideal world-model -- instead of issuing instructions. You write that intent as familiar structured Markdown contracts (*.prose.md), with optional imperative ProseScript fulfillment plans for when order, loops, or exact choreography matter. The render function is not deterministic byte code -- it is declarative Markdown fulfilled by a bounded agent session. OpenProse shipped first as a Skill and runs on any Prose-Complete agent harness.

Reactor (@openprose/reactor) is the harness built to run OpenProse -- and the recommended fast path. It keeps a composed world-model up to date against a changing world, re-rendering only the declared facets whose upstream inputs actually moved (memoized agent sessions wired into a DAG), and leaves a content-addressed receipt behind every decision.

These are not two systems. They are one system, two layers that fit together: OpenProse is the language you author in; Reactor is the deterministic host that serves it efficiently. The thesis Reactor works toward:

Inference cost that scales with surprise, not wall-clock time.

In plain terms: you declare what should stay true, the system watches the world, and it does expensive model work only when something material actually moved.

Start here

The shape of a contract

You author Responsibilities -- standing goals, written as Markdown contracts. A responsibility declares what it subscribes to (### Requires) and the truth it keeps current (### Maintains):

---
name: renewal-risk
kind: responsibility
---

### Goal

Keep a current risk read on every account whose signals have moved.

### Requires

- `usage`: the per-account usage facet from the telemetry responsibility

### Maintains

A current risk score per account. Material: the score band and the top
driver per account; `fetched_at` and request ids are immaterial. Each
account carries a `valid_until`. Postcondition: every flagged account
cites a corroborating signal.

### Maintains is the world-model schema doing four jobs at once: it is a type, a canonicalization spec (what is material vs. immaterial, how things normalize), an optional set of facets (named sub-truths a consumer can subscribe to one at a time), and a set of postconditions that compile to commit-gate validators. Structure is subscription: Forme matches Requires.<facet> against Maintains.<facet> and wires the graph from the contracts themselves.

Reactor compiles that set of contracts once (intelligently -- Forme topology, a per-node canonicalizer, postcondition validators, all frozen), then runs them forever (dumbly -- compare fingerprints, then skip, render, or propagate). The reconciler that decides whether to wake is deliberately deterministic: there is no judge step. The memo key has no clock in it. A re-poll that returns the same truth costs nothing. See the foundation for the full authored surface, and the harness for how it runs.

React-flavored, not React-gated

You do not need React to use this. The contracts are Markdown; the CLI, the receipts, and the keyless replay are entirely React-free. The whole product in two sentences: you declare what should stay true, the system watches the world, and it does expensive model work only when something material actually moved. The table below is an optional mental model for the people who already carry one -- skip it freely.

Optional: the React metaphor (skippable)

If you know React, you already know the shape -- substitute three nouns:

ReactReactor
ComponentResponsibility -- a declared standing goal
DOMWorld-model -- the maintained truth, on disk, passed by pointer
render()A bounded LLM session that computes the next world-model
propsSubscriptions to other responsibilities' outputs
React.memo (skip if props unchanged)Skip the render if subscribed inputs haven't moved
Manual dependency wiringForme -- the graph wires itself from declared contracts

The intelligence is frozen ahead of time, at compile, into a per-node canonicalizer and the Forme wiring. The reconciler at run time is dumb on purpose. There is no .prose parser and no interpreter -- a compile step is itself an agent session; the session embodies the VM.

See the thesis -- keyless, no model call

The fastest way to understand the system is to replay a real saved run and read the per-node rendered/skipped dispositions, the receipt counts by surprise_cause, the token cost rollup, and per-node chain-verify -- with no key and no spend. No install required:

npx -p @openprose/reactor-devtools reactor-devtools --example masked-relay --describe
reactor-devtools --describe
  (synthetic sample ledger -- token counts are illustrative, not a bill)
dispositions  rendered=46 · skipped=31 · failed=0
surprise-cause  external=8 · input=69   (a.k.a. wake-cause)   ← receipt COUNTS, 77 total

COST ROLLUP  (tokens)
  total       fresh=27180 tokens · reused=12840 tokens · reuse=32%
    external  receipts=  8 fresh=   1080 tokens reused=840 tokens
    input     receipts= 69 fresh=  26100 tokens reused=12000 tokens
CHAIN-VERIFY ok

The binary prints that synthetic-sample banner first, and it is the honest frame: masked-relay is a saved sample ledger, so the token magnitudes are illustrative, not a measured bill. What is genuinely checkable here is the structure -- the per-node rendered/skipped dispositions, the surprise_cause receipt counts, and CHAIN-VERIFY ok (every receipt links its prev). That structural shape is "cost scales with surprise," and you can verify it with no key and no spend. (When you run your own contract, the cost rollup becomes your real spend; see the honest-status notes on why there are no benchmark numbers yet.) From there, the setup path walks the full ordered route: the keyless proof first, then init -> doctor -> compile offline, then go live and serve. Or jump to the CLI quickstart.

Where the truth lives

The canonical execution behavior lives in the open-source open-prose skill in the openprose/prose repo. These docs are orientation; if the docs and the skill disagree, trust the skill. New here? Start with OpenProse the paradigm; coming from a chat-first workflow, jump to Reactor, the dependency-across-runs layer your prompts kept asking for.


The conversation always ends. The responsibility shouldn't have to.

On this page