The File-as-Bus Pattern
When a parent agent calls a sub-agent, the sub-agent’s full output can be thousands of words — a research report, a paper section, an entire analysis. Injecting all of that back into the parent’s context window wastes tokens and pushes out earlier context that the parent needs for planning.
QARK solves this with the File-as-Bus pattern: the filesystem acts as a shared message bus between agents. Sub-agent outputs are automatically saved to disk, and the parent receives a compact reference with just enough information to route the next step.
How it works
Section titled “How it works”Every sub-agent call flows through the same path, regardless of the agent’s configuration:
- The parent agent calls a sub-agent (e.g.,
agent_tool:@Web Researcher) - The sub-agent runs — makes tool calls, generates output, streams to the UI
- QARK intercepts the full output and writes it to disk
- The parent receives a compact JSON reference instead of the full text
Parent calls agent_tool:@Web Researcher ↓Web Researcher runs, produces 3,000 words ↓QARK saves to: ~/.qark/agent_tool_results/{conversation_id}/{tool_call_id}.md ↓Parent receives:{ "agent": "web_researcher", "result_file": "/path/to/abc123.md", "word_count": 3200, "preview": "The study found that transformer architectures..."}The parent never sees the 3,000 words. It sees a file path, a word count, and a preview. The UI still displays the full output — only the parent’s context window is protected.
The preview field
Section titled “The preview field”The preview gives the parent enough context to make routing decisions without reading the full file. QARK extracts previews using two strategies:
Structured output agents (agents with an output schema) — QARK uses the summary field. If the agent’s output schema doesn’t include a summary field, QARK auto-injects one at build time. The LLM is required to produce a concise summary as part of its structured response. This gives the sub-agent control over what the parent sees.
Unstructured output agents (agents that return free-form markdown) — QARK extracts the first non-heading paragraph from the output, capped at 500 characters on a word boundary. This is far more informative than a blind character truncation, since markdown documents typically start with a heading followed by an introductory paragraph that summarizes the content.
The parent uses this preview to decide:
- Which file to pass to which sub-agent — “This file covers benchmarks, send it to the Performance section writer”
- Whether to dispatch another agent — “The preview shows sufficient coverage, no need for another search”
- How to frame the next prompt — “Based on the preview, emphasize the statistical methods”
Transparent by design
Section titled “Transparent by design”Neither the parent nor the sub-agent is aware of the file mechanism:
- Sub-agents produce their output normally. They don’t call
save_to_fileor format anything specially. The interception happens in the infrastructure layer after the sub-agent completes. - Parent agents receive a consistent JSON shape for every sub-agent call. They route file paths to downstream agents, which read the files using their own tools (unix commands, combine files, etc.).
- The contract is uniform — every sub-agent call, structured or unstructured, returns
{ agent, result_file, word_count, preview }. No conditionals, no branching logic.
This is critical. If some agents saved to files and others returned inline text, every downstream consumer would need branching logic to handle both cases. The unconditional design keeps the system simple.
File lifecycle
Section titled “File lifecycle”Sub-agent output files are stored at:
~/.qark/agent_tool_results/{conversation_id}/{tool_call_id}.mdEach file is:
- Immutable — once written, the file is never modified. If the sub-agent is called again, a new file is created with a new tool call ID.
- Conversation-scoped — files are grouped by conversation, making cleanup straightforward.
- Inspectable — you can read these files directly to audit what any sub-agent produced.
Real-world pipeline: Review Article Writer
Section titled “Real-world pipeline: Review Article Writer”The Review Article Writer demonstrates the full pattern across 7 sub-agents:
Phase 1: Research
Section titled “Phase 1: Research”The orchestrator dispatches research agents in parallel. Each saves its output to disk.
agent_tool:@Source Deep Diver → results/aaa.md (3,200 words)agent_tool:@Web Researcher → results/bbb.md (2,800 words)agent_tool:@Web Researcher → results/ccc.md (2,500 words)agent_tool:@Academic Researcher → results/ddd.md (4,100 words)The parent sees 4 compact references (~200 tokens total) instead of 12,600 words of research.
Phase 2: Outline
Section titled “Phase 2: Outline”The parent passes the research file paths to the outliner:
agent_tool:@Paper Outliner( source_files: ["results/aaa.md", "results/bbb.md", "results/ccc.md", "results/ddd.md"])→ results/outline.mdThe Paper Outliner reads the files from disk using its unix command tool, then produces a structured outline.
Phase 3: Section writing
Section titled “Phase 3: Section writing”The parent dispatches section writers, each receiving the outline and relevant research files:
agent_tool:@Section Writer(outline: "results/outline.md", sources: ["results/aaa.md", "results/bbb.md"])→ results/section_1.md
agent_tool:@Section Writer(outline: "results/outline.md", sources: ["results/ccc.md", "results/ddd.md"])→ results/section_2.mdPhase 4: Assembly and polish
Section titled “Phase 4: Assembly and polish”combine_files(paths: ["results/section_1.md", "results/section_2.md", ...])→ combined_paper.md
agent_tool:@Paper Editor(file: "combined_paper.md")→ results/edited.md
agent_tool:@Citation Formatter(file: "results/edited.md")→ results/final.mdPhase 5: PDF
Section titled “Phase 5: PDF”save_paper_pdf(content_file: "results/final.md", title: "Review Article")→ ~/Documents/Qark Papers/Review Article.pdfThroughout this entire pipeline, the parent orchestrator’s context window held only compact references — never the full text of any section, research finding, or draft. The heavy content lived on disk, read only by the agents that needed it.
Three tools that enable the pattern
Section titled “Three tools that enable the pattern”| Tool | Role | How it participates |
|---|---|---|
Agent-tools (agent_tool:@Name) | Produce files | Every sub-agent output is automatically saved to disk; parent gets a compact reference |
| Combine files | Assemble files | Reads multiple result files, concatenates them into a single file with optional separators |
Save paper PDF (content_file parameter) | Consume files | Reads the final assembled file from disk and renders it to PDF — no inline content needed |
Context window math
Section titled “Context window math”Consider the Review Article Writer pipeline without the File-as-Bus pattern:
| Step | Words returned | Cumulative context |
|---|---|---|
| 4 research agents | ~12,600 | 12,600 |
| 1 outline | ~2,000 | 14,600 |
| 5 section writers | ~15,000 | 29,600 |
| 1 editor | ~15,000 | 44,600 |
| 1 citation formatter | ~15,000 | 59,600 |
That’s ~60,000 words (~80,000 tokens) in the parent’s context — well beyond most model limits. Many of these tokens would be evicted by auto-compaction, losing information the parent needs.
With the File-as-Bus pattern, the parent’s context holds ~14 compact references at ~50 tokens each = ~700 tokens. The difference is two orders of magnitude.
Designing agents for this pattern
Section titled “Designing agents for this pattern”When creating orchestrator and tool agents that participate in file-based pipelines:
For orchestrators:
- Reference file paths from sub-agent results when calling the next sub-agent
- Use
combine_filesto merge outputs before passing to editing/formatting stages - Use
save_paper_pdfwithcontent_filefor final output — never paste content inline
For structured tool agents (with output schema):
- Include a
summaryfield in the output schema. Write a clear description like “A concise 2-3 sentence summary of your key findings and conclusions.” If you omit it, QARK auto-injects one. - The summary should be informative enough for the parent to make routing decisions without reading the full file.
For unstructured tool agents (free-form output):
- Start with a clear introductory paragraph that summarizes the content. QARK extracts this as the preview.
- Avoid starting with headings, metadata blocks, or boilerplate — the first substantive paragraph is what the parent sees.