Built-in sandbox SHIM: attach — the ONE way a block hands an artifact it
produced to the engine. A tool running in python_execution
writes any artifact (a PNG it rendered, a CSV/JSON/PDF/wav it built, whatever)
and hands it to attach(path) (or attach(data, filename) for bytes it
never wrote out), getting back the stored artifact's DESCRIPTOR; the
engine then OWNS the bytes as a durable session_iteration_attachment row —
surviving a web/TUI restart and (for image media-types) replayable to a
vision model cross-turn.
No parsing, no round-trip through the model-facing stdout: we control the whole
boundary. One Python front serves attach in a block and vis.attach in an
extension: _attachment_verbs of the SDK (blockether/vis/extension.py). It reads
the file through the confined open of its process, so a path outside the roots
raises the normal sandbox error. Then it calls the host bridge with one options
map and the type that the filename suggests as a hint. Each operation has one
body here behind two door names: a __vis_record_attachment__ name for the
sandbox and a __vis_host_attach__ name for an extension
([[extension-host-doors]]). The engine decides the media type
([[decide-attachment]]). The bridge appends the attachment map to the
per-block *attachment-sink* (mpl-capture/record-attachment!). run-python-block
drains that sink into the block outcome's :attachments; the loop stamps each with
the producing block's tool-call-id and hands them to db-store-iteration!'s
:attachments. The artifact's :id and :version are minted at the sink, so
the block that produced it can address it immediately.
Registered unconditionally as a foundation shim, alongside ls: its
:ext/sandbox-shims entry autoloads attach into every sandbox.
Built-in sandbox SHIM: `attach` — the ONE way a block hands an artifact it produced to the engine. A tool running in `python_execution` writes any artifact (a PNG it rendered, a CSV/JSON/PDF/wav it built, whatever) and hands it to `attach(path)` (or `attach(data, filename)` for bytes it never wrote out), getting back the stored artifact's DESCRIPTOR; the engine then OWNS the bytes as a durable `session_iteration_attachment` row — surviving a web/TUI restart and (for image media-types) replayable to a vision model cross-turn. No parsing, no round-trip through the model-facing stdout: we control the whole boundary. One Python front serves `attach` in a block and `vis.attach` in an extension: `_attachment_verbs` of the SDK (`blockether/vis/extension.py`). It reads the file through the confined `open` of its process, so a path outside the roots raises the normal sandbox error. Then it calls the host bridge with one options map and the type that the filename suggests as a hint. Each operation has one body here behind two door names: a `__vis_record_attachment__` name for the sandbox and a `__vis_host_attach__` name for an extension ([[extension-host-doors]]). The engine decides the media type ([[decide-attachment]]). The bridge appends the attachment map to the per-block `*attachment-sink*` (`mpl-capture/record-attachment!`). `run-python-block` drains that sink into the block outcome's `:attachments`; the loop stamps each with the producing block's tool-call-id and hands them to `db-store-iteration!`'s `:attachments`. The artifact's `:id` and `:version` are minted at the sink, so the block that produced it can address it immediately. Registered unconditionally as a foundation shim, alongside `ls`: its `:ext/sandbox-shims` entry autoloads `attach` into every sandbox.
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 |