# Edge-Site Properties in the Code-Graph-RAG Graph Schema

> Discover edge-site properties in Code-Graph-RAG graph schema. Learn how these metadata dictionaries pinpoint source-code locations for relationship edges. Essential for precise code analysis.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: internals
- Published: 2026-09-06

---

**Edge-site properties in Code-Graph-RAG are metadata dictionaries attached to relationship edges that store the precise source-code location (file, line, column) where a code relationship originates.**

The **Code-Graph-RAG** graph model enriches edges with location-aware metadata, enabling precise traceability from graph relationships back to the exact lines of code that generated them. This article documents the complete set of edge-site properties defined in the schema, their structure, and how they are constructed and consumed across the codebase.

---

## What Are Edge-Site Properties?

In graph terminology, an **edge** represents a relationship between two nodes (e.g., a function calling another function). An **edge-site property** is a dictionary attached to that edge describing *where* in the source code that relationship was observed.

The schema defines these properties using two core types in [`codebase_rag/constants/structural.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/structural.py):

- **`Span`** — A concrete location range with file path, start/end lines, and columns
- **`PropertyDict`** — A flexible string-to-value map that serializes site data into the graph

These types feed into the protobuf `Edge` message defined in [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py), which stores the optional `site` field on every edge.

---

## Complete List of Edge-Site Properties

The Code-Graph-RAG schema defines several specialized site properties for different edge types. Each extends or specializes the base `site` property with domain-specific fields.

### `site` — The Base Property

The foundational edge-site property. Present on any edge that requires location information. Contains at minimum a `Span` serialized as a dictionary.

| Field | Type | Description |
|-------|------|-------------|
| `file` | `str` | Absolute or repository-relative file path |
| `start_line` | `int` | 1-indexed start line |
| `start_col` | `int` | 0-indexed start column |
| `end_line` | `int` | 1-indexed end line |
| `end_col` | `int` | 0-indexed end column |

### `call_site` — For CALLS Edges

Specific to edges where one callable invokes another. Records the exact expression location of the call.

Constructed in [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) when processing call expressions from language-specific parsers. Includes the base `Span` plus optional fields:

- `callee_name` — The resolved name of the called function
- `is_implicit` — Boolean flag for implicit calls (e.g., operator overloading)

### `definition_site` — For DEF and DEF_TYPE Edges

Marks where a symbol is originally defined. Used for function definitions, class definitions, type aliases, and variable declarations.

Populated by the symbol resolver in [`codebase_rag/schema_builder.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/schema_builder.py). Contains:

- Full `Span` of the definition statement
- `symbol_type` — Enum indicating function, class, variable, etc.
- `scope_qualifier` — Namespace or module path for disambiguation

### `import_site` — For IMPORT Edges

Captures details of import statements. Set in [`codebase_rag/editor_links.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/editor_links.py) during import resolution.

Extends base `site` with:

| Field | Description |
|-------|-------------|
| `imported_name` | The raw name being imported |
| `local_alias` | Alias used locally, if any |
| `is_from_import` | Boolean for `from X import Y` vs `import X` |
| `source_module` | Resolved module path of the origin |

### `reference_site` — For REFERENCE Edges

Tracks non-call usages of a symbol—variable reads, attribute access, or type annotations.

Filled in [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) during reference analysis. Contains the `Span` plus `reference_type` to distinguish read vs. write vs. annotation contexts.

### `bind_site` — For BIND Edges

Used where a name is bound to a value: assignments, pattern matching, destructuring, or parameter bindings.

Created in [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) during AST traversal. Records:

- `Span` of the binding expression
- `bind_type` — assignment, parameter, catch clause, etc.
- `is_rebinding` — Boolean if shadowing an existing name

---

## How Edge-Site Properties Are Constructed

The pipeline for adding site metadata follows a consistent pattern across edge types.

### Step 1: Parse Source Location

Language-specific parsers extract raw location data from AST nodes. The `Span` constructor normalizes this into the schema's standard format.

```python
from codebase_rag.constants.structural import Span

def node_to_span(ast_node, file_path: str) -> Span:
    return Span(
        file=file_path,
        start_line=ast_node.lineno,
        start_col=ast_node.col_offset,
        end_line=ast_node.end_lineno,
        end_col=ast_node.end_col_offset,
    )

```

### Step 2: Build Property Dictionary

The `Span` serializes to a plain dictionary for storage in the `PropertyDict` type.

```python
site_data = span.to_dict()  # Returns dict matching PropertyDict schema

```

Specialized edge types add their domain fields to this base dictionary.

### Step 3: Attach to Edge

The `add_edge` helper in [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) accepts the site data and encodes it into the protobuf `Edge` message.

```python
from codebase_rag.graph_loader import add_edge

# Example: creating a CALL edge with full site information

caller_node = ("my_module", "src/services.py", 42)
callee_node = ("utils_module", "src/utils.py", 15)

call_site = Span(
    file="src/services.py",
    start_line=42,
    start_col=8,
    end_line=42,
    end_col=25,
).to_dict()

call_site["callee_name"] = "validate_input"
call_site["is_implicit"] = False

add_edge(
    parent=caller_node,
    child=callee_node,
    rel_type="CALLS",
    site=call_site,
)

```

### Step 4: Persist via Protobuf

The [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py) file defines the wire format. The `Edge` message includes:

```protobuf
message Edge {
  string parent_id = 1;
  string child_id = 2;
  string rel_type = 3;
  optional PropertyDict site = 4;
}

```

Where `PropertyDict` maps to the Python dictionary structure used throughout the loader.

---

## Retrieving and Querying Edge-Site Data

Site properties enable precise code navigation queries. The graph API provides accessors that expose this metadata.

### Basic Site Inspection

```python

# Fetch an edge and inspect its site

edge = graph.get_edge(parent_id, child_id, rel_type="IMPORTS")

if edge.HasField("site"):
    site = edge.site
    print(f"Imported at {site['file']}:{site['start_line']}")
    if "local_alias" in site:
        print(f"  Aliased as: {site['local_alias']}")

```

### Querying by Location

The [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) module uses site properties to implement location-based queries:

```python
def find_edges_in_range(graph, file: str, start_line: int, end_line: int):
    """Return all edges whose site falls within the given line range."""
    results = []
    for edge in graph.edges:
        if not edge.HasField("site"):
            continue
        site = edge.site
        if site["file"] == file and start_line <= site["start_line"] <= end_line:
            results.append(edge)
    return results

```

### Editor Integration

The [`codebase_rag/editor_links.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/editor_links.py) module consumes `import_site` properties to generate IDE-compatible location links, enabling "Go to Import" functionality.

---

## Edge-Site Property Reference Table

| Property | Edge Types | Populated By | Key Additional Fields |
|----------|-----------|--------------|----------------------|
| `site` | Any (generic) | [`graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/graph_loader.py) | `file`, `start_line`, `start_col`, `end_line`, `end_col` |
| `call_site` | `CALLS` | [`graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/graph_loader.py) | `callee_name`, `is_implicit` |
| `definition_site` | `DEF`, `DEF_TYPE` | [`schema_builder.py`](https://github.com/vitali87/code-graph-rag/blob/main/schema_builder.py) | `symbol_type`, `scope_qualifier` |
| `import_site` | `IMPORTS` | [`editor_links.py`](https://github.com/vitali87/code-graph-rag/blob/main/editor_links.py) | `imported_name`, `local_alias`, `is_from_import`, `source_module` |
| `reference_site` | `REFERENCES` | [`graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/graph_updater.py) | `reference_type` (read/write/annotation) |
| `bind_site` | `BINDS` | [`graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/graph_loader.py) | `bind_type`, `is_rebinding` |

---

## Summary

- **Edge-site properties** are `PropertyDict` dictionaries attached to edges, stored in the optional `site` field of the protobuf `Edge` message.
- The base `site` property contains a `Span` with precise file, line, and column information.
- Specialized variants (`call_site`, `definition_site`, `import_site`, `reference_site`, `bind_site`) extend this for specific relationship types.
- Core types are defined in [`codebase_rag/constants/structural.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/structural.py) and encoded via [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py).
- Construction happens in [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) and [`codebase_rag/schema_builder.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/schema_builder.py); consumption in [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) and [`codebase_rag/editor_links.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/editor_links.py).

---

## Frequently Asked Questions

### What is the difference between `site` and `call_site` in Code-Graph-RAG?

The **`site`** property is the generic base container for any location metadata on an edge. **`call_site`** is a specialized variant used exclusively for `CALLS` edges that adds call-specific fields like `callee_name` and `is_implicit`. Internally, `call_site` is stored as the `site` field—the specialization is a semantic convention in the loader code, not a separate protobuf field.

### How does Code-Graph-RAG handle edges without location information?

Edges where location is irrelevant or unavailable simply omit the `site` field. The protobuf definition marks `site` as `optional`, and graph consumers check `HasField("site")` before accessing location data. This design keeps the graph compact for structural relationships like containment hierarchies where source location adds no semantic value.

### Can edge-site properties be updated after initial graph construction?

Yes. The [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) module provides methods to refresh site data when source files change. The updater compares stored `Span` information against re-parsed AST locations and merges changes while preserving edge identity. This incremental update capability is essential for IDE integrations that must stay synchronized with live code edits.