Put the pieces together
You can now read the workflow as three responsibilities: ask for an amount, describe the decision, and keep failure explicit. Each responsibility has a place in the complete source bundle.
use "./service"
use "./decisions"
pub flow main() -> Text = match service.lookup() {
Ok(amount) => decisions.describe(amount),
Err(problem) => { let _ = problem
"Could not decide"
},
}
@tool pub flow lookup() -> Result<Int, Text>
pub flow describe(amount: Int) -> Text = if amount > 100 { "Review" } else { "Proceed" }
"Proceed"Read the entry first
The entry imports the service and the decision module. It calls the service once. A successful amount goes to the pure helper; an error takes its own branch. The helper does not need to know which process, model or service supplied the amount.
Try the exercise. Change the rule so that an amount of 42 or higher requires review. Keep the failure answer intact. The check tries both a successful and a failed reply, so returning a constant answer is not enough.
Explain the run to someone else
Run successfully and expand its recorded history. Point to the call, its reply, and the result. Explain which part came from outside and which part follows from the source. Replay it after changing the selected fixture. Explain why the current fixture did not change that recorded result.
This is the core habit the book is building: write a program whose decisions you can follow, make its outside observations typed, and use the record to distinguish what happened from what could happen on another run.
What belongs around this program?
The application still chooses the implementations, obtains credentials, handles approvals and manages the run's lifecycle. Those concerns do not become language mechanisms because a Tool has a helpful name. The final chapter takes that program into an application.
Exact rules: application boundary, execution.
Diagnose before repairing
A useful next workflow measures several candidates, finds the failing ones, repairs only those, and measures them again. Keep the decision in Flow: returned facts should select the work that happens next. Keep the specialist calculation behind a typed Tool.
Read the recorded reply beside the predicate that uses it. A passing check only answers its stated question. Ask which units, inputs, time window and reference it covers. “Close enough” pixels cannot establish exact pixels; a build that succeeded for yesterday's source cannot establish today's artifact.
A repair is not a new passing check. Recheck the edited candidate before choosing it. Preserve failures and uncertainty instead of replacing them with a broad “verified” flag.
Practice with shared libraries
From a repository checkout, build the CLI with cargo build -p flow-cli --locked.
Run flow test libraries/workflow to exercise the shared selection and repair
functions against typed fakes. Run python3 examples/integration-repair/verify.py
to bind real numerical Python, C compilation and SQLite implementations.
The exercise checks three candidates. It repairs only the failed Python and C candidates, rechecks all three and selects the greatest passing score. A second scenario changes a dependency after validation: delivery is refused. A third uses a narrower check domain: that evidence cannot justify repair or delivery. The host evidence library records the entire declared dependency set, not only the main source file. Undeclared dependencies remain the application's concern.
Try these steps:
- Read
libraries/workflow/integration_example.flow: locate observation, repair, recheck and selection. Specialist computation stays behind Tools. - Run the exercise with
--receipt target/integration-repair.json --workspace target/integration-workspace(a new directory). Read the ordered repairs and the exact refusal reason for each negative scenario. - Install the toolkit into a new environment with
python3 -m venv target/workflow-venvandtarget/workflow-venv/bin/python -m pip install ./toolkits/python. Runtarget/workflow-venv/bin/flow-evidence target/integration-workspace/ok/compiler.check.json --subjects target/integration-workspace/ok/compiler.subjects.json --required target/integration-workspace/ok/required-domain.json. It explains freshness and domain mismatches without invoking the validator. - Find the
okrun ID in the receipt. Inspect it withflow history RUN --runs target/integration-workspace/ok/.flow/runs --kind Callor MCP. A check receipt is ordinary host reply data; it does not create a permission or a scientific proof.
For general transformations, begin with std's filter, partition, traversal and extrema functions. Put domain-specific workflow functions in a library. Keep processes, dependencies and delivery evidence in the application toolkit.