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 --> Leashes["Set max steps, turns, timeout, fanout"]
Leashes --> 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 explicit leashes: :max-steps, :max-turns, :call-timeout-ms,
:max-fanout, and :fanout-pool.
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.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 these controls 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;:call-timeout-ms to bound provider stalls and retry loops;If a live scenario needs high fan-out, deep recursion, or multiple turns, record the expected upper bound before starting the run.
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 |