Live validation proves that the runtime works with real providers. It is not the default development gate, and it should never be required for routine offline changes.
Run live validation when a change touches:
For docs-only or deterministic runtime changes, clojure -M:test plus hygiene
checks is usually enough.
Before starting a live run:
flowchart LR
Offline["clojure -M:test"] --> Models["Choose provider and models"]
Models --> Env["Export credentials into JVM shell"]
Env --> Governor["Set runtime governor"]
Governor --> Run["Run API or CLI specimen"]
Run --> Inspect["Inspect report, events, heads, trace"]
Inspect --> Sanitize["Record public-safe summary"]
Run the offline gate first:
clojure -M:test
Decide the exact provider, root model, child model, and leaf model for this run. Prefer smaller or cheaper models for leaves when that still exercises the behavior under test.
Export provider credentials into the shell that will start the JVM. Do not rely on credentials loaded only into an editor, terminal profile, or separate process.
Use an ignored artifact directory for durable stores and reports. Relative
paths under .fractal/ or runs/ are ignored by this repo.
Set the runtime governor explicitly: :max-steps, :max-turns,
:call-timeout-ms, :max-fanout, :fanout-pool,
:leaf-concurrency, and the hard context-window threshold.
The checked-in opt-in suite is:
clojure -M:live-test
Interpret results carefully:
Do not add live tests to the default :test alias.
For one-off live specimens, keep the config small and explicit. A typical shape:
(require '[fractal.engine.api :as fe])
(def cfg
(fe/make-config
{:adapter :sdk
:provider :provider-key
:model "root-model-id"
:harness :rlm
:child-model "child-model-id"
:leaf-model "leaf-model-id"
:max-steps 8
:max-turns 1
:call-timeout-ms 60000
:max-fanout 4
:fanout-pool 2
:store :sqlite
:store/dir ".fractal/live-validation/run-id"}))
(def s (fe/start-session! cfg {:id "live-validation-run"}))
(def result (fe/run-turn! s "Return a small deterministic value via FINAL."))
(fe/close-session! s)
Replace provider and model placeholders with public provider identifiers that exist in the SDK catalog or are explicitly supported by the local provider configuration. Keep any credentials outside the repository.
When the control plane changes, validate through the shipped CLI rather than only through the Clojure API. Use an ignored artifact directory and an EDN config profile:
{:default-profile :live
:profiles
{:live
{:adapter :sdk
:provider :provider-key
:model "root-model-id"
:harness :rlm
:capability :default
:store :sqlite
:store/dir ".fractal/live-cli-validation/run-id/store"
:child-model "child-model-id"
:leaf-model "leaf-model-id"
:max-steps 8
:max-turns 8
:call-timeout-ms 90000
:max-fanout 4
:fanout-pool 2
:leaf-concurrency 2
:cache-ttl "5m"}}}
A complete control-plane smoke should exercise every command at least once:
clojure -M:cli init --config .fractal/live-cli-validation/run-id/init.edn --store-dir .fractal/live-cli-validation/run-id/init-store --session init-session --force
clojure -M:cli config --config .fractal/live-cli-validation/run-id/fractal.edn --pretty
clojure -M:cli run --config .fractal/live-cli-validation/run-id/fractal.edn --session live-run --message-file messages/run.md
clojure -M:cli start --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli turn --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal --message-file messages/turn-1.md
clojure -M:cli turn --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal --message-file messages/turn-2.md
clojure -M:cli resume --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli compact --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli wait --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli status --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli progress --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli view --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli events --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal --since 0
clojure -M:cli heads --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli head --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal --head "$head_id"
clojure -M:cli messages --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli turns --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli steps --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli evals --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli trace --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli check --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli report --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli close --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli stop --config .fractal/live-cli-validation/run-id/fractal.edn --session live-normal
clojure -M:cli run --config .fractal/live-cli-validation/run-id/fractal.edn --session live-recursive --message-file messages/recursive.md
clojure -M:cli edges --config .fractal/live-cli-validation/run-id/fractal.edn --session live-recursive
clojure -M:cli tree --config .fractal/live-cli-validation/run-id/fractal.edn --session live-recursive
clojure -M:cli run --config .fractal/live-cli-validation/run-id/fractal.edn --session live-payload --message-file messages/payload.md
clojure -M:cli turns --config .fractal/live-cli-validation/run-id/fractal.edn --session live-payload --edn
clojure -M:cli payload --config .fractal/live-cli-validation/run-id/fractal.edn --session live-payload --ref "$payload_ref"
clojure -M:cli help
The assertions should prove more than command exit status:
:final;turn observes REPL state from an earlier turn;tree sees at least two
sessions;compact publishes a compaction head;check returns ok true;trace hydrates assistant code and observation messages for a turn;payload hydrates a content-addressed value from a ref returned by turns;stop, close, and resume work through durable reopen.When changing fractal.engine.surface, capability gating, request assembly, or
leaf prompt wiring, run the focused surface live test instead of relying only on
generic recursion tests:
clojure -M:live-test -n fractal.engine.live-surface-test
The checked-in surface smoke uses a temporary Git-like repository surface and a bounded task that asks the root model to:
Useful assertions for manual or extended surface smokes:
:final;:surface/mismatch;A useful live validation note should include:
Do not include raw prompts, full transcripts, local credential paths, cloud project identifiers, secret names, personal identifiers, or machine-specific paths in tracked reports.
Treat every live recursion run as potentially multiplicative. A root turn may make additional provider calls through leaves, children, nested children, or fan-out lanes.
Use the engine runtime governor deliberately:
:max-fanout and :fanout-pool before raising model quality;:max-turns for live sessions unless the scenario specifically tests
multi-turn continuity;:max-steps per turn and raise it only when a scenario requires
multi-step REPL work;:leaf-concurrency when a provider or account is rate-limit sensitive;:call-timeout-ms to bound provider stalls and retry loops;:context;If a live scenario needs high fan-out, deep recursion, or multiple turns, record the expected upper bound before starting the run.
The engine records usage and cost when providers report them, but those records are observability metadata. The governor remains the execution controls above.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |