Design philosophy source: Deepak Babu Piskala, From Everything-is-a-File to Files-Are-All-You-Need: How Unix Philosophy Informs the Design of Agentic AI Systems (arXiv:2601.11672, 2026-01-16).
The ICM runner is file-native in the sense that each stage writes an output file and the next stage reads that file back from disk.
icm_agent/run_icm.py:168-229indo_ingest(repo_url, output_path)buildsadr-icm-workspace/stages/01_ingest/output/repo-data.mdfrom git history, file tree, commit counts, and README text.icm_agent/run_icm.py:312-383inparse_judge_scores(eval_text)parses the judge report from the file contents, not from live Python objects.icm_agent/run_icm.py:405-540inmain()defines the stage chain:01_ingest→repo-data.md02_analysis→decision-points.md03_rationale→inferred-rationale.md04_synthesis→ADR-generated.md05_judge→evaluation.mdandbenchmark.json06_content→social-posts.md
icm_agent/run_icm.py:256-290inrun_stage()writes each stage’s output file underadr-icm-workspace/stages/<stage>/output/.icm_agent/run_icm.py:94-139inload_stage_context(stage_num)reconstructs prompt context by reading the current stage’sCONTEXT.md, itsreferences/*.md, shared repo conventions, and all prior stage output files.icm_agent/run_icm.py:516-532readsevaluation.mdonly afterrun_stage()for stage 05 returns.run_stage()itself writes the stage output viaout_path.write_text(...)before returning, so I do not see an intra-process race where stage 06 or the summary parser reads a file before stage 05 has flushed it. The file handoff is synchronous in this implementation.
So yes: each stage reads from and writes to actual files on disk. The stage boundaries are file boundaries.
Important nuance: the pipeline still uses an in-memory benchmark dict and in-memory return values for token/latency bookkeeping in main() (icm_agent/run_icm.py:421-543). So the design is file-mediated, but not purely file-only.
The LangGraph design in agent/ is different.
agent/src/agents/orchestrator.py:28-31says the LangGraph file is architectural documentation and that the actual pipeline is driven by the TUI worker thread insrc/tui/app.py.agent/src/agents/orchestrator.py:96-159builds aStateGraph(ADRState)with nodes for ingest, analysis/structure, rationale, synthesis, and quality checking.agent/src/tui/app.py:358-520initializesstate: ADRState = {"repo_url": self.repo_url}and then passes that same Python object throughingest_agent,analysis_agentorstructure_node,rationale_agent,synthesis_node, andquality_checker_node.agent/src/agents/quality_checker.py:67-151mutatesstatein place, updatesstate["quality_score"],state["evaluation_scores"], and writes ADR files todocs/adr/.
I found no checkpointing layer or persistence backend in the repo for this flow. There is no checkpointer, MemorySaver, or similar runtime persistence in the current code path. The practical behavior is in-memory graph state inside a single process, with file output only at the ADR-writing step.
The ICM runner reduces token use mainly by limiting what each stage serializes into its prompt, not by avoiding prompt reserialization entirely.
icm_agent/run_icm.py:94-139reads only the current stage’s config plus prior stage output files.icm_agent/run_icm.py:114-118truncates each previous output file withMAX_CHARS_PER_PART, defaulting to6000chars (icm_agent/run_icm.py:22-23).icm_agent/run_icm.py:120-139concatenates those files into one stage prompt.
That means the prompt grows by stage, but each prior file is capped. Roughly:
- Stage 04 synthesis can ingest up to three earlier output files, each truncated to 6,000 chars, so about 18 KB of prior stage output plus shared context.
- Stage 05 judge can ingest stage 04 output in addition to the earlier files.
- Stage 06 content can ingest stage 04 and 05 outputs.
So the savings come from:
- Reading only the stage-relevant files.
- Truncating prior outputs.
- Avoiding repeated live state objects that accumulate everything in memory.
That said, it is not a strict “one file in, one file out, no accumulation” model. load_stage_context() re-serializes the accumulated prior outputs into the next prompt, so the context still becomes cumulative across stages.
The ICM design is close to file-native, but not perfectly so.
- The driver still keeps control flow in Python, not in the filesystem itself (
icm_agent/run_icm.py:405-543). benchmark,stage_token_estimates, andstage_latency_secondsstay in memory until written at the end (icm_agent/run_icm.py:421-543).- Stage instructions are embedded as Python string literals in
main()rather than being fully externalized to files (icm_agent/run_icm.py:431-513). - The judge/content stages still re-serialize earlier stage outputs into prompt strings in memory; the filesystem is the source of truth, but the model still receives concatenated text, not literal file descriptors.
agent/is even less file-native at runtime: state is passed as an in-memoryADRStatedict through node calls (agent/src/tui/app.py:358-520), even though nodes often write side-effect files underdocs/adr/.
If the paper’s philosophy is “make files the primary interface for agent context and artifacts,” then icm_agent instantiates that reasonably well: stage handoffs happen through files, outputs are persisted stage-by-stage, and prompt context is reconstructed from disk.
Compared with agent/, which primarily passes a mutable in-memory state object between nodes, icm_agent is more file-native and more auditable. But it still uses Python orchestration and cumulative prompt assembly, so it is file-mediated rather than purely file-only.