Skip to content
Download for Mac

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.

Every sub-agent call flows through the same path, regardless of the agent’s configuration:

  1. The parent agent calls a sub-agent (e.g., agent_tool:@Web Researcher)
  2. The sub-agent runs — makes tool calls, generates output, streams to the UI
  3. QARK intercepts the full output and writes it to disk
  4. 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 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”

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_file or 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.

Sub-agent output files are stored at:

~/.qark/agent_tool_results/{conversation_id}/{tool_call_id}.md

Each 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:

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.

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.md

The Paper Outliner reads the files from disk using its unix command tool, then produces a structured outline.

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.md
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.md
save_paper_pdf(content_file: "results/final.md", title: "Review Article")
→ ~/Documents/Qark Papers/Review Article.pdf

Throughout 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.

ToolRoleHow it participates
Agent-tools (agent_tool:@Name)Produce filesEvery sub-agent output is automatically saved to disk; parent gets a compact reference
Combine filesAssemble filesReads multiple result files, concatenates them into a single file with optional separators
Save paper PDF (content_file parameter)Consume filesReads the final assembled file from disk and renders it to PDF — no inline content needed

Consider the Review Article Writer pipeline without the File-as-Bus pattern:

StepWords returnedCumulative context
4 research agents~12,60012,600
1 outline~2,00014,600
5 section writers~15,00029,600
1 editor~15,00044,600
1 citation formatter~15,00059,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.

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_files to merge outputs before passing to editing/formatting stages
  • Use save_paper_pdf with content_file for final output — never paste content inline

For structured tool agents (with output schema):

  • Include a summary field 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.