Authoring Tools for the Subprocess Seam
The full guide lives in the repository at
docs/guides/subprocess-tool-authoring.md
— this page is the summary.
The wire protocol
- in: one JSON value on stdin, then EOF
- out (success): blocks on stdout (array / ndjson / single object)
- out (failure): structured
ToolErroron stderr + nonzero exit
The rules
- Payloads serialize adjacently tagged (
{"kind", "data"}). Internal tagging hard-fails at the seam. In Rust, use#[derive(BlockPayload)]; in other languages, emit the two-key object. - Kind tags are namespaced (
<vertical>.<kind>) and equal tokind_name()— one declaration, no divergence. - The minimal block requires
schema_version,attribution(withprovenance.whenRFC 3339 +provenance.producer), andpayload. Unknown top-level fields are rejected. Validate againstlonis schema block. - Targets arrive via stdin or argv — never env or cwd. The environment is cleared and the cwd neutral by design.
- You are bounded — hard timeout, byte caps; exceeding either kills your process. Keep payloads small; stream incrementally.
- Streaming: one block per line (ndjson), and flush after each line — runtimes block-buffer stdout on pipes.
Hosting many tools
Ship one executable with the provider surface (manifest / tools list /
tools describe / call) — the host discovers your whole operation set.
See The Provider Model.
Depending on Lonis pre-1.0-era
Since v0.1.0 the crates are on crates.io: lonis-schema = "0.1". Before
publication, the discipline was git deps pinned to a rev, optional behind a
feature — the pattern is preserved in the full guide for pre-release
branches.