# How to Coordinate the Egonex Multi-Agent Pipeline: Project-Scanner, File-Analyzer, and Architecture-Analyzer

> Coordinate the Egonex multi-agent pipeline seamlessy using JSON contracts. Learn how project-scanner, file-analyzer, and architecture-analyzer work together in the .understand-anything directory.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: how-to-guide
- Published: 2026-06-21

---

**The Egonex multi-agent pipeline coordinates three specialized agents through deterministic JSON contracts, where the project-scanner creates an inventory, the file-analyzer processes batched graph fragments, and the architecture-analyzer synthesizes layered architecture by reading and writing specific files in the `.understand-anything` directory.**

The Egonex "Understand-Anything" plugin orchestrates a deterministic three-stage pipeline that transforms raw codebases into layered architecture graphs. To coordinate the **project-scanner**, **file-analyzer**, and **architecture-analyzer** agents effectively, you must understand their strict file-based contracts and the exact JSON schemas they exchange through the repository's `.understand-anything` directory. This guide walks through the precise data flow, authoritative source file paths, and deterministic scripts that bind these agents together.

## Stage 1: Project-Scanner – Creating the Codebase Inventory

The **project-scanner** agent initiates the pipeline by performing a deterministic discovery of the codebase structure, followed by an LLM-driven narrative extraction phase. This agent writes the canonical [`scan-result.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/scan-result.json) file that downstream agents consume.

### Discovery Phase: File Enumeration and Import Mapping

The scanner executes two bundled Node.js scripts in sequence to ensure reproducible results. First, it runs `scan-project.mjs` to enumerate every file, assign deterministic `language` and `fileCategory` values, count lines, and compute `estimatedComplexity` metrics. According to the implementation in [`agents/project-scanner.md`](https://github.com/Egonex-AI/Understand-Anything/blob/main/agents/project-scanner.md), this script writes its output to [`ua-scan-files.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-scan-files.json) in the temporary directory.

Immediately following, the scanner invokes `extract-import-map.mjs` to parse all supported languages using tree-sitter and produce a deterministic import map. This script reads the previous output and writes [`ua-import-map-output.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-import-map-output.json) containing the resolved dependency graph.

### Final Assembly and the Scan-Result Contract

After the deterministic scripts complete, the agent merges the LLM-generated narrative fields (extracted from `README`, [`package.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/package.json), [`pyproject.toml`](https://github.com/Egonex-AI/Understand-Anything/blob/main/pyproject.toml), etc.) with the script outputs to build the final inventory. The resulting JSON is written to `$PROJECT_ROOT/.understand-anything/intermediate/scan-result.json`.

This file must contain:
- **`files`**: An array of file objects with `path`, `language`, `fileCategory`, `sizeLines`, and `estimatedComplexity`
- **`importMap`**: A mapping of file paths to their import targets
- **`name`**, **`rawDescription`**, **`readmeHead`**, **`frameworks`**, and **`languages`**: LLM-extracted metadata

```bash

# Execute the deterministic scanning scripts

node understand-anything-plugin/skills/understand/scan-project.mjs \
  "$PROJECT_ROOT" \
  "$PROJECT_ROOT/.understand-anything/tmp/ua-scan-files.json"

node understand-anything-plugin/skills/understand/extract-import-map.mjs \
  "$PROJECT_ROOT/.understand-anything/tmp/ua-scan-files.json" \
  "$PROJECT_ROOT/.understand-anything/tmp/ua-import-map-output.json"

```

## Stage 2: File-Analyzer – Processing Batched Graph Fragments

The **file-analyzer** agent consumes [`scan-result.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/scan-result.json) and processes the `files` array in batches to generate graph fragments containing nodes and edges. This agent must ensure every file from the scanner appears in exactly one batch and every import listed in the `importMap` is emitted as an edge.

### Structural Extraction with extract-structure.mjs

For each batch, the analyzer writes a temporary input JSON (`ua-file-analyzer-input-<batchIndex>.json`) containing the `path`, `language`, `sizeLines`, and `fileCategory` for files in that batch, along with the relevant slice of the `importMap`. It then executes the bundled `extract-structure.mjs` script as specified in [`agents/file-analyzer.md`](https://github.com/Egonex-AI/Understand-Anything/blob/main/agents/file-analyzer.md).

This script performs static analysis to extract functions, classes, and structural metrics, writing results to `ua-file-extract-results-<batchIndex>.json`.

### Semantic Analysis and Mandatory Edge Emission

Following structural extraction, the agent creates Graph Node objects for each file, function, class, and configuration element. **Crucially**, it must emit an `imports` edge for **every** entry in `batchImportData[filePath]` as defined in the contract. The resulting fragment is validated to ensure no duplicate node IDs exist and all imports are represented.

The final batch fragments are written to `.understand-anything/intermediate/batch-<batchIndex>.json` (or split into `batch-<batchIndex>-part-<k>.json` files if the fragment exceeds size limits).

### Batch Processing Orchestration

A typical orchestrator chunks the file list into batches of 60 or fewer files to manage memory and processing constraints:

```javascript
// run-file-analyzer.js
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

const batchIdx = process.argv[2];
const batchFiles = JSON.parse(fs.readFileSync(process.argv[3], 'utf8'));
const importMap = JSON.parse(fs.readFileSync(process.argv[4], 'utf8'));

const tmpDir = path.resolve('.understand-anything/tmp');
const interDir = path.resolve('.understand-anything/intermediate');

// Build input for extract-structure.mjs
const input = {
  projectRoot: process.cwd(),
  batchFiles,
  batchImportData: importMap
};

const inputPath = `${tmpDir}/ua-file-analyzer-input-${batchIdx}.json`;
fs.writeFileSync(inputPath, JSON.stringify(input, null, 2));

// Execute structural extraction
execSync(`node understand-anything-plugin/skills/understand/extract-structure.mjs \
  ${inputPath} \
  ${tmpDir}/ua-file-extract-results-${batchIdx}.json`, { stdio: 'inherit' });

// Convert to graph fragment (simplified)
const results = JSON.parse(fs.readFileSync(`${tmpDir}/ua-file-extract-results-${batchIdx}.json`));
const fragment = {
  nodes: results.results.map(r => ({
    id: `file:${r.path}`,
    type: 'file',
    name: path.basename(r.path),
    filePath: r.path,
    complexity: r.metrics?.functionCount > 5 ? 'complex' : 'simple'
  })),
  edges: [] // Populate with imports from batchImportData
};

fs.writeFileSync(`${interDir}/batch-${batchIdx}.json`, JSON.stringify(fragment, null, 2));

```

## Stage 3: Architecture-Analyzer – Synthesizing Layered Architecture

The **architecture-analyzer** consumes the merged knowledge graph (produced by stitching all batch fragments together) and runs a deterministic analysis script to compute structural patterns and assign files to architectural layers.

### Input Preparation and Deterministic Analysis

The agent prepares [`ua-arch-input.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-arch-input.json) containing three top-level arrays: `fileNodes`, `importEdges`, and `allEdges`. It then executes the [`ua-arch-analyze.js`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-arch-analyze.js) script, which computes:
- **`directoryGroups`**: Files grouped by top-level folder
- **`nodeTypeGroups`**: Categorization of code vs. config vs. documents
- **`crossCategoryEdges`**: Dependencies between different file types
- **`interGroupImports`** and **`intraGroupDensity`**: Connectivity metrics
- **`patternMatches`**: Recognized architectural patterns (e.g., `routes → api`, `services → service`)

```bash

# Prepare merged graph (conceptual merge step)

jq -s 'add' .understand-anything/intermediate/batch-*.json > .understand-anything/tmp/merged-graph.json

# Build architecture input

jq -n \
  --argfile nodes .understand-anything/tmp/merged-graph.json \
  '{fileNodes: $nodes.nodes, importEdges: $nodes.edges, allEdges: $nodes.edges}' \
  > .understand-anything/tmp/ua-arch-input.json

# Run deterministic analysis

node understand-anything-plugin/agents/architecture-analyzer.mjs \
  .understand-anything/tmp/ua-arch-input.json \
  .understand-anything/intermediate/layers.json

```

### Layer Selection and Node Assignment

Based on the analysis results, the agent selects **3-10 layers** using specific heuristics:
- **Pattern matches** provide strong signals for layer names
- **Intra-group density** exceeding 0.3 indicates a distinct layer boundary
- **Dependency direction** identifies foundation layers (high inbound edge count)
- **Non-code signals** map `Dockerfile` to `infrastructure` and CI configs to `ci-cd`

Every file node from the input must be assigned to exactly one layer's `nodeIds` array. The agent validates that the total count matches the input `fileStats.totalFileNodes` before writing the final output.

### Final Output Contract

The analyzer writes a JSON array to [`.understand-anything/intermediate/layers.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/.understand-anything/intermediate/layers.json), where each layer object contains:
- **`id`**: Unique identifier (e.g., `layer:api`)
- **`name`**: Human-readable layer name
- **`description`**: Contextual explanation of the layer's purpose
- **`nodeIds`**: Array of file and service identifiers belonging to this layer

```json
[
  {
    "id": "layer:api",
    "name": "API Layer",
    "description": "HTTP route handlers that expose the public REST endpoints.",
    "nodeIds": [
      "file:src/routes/index.ts",
      "file:src/controllers/auth.ts"
    ]
  },
  {
    "id": "layer:infrastructure",
    "name": "Infrastructure",
    "description": "Dockerfile, compose file and CI pipelines that build and deploy the service.",
    "nodeIds": [
      "service:Dockerfile",
      "pipeline:.github/workflows/ci.yml"
    ]
  }
]

```

## End-to-End Data Flow and Contract Boundaries

The pipeline follows a strict linear progression where each agent's output becomes the next agent's input:

1. **Project-Scanner** writes [`scan-result.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/scan-result.json) containing the complete file inventory and import map
2. **File-Analyzer** reads [`scan-result.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/scan-result.json), processes batches, and writes `batch-<N>.json` fragments
3. **Merge Script** (typically [`merge-batch-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-batch-graphs.py) or equivalent) consolidates fragments into a unified graph
4. **Architecture-Analyzer** reads the merged graph, runs [`ua-arch-analyze.js`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-arch-analyze.js), and writes [`layers.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/layers.json)

This separation of concerns ensures **determinism**: the bundled scripts (`scan-project.mjs`, `extract-import-map.mjs`, `extract-structure.mjs`, and [`ua-arch-analyze.js`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-arch-analyze.js)) guarantee identical outputs on every execution, which is required for reproducible graph construction. Never re-implement the file walking, language detection, or import resolution logic, as downstream agents rely on the exact JSON payload shapes produced by these canonical scripts.

## Summary

- **Project-Scanner** builds the deterministic inventory using `scan-project.mjs` and `extract-import-map.mjs`, outputting [`scan-result.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/scan-result.json) with narrative metadata and file statistics.
- **File-Analyzer** processes the inventory in batches via `extract-structure.mjs`, emitting complete graph fragments with all import edges preserved in `batch-<N>.json` files.
- **Architecture-Analyzer** consumes the merged graph, executes [`ua-arch-analyze.js`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-arch-analyze.js) to compute structural patterns, and produces [`layers.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/layers.json) containing 3-10 validated architectural layers.
- **Contract Compliance** requires adhering to specific file paths, JSON schemas, and edge emission rules to ensure pipeline reliability.

## Frequently Asked Questions

### How do the agents communicate if they run in separate processes?

The Egonex multi-agent pipeline uses **file-based communication** exclusively through the `.understand-anything` directory. Each agent writes JSON files to specific subdirectories (`tmp/` for intermediate files, `intermediate/` for stage outputs) that subsequent agents read as input. This design ensures process isolation and provides an audit trail of the pipeline state at every stage.

### What happens if a file from the scanner doesn't appear in the analyzer output?

The **file-analyzer** contract requires that every file listed in [`scan-result.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/scan-result.json) must appear in exactly one batch fragment. If a file is missing, the downstream `merge-batch-graphs` script will detect the discrepancy when validating against `fileStats.totalFileNodes`, and the architecture-analyzer will fail to assign the node to a layer. Always verify that your batch processing logic handles the complete file list without omission.

### Can I modify the layer selection logic in the architecture-analyzer?

While you can adjust the heuristic thresholds (such as the 0.3 intra-group density threshold) in your implementation of the agent logic, you must not modify the deterministic [`ua-arch-analyze.js`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ua-arch-analyze.js) script itself. The script computes the structural metrics (directory groups, cross-category edges, pattern matches) that feed into the layer selection algorithm. Modify the selection logic that runs after the script execution, but ensure the final [`layers.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/layers.json) still assigns every file node to exactly one layer and maintains the required JSON schema.

### Why must imports be emitted as edges in every batch?

The **file-analyzer** must emit an `imports` edge for every entry in `batchImportData[filePath]` because the downstream architecture-analyzer relies on the complete dependency graph to calculate `crossCategoryEdges` and identify foundation layers. Missing import edges would cause the density calculations and layer boundary detection to fail, resulting in an incorrect architectural view that doesn't reflect actual code dependencies.