Skip to main content

Relation kinds

A relation is a directed, typed edge between two nodes. It is a frozen dataclass:

from graphlens import Relation, RelationKind

Relation(
source_id="a1b2c3d4e5f6a7b8",
target_id="0011223344556677",
kind=RelationKind.CALLS,
metadata={}, # edge data: mechanism, confidence, boundary_key, ...
)
FieldTypeDescription
source_idstrId of the source node
target_idstrId of the target node
kindRelationKindThe edge type
metadatadict[str, object]Arbitrary edge data

The kinds

KindFrom → ToMeaning
CONTAINSproject → module → file → classStructural containment
DECLARESfile → function, class → methodDeclaration
IMPORTSfile → importAn import statement in a file
RESOLVES_TOimport → module / external symbolWhere an import resolves
CALLSfunction/method → function/methodA resolved call
REFERENCESfile/function → variable/attributeA resolved value reference
INHERITS_FROMclass → classA resolved base class
HAS_TYPEfunction/param/variable → class / externalA type annotation or inference
DEPENDS_ONproject → dependencyA declared package dependency
EXPOSESprovider → boundaryA server exposes a port (e.g. a route handler)
CONSUMESconsumer → boundaryA client consumes a port (e.g. an HTTP call)
COMMUNICATES_WITHconsumer → providerAdded by graphlens-link from matching EXPOSES/CONSUMES

Resolved vs. structural edges

  • Structural edges (CONTAINS, DECLARES, IMPORTS, DEPENDS_ON) come straight from parsing and are always present.
  • Resolved edges (CALLS, REFERENCES, INHERITS_FROM, HAS_TYPE) come from the type-aware resolver. Their completeness depends on the resolver status — on a degraded or unavailable graph some of these will be missing. Check the status (or use --strict) before relying on them.
  • Cross-language edges (EXPOSES, CONSUMES, COMMUNICATES_WITH) connect services through boundaries.

Falling back to external symbols

When a resolved edge's target is not a declaration inside the project — a call into the standard library or a third-party package — the edge points at an EXTERNAL_SYMBOL node instead, which carries metadata["origin"] (stdlib / third_party / internal / unknown). This way a resolved edge is never silently dropped just because its target lives outside your code.

Reading edges in code

from graphlens import RelationKind

# All CALLS edges leaving a node
graph.outgoing(node.id, RelationKind.CALLS)
# All CALLS edges arriving at a node
graph.incoming(node.id, RelationKind.CALLS)

The convenience methods callers, callees, references_to, and neighbors wrap these — see Querying the graph.