Module 03
Actions & workflows
Governed actions, ordered workflows, and reads.
Learning intent
By the end of this module you will be able to
- Explain how actions, queries, and workflows add governed behaviour to a checked contract.
- Separate read-only queries from mutating actions and ordered workflows.
Success criteria
- Classify an operation as action, query, or workflow from its semantics.
- Explain why workflow order is load-bearing.
- Describe preview-by-default for a mutating action.
Retrieval warm-up
Before the new material
Recall
Does the `ask` verb ever mutate state? If not, which verbs do?
Answer
No. `ask` is read-only; it retrieves authoritative truth. Only `run` (execute an action) and `create` (make a new artifact) mutate, and both under preview-by-default.
Recall
Both `show` and `ask` are read-only. What distinguishes them?
Answer
`ask` retrieves a value into the conversation; `show` renders a selection for presentation (a view or table). Same read, different intent.
Recall
What happens in a workflow when a `check` step fails?
Answer
`check` validates an artifact against its contract and emits diagnostics; it never executes. On failure the workflow fails closed, so any following `create` or `run` does not proceed.
Learner readiness
Before this reference page
Assumed terms:
Terms introduced or strengthened here:
You are ready to continue when you can:
- distinguish a mutating action from a read-only query
- explain why workflow order is load-bearing
- state why preview-by-default is safer than direct mutation
Concept · grounded · RICH E4
action
A governed, risk-typed operation with declared inputs.
Worked examples
action authorize-ignition {
input authorization_lane: string required
risk high
lowers-to "helios://action/authorize-ignition"
}
An `action` declares a governed operation: its typed inputs, a risk class, and a `lowers-to` target. It is invoked by the `run` verb and is subject to preview-by-default.
action parse-paper {
risk low
binding required
input source_paper_ref: uri required
input parser_kg_ref: uri required
}
An `action` is a governed mutation contract with four parts: a `risk` class, a `binding` (whether a concrete lowering target is required), and typed `input`s. The action does not contain an implementation body — it declares the contract and `lowers-to` an executable target downstream. Evaluate the separation: the risk class and binding are reviewable governance metadata sitting in front of the code, so an approver reasons about blast radius from the contract alone, before any implementation exists.
Try it
Inside a complete refund-desk `system`, author three governed `action`s — request, approve and pay a refund — that demonstrate the action contract: a `risk` class, a `binding`, and declared `input`s. Make the read-ish request action `risk low` / `binding optional` and the money-moving actions `risk confirm_required` / `binding required`. The full system must pass `varro check vsl` with zero errors.
action approve-refund {
risk confirm_required
binding required
input refund_id: string required
}
# request-refund (risk low) and pay-refund actions still TODO
Model answer (passes varro check vsl)
system mentormind.payments.refund_desk {
mission "Specify a governed refund desk where each mutation is a risk-typed action with declared inputs and a lowering target, under research authority"
authority lane "operator:research"
domain education
maturity draft
context root = "helios://local/mentormind/payments/refund-desk?view=detail&tab=contract&bind=auto"
enum RefundState {
value requested
value approved
value paid
value rejected
}
type Refund {
field refund_id: string required
field amount: number required
field reason: markdown required
field state: RefundState required
}
compile refund-runtime -> varro
action request-refund {
risk low
binding optional
input order_id: string required
input amount: number required
}
action approve-refund {
risk confirm_required
binding required
input refund_id: string required
}
action pay-refund {
risk confirm_required
binding required
input refund_id: string required
}
query refunds.approved {
output Refund[]
}
workflow settle-refund {
inspect selection
resolve refunds.approved
check approve-refund
check pay-refund
render center.detail
}
runtime specification {
host governed
commit-mode host-only
}
}
Try it
Author a complete governed room-booking VSL system that composes a system header, enum, type, compile target, action, query, workflow, and runtime block, then validate it with `varro check vsl`.
system mentormind.facilities.room_booking {
mission "..."
authority lane "operator:research"
domain education
maturity draft
# full contract still TODO
}
Model answer (passes varro check vsl)
system mentormind.facilities.room_booking {
mission "Specify a governed room-booking surface for a campus, exposing booking state as typed contracts under research authority"
authority lane "operator:research"
domain education
maturity draft
context root = "helios://local/mentormind/facilities/room-booking?view=detail&tab=contract&bind=auto"
enum RoomState {
value free
value held
value booked
}
type Room {
field room_id: string required
field capacity: integer required
field state: RoomState required
}
compile booking-runtime -> varro
action hold-room {
risk low
binding required
input room_id: string required
}
query rooms.free {
output Room[]
}
workflow reserve-room {
inspect selection
resolve rooms.free
check hold-room
render center.detail
}
runtime specification {
host governed
commit-mode host-only
}
}
Common trap
❌ Learners assume an `action` just executes code with no risk gating.
Correction
✅ An `action` is risk-typed and governed: it declares inputs, a risk class, and a lowers-to target, and it runs under preview-by-default. There is no ungoverned action.
Check yourself
What does an `action` declaration carry beyond its inputs?
Answer
A risk class and a `lowers-to` target, and it runs under preview-by-default. There is no ungoverned action; it is invoked by the `run` verb.
Concept · grounded · RICH E4
workflow
An ordered sequence of steps composing actions/queries.
Worked examples
workflow classify-year10-evidence {
ask imported-artefact
show allowed-claims
check evidence-class
create evidence-class-mapping
}
A `workflow` composes the five verbs into an ordered behaviour. Read top to bottom: gather, present, validate, then create. Order matters because each step can depend on the last.
workflow parse-paper-pipeline {
inspect selection
resolve parser-knowledge
resolve source-paper
check validate-parser-spec
render center.detail
emit route gate.round_trip
}
A `workflow` is a staged behaviour sequence written as verb + target pairs (`inspect`, `resolve`, `check`, `render`, `emit`...). It composes the declared queries and actions into an ordered pipeline; the ordering is the contract. Note these stage verbs are workflow-internal and distinct from the five-verb command grammar (`ask/show/check/run/create`) at the conversation surface. Evaluate it as a declarative DAG-of-steps: the spec states the sequence and bindings, and lowering generates the executor, so reordering is a spec edit, not a code refactor.
Try it
Inside a complete publishing `system` that already declares `submit-review` and `publish-article` actions plus an `articles.in-review` query, author a `workflow` that sequences them: inspect the selection, resolve the query, check the submit action, propose then check the publish action, render a view and emit a route. Declare the route you emit. The full system must pass `varro check vsl` with zero errors.
workflow review-and-publish {
inspect selection
resolve articles.in-review
check submit-review
# propose + check publish-article, render, emit route still TODO
}
Model answer (passes varro check vsl)
system mentormind.publishing.review_pipeline {
mission "Specify an article review pipeline as an ordered workflow composing inspect, resolve, check and render steps under research authority"
authority lane "operator:research"
domain education
maturity draft
context root = "helios://local/mentormind/publishing/review-pipeline?view=detail&tab=contract&bind=auto"
enum Stage {
value drafting
value review
value published
}
type Article {
field article_id: string required
field title: markdown required
field stage: Stage required
field word_count: integer required
}
compile pipeline-runtime -> varro
action submit-review {
risk low
binding required
input article_id: string required
}
action publish-article {
risk confirm_required
binding required
input article_id: string required
}
query articles.in-review {
output Article[]
}
workflow review-and-publish {
inspect selection
resolve articles.in-review
check submit-review
propose publish-article
check publish-article
render center.detail
emit route pipeline.published
}
route pipeline.published = "helios://local/mentormind/publishing/review-pipeline/published?view=detail&tab=state&bind=auto"
runtime specification {
host governed
commit-mode host-only
}
}
Try it
Author a complete governed room-booking VSL system that composes a system header, enum, type, compile target, action, query, workflow, and runtime block, then validate it with `varro check vsl`.
system mentormind.facilities.room_booking {
mission "..."
authority lane "operator:research"
domain education
maturity draft
# full contract still TODO
}
Model answer (passes varro check vsl)
system mentormind.facilities.room_booking {
mission "Specify a governed room-booking surface for a campus, exposing booking state as typed contracts under research authority"
authority lane "operator:research"
domain education
maturity draft
context root = "helios://local/mentormind/facilities/room-booking?view=detail&tab=contract&bind=auto"
enum RoomState {
value free
value held
value booked
}
type Room {
field room_id: string required
field capacity: integer required
field state: RoomState required
}
compile booking-runtime -> varro
action hold-room {
risk low
binding required
input room_id: string required
}
query rooms.free {
output Room[]
}
workflow reserve-room {
inspect selection
resolve rooms.free
check hold-room
render center.detail
}
runtime specification {
host governed
commit-mode host-only
}
}
Common trap
❌ Learners think workflow steps are an unordered set that may run in parallel.
Correction
✅ A `workflow` is an ordered sequence. Steps run top to bottom; a `check` placed before a `create` exists precisely so the create cannot run if the check fails.
Check yourself
Do the steps of a `workflow` run in order, and why does it matter?
Answer
Yes, top to bottom. Order matters because steps depend on earlier ones; a `check` before a `create` blocks the create when the check fails.
Concept · grounded · RICH E4
query
A read of state with declared output and authorities.
Worked examples
query parsed-papers {
output ParsedPaper[]
authority knowledge-graph
}
A `query` in VSL is a named read contract: it declares an `output` type (here a `ParsedPaper[]`) and the `authority` it reads from. It never mutates. The declared output is part of the contract surface, so an agent can statically know the shape of what a query returns without executing it. Contrast the `ask`/`show` verbs of the five-verb command grammar: those are interactive read commands at the conversation surface, whereas a `query` is a reusable declared contract inside a `system`.
query open-gates { output GateStatus[] authority knowledge-graph }
action run-round-trip-gate {
risk none
binding required
input parsed_paper_ref: uri required
}
Place a `query` and an `action` side by side: the query has only an `output` and an `authority` and carries no `risk` because it cannot change state; the action carries a `risk` class and a `binding` precisely because it can. Evaluate the design: putting the mutate/read split into the grammar (queries simply cannot declare a risk class) means a reviewer never has to audit a query for side effects — the absence of a risk field is a proof obligation discharged by parsing, not by reading the body.
Try it
Inside a complete analytics `system` that declares `Cohort` and `Metric` types, author three read-only `query` contracts, each declaring a typed `output`: all cohorts, all metrics, and only the rising metrics. Use a collection output (`Type[]`) where appropriate. The full system must pass `varro check vsl` with zero errors.
query cohorts.all {
output Cohort[]
}
# metrics.by-cohort and metrics.rising query contracts still TODO
Model answer (passes varro check vsl)
system mentormind.analytics.cohort_metrics {
mission "Specify read-only cohort analytics as named query contracts each declaring a typed output, under research authority"
authority lane "operator:research"
domain education
maturity draft
context root = "helios://local/mentormind/analytics/cohort-metrics?view=detail&tab=contract&bind=auto"
enum Trend {
value rising
value flat
value falling
}
type Cohort {
field cohort_id: string required
field label: string required
field learner_count: integer required
}
type Metric {
field metric_id: string required
field cohort_ref: string required
field mastery: number required
field trend: Trend required
}
compile analytics-runtime -> varro
action recompute-metric {
risk low
binding optional
input cohort_id: string required
}
query cohorts.all {
output Cohort[]
}
query metrics.by-cohort {
output Metric[]
}
query metrics.rising {
output Metric[]
}
workflow surface-metrics {
inspect selection
resolve cohorts.all
resolve metrics.rising
check recompute-metric
render center.table
}
runtime specification {
host governed
commit-mode host-only
}
}
Try it
Author a complete governed room-booking VSL system that composes a system header, enum, type, compile target, action, query, workflow, and runtime block, then validate it with `varro check vsl`.
system mentormind.facilities.room_booking {
mission "..."
authority lane "operator:research"
domain education
maturity draft
# full contract still TODO
}
Model answer (passes varro check vsl)
system mentormind.facilities.room_booking {
mission "Specify a governed room-booking surface for a campus, exposing booking state as typed contracts under research authority"
authority lane "operator:research"
domain education
maturity draft
context root = "helios://local/mentormind/facilities/room-booking?view=detail&tab=contract&bind=auto"
enum RoomState {
value free
value held
value booked
}
type Room {
field room_id: string required
field capacity: integer required
field state: RoomState required
}
compile booking-runtime -> varro
action hold-room {
risk low
binding required
input room_id: string required
}
query rooms.free {
output Room[]
}
workflow reserve-room {
inspect selection
resolve rooms.free
check hold-room
render center.detail
}
runtime specification {
host governed
commit-mode host-only
}
}
Common trap
❌ Because SQL `query` can call functions with side effects and a GraphQL field resolver can mutate, an engineer assumes a VSL `query` is just "any callable" and may write.
Correction
✅ In VSL the read/write split is in the grammar: a `query` declares only output + authority and is non-mutating; anything that changes state is an `action` with a declared risk class and binding. The category boundary is enforced by the parser, not by convention.
Check yourself
A `query` declares an output type and an authority. Can it also declare a risk class and mutate state? Why or why not?
Answer
No. A query is a read contract: it declares output + authority and is non-mutating by construction. Mutation is the province of `action` (risk-typed, bound). The grammar makes the read/write distinction structural, so a query cannot carry a risk class.
Module assessment · scored