Docs
Reference

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

SourceShape
flow/inputrun input map declared by :invocations
step resultClojure map, vector, scalar, or persisted ref map
:http inline resultmap with status, headers, and body fields when not persisted
persisted blob resultcompact ref map with :uri or :resource-uri plus metadata
persisted table resulttable ref plus preview/count metadata
CLI command resultJSON envelope with ok, data, meta, and optional links / error

Ephemeral Local-Literal Step Runs

breyta flows steps run <slug> <step-id> sends the complete local source as
args.flowLiteral to steps.run. The API validates that literal in memory,
resolves the qualified step id from the top-level :steps vector, and executes
it through the normal runtime without creating or updating a flow draft. The
response identifies this explicitly:

{
  "data": {
    "stepType": "function",
    "stepId": "tools/add-one",
    "flow": {
      "flowSource": "literal",
      "persisted": false,
      "sourceHash": "sha256..."
    },
    "result": {"answer": 3}
  }
}

This is a proof surface, not a second manifest. The local .clj file remains
the source of truth; use breyta flows push --file ... when the source should
be persisted as the workspace draft.

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 :function :make-output {...})
      first-row (get-in make-output [:rows 0])]
  {:id (:id first-row)})

For selective expansion:

  • --result-path rows.0 or --result-path '[:rows 0]' previews one branch
  • --preview-depth, --preview-items, and --preview-runes raise bounded caps
  • --result-file ./tmp/result.json writes the full result locally without
    putting it in the CLI output
  • --full restores full data.result output

Run and step preview surfaces redact secret-like map values before returning
them to CLI/API/UI clients. Keys such as authorization, developer-token,
api-key, token, password, and secret render as [REDACTED] in
resultPreview, run events, run step output, and run inspection output.

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.

For application/json resources, :load [:field] hydrates parsed data. When the
next API needs the original file contents, such as a GitHub Contents update for
package-lock.json, use :load {:field :text} or {:field :raw} to receive the
raw UTF-8 string instead. For binary files (docx, xlsx, pptx, pdf, images) use
:load {:field :bytes}; :text/:raw UTF-8-decode and corrupt them. Pair with
breyta.sandbox/base64-encode for APIs that take base64 or data: URIs.

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/parse for JSON strings or bytes
  • use json/write-str when 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.

References

As of Jul 27, 2026