Expand description
§output_store — Data-plane support layer
Module built on the Data (Big Response handling) vs. Domain (Flow / verdict)
separation axis. Owns the machinery for shuttling big response bodies
(4k-token-scale text / file paths / blobs) between SubAgents, and stays out
of the Engine’s flow control (the BLOCKED/PASS if/else verdicts). The
Domain path — engine.rs submit_output / output_tail / dispatch — is
left untouched.
§Why (Data / Domain separation)
The Engine’s output_store HashMap plus Final.ok extraction in
the dispatch path already covers the Domain (verdict flow). Pushing Big Response
payloads (LLM answers of several kilotokens, intermediate files, large
blobs) through the same path floods MainAI context after only a handful of
SubAgents and turns the return-text channel into a file-path junk drawer.
Resolution: MainAI only carries OutputRef (a small out_id); this
module owns the big bodies. The Domain (flow control) stays inside the
Engine, the Data plane (Big Response handling) is completed by this module
and its paired SpawnerLayers, and the two do not interfere.
Note that the Sub/Main-Agent split is not just a context-size trick — it is a support scaffold for MainAI, which is what keeps a pure Flow orchestrator from becoming either rigid or brittle. Data-plane offloading is one of the things that scaffold needs to work.
§Architecture (three lifecycle axes)
Data handling is cut along three lifecycles. Mixing them collapses into Agent hardcoding, non-portability, or unmanaged growth:
- LC1 — Agent authoring (Swarm-independent): the Agent contract in
Agent.mdspeaks in terms of$IN_REFSand a single EMIT tool. It does not know Swarm-specific paths or ids. - LC2 — Agent execution (Swarm = runtime environment): at spawn time
the runtime injects env (
$IN_REFS= previousout_idlist, EMIT tool plus token). The SubAgent POSTs directly to the store, bypassing MainAgent. - LC3 — Swarm management (this module = Data owner): intake (EMIT) →
allocate
OutputRef→ register → optional disk persistence.get(out_id)feeds the next spawn’sIN_REFS.
§Discipline
- SubAgent → MainAgent direct return is forbidden. Big bodies never
ride the return text; MainAgent only holds an
OutputRef(small id). - Write path is the EMIT tool, once. No file-side channel, no smuggling through return text — the goal is to remove the “LLM forgets at the tail of the task” failure mode by construction.
- Same-shape
SpawnerLayerpattern. All intake / inject flows throughmiddleware/sink.rs/middleware/input_inject.rs(bothSpawnerLayerimpls). Same shape asAgentResolver/ProjectNameAliasLayer. - Multi-in / multi-out is the default assumption, even when the current traffic is one or two refs. All handling goes through the sink pattern.
- Zero change to engine core. Only additive Data-plane wiring; the
Domain path (
submit_output/output_tail/ dispatch verdict) stays as it was.
§History
The former standalone mlua-swarm-output-store crate was folded into
engine-core as a module (a Repository/Store sibling to issue_store /
blueprint_store). Independent distribution, separate ownership, and
dependency isolation did not justify the crate boundary. The duplicated
OutputEvent / ContentRef in worker/output.rs were absorbed here
(canonical), and worker/output.rs was narrowed to re-exports plus the
engine-specific OutputSink / EngineSink.
Re-exports§
pub use sqlite::SqliteOutputStore;
Modules§
- sqlite
SqliteOutputStore— SQLite-backedOutputStore.
Structs§
- InMemory
Output Store - MVP implementation — in-memory, and the default for tests and prototyping.
- Output
Record - Metadata for one registered output.
- Output
Ref - Reference handle for a stored output (the id carried by
IN_REFSat LC2).
Enums§
- Content
Ref - How content travels — inline value or file path. Streaming is not carried as its own variant in this iteration.
- Output
Event - A single output event submitted from a worker into the engine.
- Output
Store Error - Errors surfaced by the output store layer.
Traits§
- Output
Store - The LC3 (Swarm management) interface.