# How Graphify Modules Communicate: The Dispatch-Based Architecture

> Discover how Graphify modules communicate using a three-layer dispatch system. Learn how the knowledge graph enables modules to publish dispatch tables and map symbols to handlers.

- Repository: [Graphify Labs/graphify](https://github.com/Graphify-Labs/graphify)
- Tags: internals
- Published: 2026-07-16

---

**Graphify modules communicate through a three-layer dispatch system embedded in the knowledge graph, where modules publish dispatch tables mapping symbols to handlers rather than calling code directly.**

Graphify is an open-source knowledge graph generator that enables loose coupling between modules through symbolic dispatch. Unlike traditional direct function calls, Graphify modules communicate by dispatching requests through a centralized graph structure. This architecture allows modules to remain independent while sharing data through symbolic references rather than hard-coded dependencies.

## The Three-Layer Dispatch Architecture

The dispatch mechanism operates across three distinct layers that translate symbolic requests into concrete handler execution.

### Direct Dispatch with @dispatch Annotations

The first layer uses literal `@dispatch` annotations embedded in generated markdown blocks. When you run `graphify install`, the system inserts these blocks into skill documentation, creating explicit pointers to handler files.

According to the Graphify source code in [`README.md`](https://github.com/Graphify-Labs/graphify/blob/main/README.md) (lines 294-298), these dispatch slots allow platforms to insert their own handler references:

```markdown
<!-- @@DISPATCH@@ -->
@dispatch: my_handler.md

```

### Indirect Dispatch via AST Inference

The second layer infers dispatch relationships automatically during source code extraction. When the AST parser encounters imports, calls, or assignments that reference dispatchable symbols, it creates inferred edges in the graph.

The test suite in [`tests/test_indirect_dispatch.py`](https://github.com/Graphify-Labs/graphify/blob/main/tests/test_indirect_dispatch.py) (lines 46-86) validates that any import, call, or assignment generating a "dispatchable" symbol automatically creates an `INFERRED` edge of type **dispatch** in the global graph. This allows modules to follow edges to handlers without hard-coded imports.

### Runtime Watch Dispatch

The third layer handles dynamic updates through the watch subsystem. Implemented in [`graphify/watch.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/watch.py), the `Watch` class monitors file system events and triggers partial re-extraction by looking up dispatch entries for changed files. When `graphify watch <path>` detects a change, the system resolves the affected dispatch entry and runs only the relevant extractor, avoiding full rebuilds.

## Core Components of the Dispatch System

### Dispatch Tables

Each skill file maintains a dispatch table—a dictionary (`dispatch: str | None`) mapping logical names to markdown fragments containing handler code. This structure acts as the contract between modules, enforced by the graph-builder during extraction.

### Indirect Dispatch Edges

During extraction, the graph builder adds edges of type **dispatch** between symbols. These edges, created in [`graphify/symbol_resolution.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/symbol_resolution.py), allow the assistant to follow connections from request to implementation without hard-coded imports. A module only needs to know the *name* of the data it wants, not the concrete implementation.

### Watch-Based Dispatch

The `Watch` service enables incremental graph updates. When `graphify watch <path>` detects a file change, it resolves the file's dispatch entry and triggers a *partial* extraction so the graph stays up-to-date without a full rebuild.

## Code Examples in Practice

### Example 1: Registering a Dispatch Entry

Generated by `graphify install`, these markdown blocks create explicit dispatch registrations:

```markdown
<!-- @@DISPATCH@@ -->
@dispatch: my_handler.md

```

### Example 2: Indirect Dispatch in Python

When the extractor processes this code, it automatically creates dispatch edges:

```python

# In module A

def do_work():
    return helper.process(data)   # `helper.process` becomes a dispatch edge

# In module B (the handler)

def process(data):
    # Actual implementation

    return data.processed

```

The extractor adds an edge `A.do_work → B.process` of type **dispatch**; any query requesting `do_work` automatically follows this edge to the implementation.

### Example 3: Watching Directories and Dispatching on Change

```python
from graphify.watch import Watch

watcher = Watch(path="src/")
watcher.start()   # On every file change, the watcher looks up its dispatch entry

```

When [`src/utils.py`](https://github.com/Graphify-Labs/graphify/blob/main/src/utils.py) changes, the watch service finds the corresponding dispatch fragment (e.g., [`utils_extractor.md`](https://github.com/Graphify-Labs/graphify/blob/main/utils_extractor.md)) and runs only that extractor, updating the graph incrementally.

## Key Implementation Files

- **[`graphify/symbol_resolution.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/symbol_resolution.py)**: Contains the logic that resolves symbols to dispatch entries and builds `dispatch → handler` edges.
- **[`graphify/watch.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/watch.py)**: Implements the `Watch` class for file system monitoring and runtime dispatch triggering.
- **[`tests/test_indirect_dispatch.py`](https://github.com/Graphify-Labs/graphify/blob/main/tests/test_indirect_dispatch.py)**: Validates that indirect dispatch edges are correctly inferred from Python AST (lines 46-86).
- **[`README.md`](https://github.com/Graphify-Labs/graphify/blob/main/README.md)**: Documents the dispatch slot syntax and platform-specific implementations (lines 294-298).

## Summary

- Graphify modules communicate through **dispatch tables** rather than direct function calls, enabling loose coupling between components.
- The system supports **three dispatch layers**: direct annotation (`@dispatch`), AST-inferred edges, and runtime file watching.
- **Indirect dispatch edges** are created automatically during extraction and validated in [`tests/test_indirect_dispatch.py`](https://github.com/Graphify-Labs/graphify/blob/main/tests/test_indirect_dispatch.py).
- The **`Watch` class** in [`graphify/watch.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/watch.py) enables incremental updates by resolving dispatch entries for changed files.
- **[`graphify/symbol_resolution.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/symbol_resolution.py)** handles the core symbol-to-handler resolution logic that makes the graph queryable.

## Frequently Asked Questions

### What is the difference between direct and indirect dispatch in Graphify?

Direct dispatch uses explicit `@dispatch` annotations in markdown blocks generated by `graphify install`, while indirect dispatch is automatically inferred from the AST during extraction. Indirect dispatch creates edges in the knowledge graph when code references symbols that have associated handlers, allowing the system to route requests without explicit registration.

### How does the watch subsystem trigger module updates?

The watch subsystem, implemented in the `Watch` class in [`graphify/watch.py`](https://github.com/Graphify-Labs/graphify/blob/main/graphify/watch.py), monitors file system events for directories specified in `graphify watch <path>`. When a file changes, the system looks up the file's dispatch entry in the graph and triggers only the relevant extractor, enabling incremental graph updates without full rebuilds.

### Where are dispatch edges stored in the Graphify knowledge graph?

Dispatch edges are stored as `INFERRED` edges of type **dispatch** in the global knowledge graph. These edges map symbols (function names, class names, file paths) to their handlers, and are created during AST extraction as validated in [`tests/test_indirect_dispatch.py`](https://github.com/Graphify-Labs/graphify/blob/main/tests/test_indirect_dispatch.py).

### How can I register a custom dispatch handler for my Graphify skill?

Register a custom handler by including a dispatch annotation in your skill's markdown documentation. When running `graphify install`, the system inserts `<!-- @@DISPATCH@@ -->` blocks containing `@dispatch: handler_file.md` pointers. These entries populate the dispatch table that other modules query when requesting your skill's data.