Runtime Data Shapes
Use this page when authoring function steps, passing persisted refs, or reading
CLI/API output without adding redundant parser code.
Default Assumption
Breyta flow values are usually Clojure maps and vectors already. Prefer map
access over defensive string parsing:
(let [customer-id (get-in input [:invoice :customer-id])
rows (:rows table-result)]
{:customer-id customer-id
:row-count (count rows)})
Only parse JSON when the value is actually a JSON string or bytes.
Common Runtime Shapes
| Source | Shape |
|---|---|
flow/input | run input map declared by :invocations |
| step result | Clojure map, vector, scalar, or persisted ref map |
:http inline result | map with status, headers, and body fields when not persisted |
| persisted blob result | compact ref map with :uri or :resource-uri plus metadata |
| persisted table result | table ref plus preview/count metadata |
| CLI command result | JSON envelope with ok, data, meta, and optional links / error |
Step Run Result Preview
breyta steps run is optimized for authoring loops. Default output omits the
full data.result and returns data.resultPreview instead:
{
"data": {
"resultPreview": {
"binding": "make-output",
"format": "clojure-value-preview",
"value": "{:rows [{:id \"row-1\", :score 0.92}], :summary \"ready\"}",
"truncated": false
}
}
}
Read resultPreview.value as the value shape you would bind from
(flow/step ...) in DSL code. The command still returns JSON as a transport
envelope, but the preview uses Clojure map/vector notation so access patterns are
obvious:
(let [make-output (flow/step :code :make-output {...})
first-row (get-in make-output [:rows 0])]
{:id (:id first-row)})
For selective expansion:
--result-path rows.0or--result-path '[:rows 0]'previews one branch--preview-depth,--preview-items, and--preview-runesraise bounded caps--result-file ./tmp/result.jsonwrites the full result locally without
putting it in the CLI output--fullrestores fulldata.resultoutput
Inline --params '<json>' is fine for small input maps. Use --params-file for
larger or reused inputs.
Resource Refs
Persisted outputs are passed as compact refs, not full payloads. Treat any
res://... URI or map with :uri / :resource-uri as a handle that can be
read later.
In source, pass the step result map forward:
(let [resp (flow/step :http :fetch
{:url "https://api.example.com/export"
:method :get
:persist {:type :blob}})
summary (flow/step :function :summarize
{:input {:resp resp}
:load [:resp]
:code '(fn [{:keys [resp]}]
{:bytes (:size resp)
:resource (:uri resp)})})]
summary)
Use :load only where the downstream step needs hydrated content. Many steps
can pass refs through without loading the full body.
Blob refs also carry storage-tier meaning: retained/default for durable or
user-visible artifacts; ephemeral for temporary streamed HTTP blobs:
(flow/step :http :download-export
{:url "https://api.example.com/export.zip"
:method :get
:response-as :bytes
:persist {:type :blob
:tier :ephemeral}})
When a later function turns that ephemeral source into a final report, image, or
table for users, persist the derived artifact intentionally on the retained
default path.
JSON And Sandbox Helpers
Inside function steps:
- use
json/parsefor JSON strings or bytes - use
json/write-strwhen a downstream API needs a JSON string - use
breyta.sandbox/*helpers for safe base64, hex, SHA-256, UUID, and
instant parsing utilities - keep functions small and domain-focused
Avoid hand-written parsers for values already represented as maps.
Bounded Output
Inline final output should be compact and user-facing. Large reports, tables,
exports, generated media, and page sets should be persisted and returned as refs
or viewer-friendly artifacts.
For human-readable tables, return a persisted table resource. Do not return a
giant inline JSON table as the final artifact.
CLI/API Envelope
Most CLI JSON output follows this shape:
{
"ok": true,
"data": {},
"meta": {},
"links": {}
}
Use data for facts, meta.nextCommands for the next small command, links
for URLs, and error for failed requests. Search/list commands are compact by
default; use explicit --full, --limit, or read/show commands when deeper
context is needed.