An executable recipe format.
Sous is an open, machine-readable format for recipes that a kitchen orchestration system can execute, not merely display. It is built on one idea that no existing recipe format has: an ingredient's state is separate from the procedure that produces it.
A recipe says it needs diced onion. Whether that comes from a bag of pre-diced onion or from a knife and a whole onion is a planning question, not a recipe fact.
"requires": [
{ "id": "onion",
"substance": { "ref": "sous:onion_peeled", "label": "onion (peeled)" },
"state": { "form": "diced" }, // WHAT is needed
"quantity": { "kind": "exact", "value": 500, "unit": "g" } }
] // not HOW to get it
Give that recipe a kitchen with whole onions and the planner emits peel then
cut. Give it a kitchen with pre-diced onions and the plan is empty. Same recipe,
both times. A raw onion is peelable and not cuttable, so the ordering
is not a rule — it is the only reachable plan.
Worked plans shows this rather than asserting it: the same recipes scheduled against different kitchens, drawn as dependency graphs and Gantt charts, and then run — including a tempering step that is observed to be finished, breaches its ninety-second control point anyway, and is discarded.
These URIs are what $id and $schema fields point at. They are
identifiers first and locations second — nothing in the toolchain dereferences them, since every
cross-file $ref is relative and resolved against a local registry. They are served
here for anyone who pastes one into a browser.
| Layer | Namespace URI |
|---|---|
| Recipe Required states, a task network, a goal |
https://sous.pras.ai/schema/v0/recipe.schema.json |
| Kitchen Equipment and pantry — the planner's initial state |
https://sous.pras.ai/schema/v0/kitchen.schema.json |
| Domain Facets and operations — compiles to PDDL |
https://sous.pras.ai/schema/v0/domain.schema.json |
| Schedule One recipe, one kitchen, resolved — the document an executor consumes. Generated, never authored. |
https://sous.pras.ai/schema/v0/schedule.schema.json |
| Run What happened: observations, deviations, escalations |
https://sous.pras.ai/schema/v0/run.schema.json |
| Common Identifiers, quantities, state, conditions |
https://sous.pras.ai/schema/v0/common/ |
| Also served | |
|---|---|
https://sous.pras.ai/vocab/ |
The domain: facets, operations, units, equipment classes, 260 substances. |
…/schema/v0/context.jsonld |
JSON-LD context. Maps foodon:, chebi: and the rest onto IRIs,
and says plainly which of them dereference. |
The namespace is scoped to the major version, so additive 0.N → 0.N+1 releases
do not rewrite the $id of every schema or the $schema line of every
document in the wild.
git clone https://github.com/psigen/sous
cd sous && uv sync # pins the interpreter and deps
uv run tests/run_tests.py # the acceptance suite
uv run tools/sous_validate.py examples/*.sous.json
# what to do, then when to do it
uv run tools/sous_schedule.py \
examples/dal-tadka.sous.json \
examples/kitchens/home-kitchen.sous-kitchen.json --out plan.json
# then carry it out -- plan.json is all the executor reads
uv run tools/sous_run.py plan.json --format text
| docs/spec/ | The normative specification, and the seven documents around it |
| SEMANTIC-RULES.md | Constraints JSON Schema cannot express |
| CONFORMANCE.md | What it means to implement Sous |
| EXECUTION.md | Turning a schedule into a run, and onto a workflow engine |
| SAFETY.md | Allergen derivation and critical control points |
| GOVERNANCE.md | Versioning and namespace policy |
| LIMITATIONS.md | Known gaps and open problems |
| docs/arch/ | The decisions and, more usefully, why the obvious alternative was rejected |