Documentation
¶
Overview ¶
Package graph provides a thread-safe, ordered directed/undirected graph built on top of ConcurrentOrderedMap. Each node can carry an arbitrary payload and an optional embedding vector, enabling graph traversal combined with semantic vector search — ideal for knowledge graphs, agentic memory systems, and RAG pipelines.
Index ¶
- Variables
- type ConcurrentOrderedGraph
- func (g *ConcurrentOrderedGraph[K, V]) AddEdge(from, to K, e EdgeData) error
- func (g *ConcurrentOrderedGraph[K, V]) AddNode(id K, data V, vec []float64) error
- func (g *ConcurrentOrderedGraph[K, V]) AllReachable(start K) ([]K, error)
- func (g *ConcurrentOrderedGraph[K, V]) BFS(start K, visit func(K, V) bool) error
- func (g *ConcurrentOrderedGraph[K, V]) BFSWithDepth(start K, maxDepth int, visit func(id K, data V, depth int) bool) error
- func (g *ConcurrentOrderedGraph[K, V]) ConnectedComponents() [][]K
- func (g *ConcurrentOrderedGraph[K, V]) DFS(start K, visit func(K, V) bool) error
- func (g *ConcurrentOrderedGraph[K, V]) GetNeighbors(id K) ([]K, error)
- func (g *ConcurrentOrderedGraph[K, V]) GetNode(id K) (*GraphNode[K, V], bool)
- func (g *ConcurrentOrderedGraph[K, V]) HasEdge(from, to K) bool
- func (g *ConcurrentOrderedGraph[K, V]) IsDirected() bool
- func (g *ConcurrentOrderedGraph[K, V]) NodeCount() int
- func (g *ConcurrentOrderedGraph[K, V]) Nodes() []*GraphNode[K, V]
- func (g *ConcurrentOrderedGraph[K, V]) RemoveEdge(from, to K) error
- func (g *ConcurrentOrderedGraph[K, V]) RemoveNode(id K) error
- func (g *ConcurrentOrderedGraph[K, V]) SemanticNeighbors(nodeID K, queryVec []float64, topK int) ([]ScoredNode[K, V], error)
- func (g *ConcurrentOrderedGraph[K, V]) ShortestPath(from, to K) (PathResult[K], error)
- func (g *ConcurrentOrderedGraph[K, V]) UpsertNode(id K, data V, vec []float64)
- func (g *ConcurrentOrderedGraph[K, V]) VectorSearchBidirectional(start K, queryVec []float64, topK int, maxHops int, filter func(V) bool) ([]ScoredNode[K, V], error)
- func (g *ConcurrentOrderedGraph[K, V]) VectorSearchFromNode(start K, queryVec []float64, topK int, maxHops int, filter func(V) bool) ([]ScoredNode[K, V], error)
- func (g *ConcurrentOrderedGraph[K, V]) VectorSearchGlobal(queryVec []float64, topK int, filter func(V) bool) ([]ScoredNode[K, V], error)
- type EdgeData
- type GraphNode
- type PathResult
- type ScoredNode
Constants ¶
This section is empty.
Variables ¶
var ErrDuplicateNode = errors.New("graph: node already exists")
ErrDuplicateNode is returned when a node already exists.
var ErrEdgeNotFound = errors.New("graph: edge not found")
ErrEdgeNotFound is returned when an operation references a missing edge.
var ErrNodeNotFound = errors.New("graph: node not found")
ErrNodeNotFound is returned when an operation references a missing node.
var ErrSelfLoop = errors.New("graph: self-loop not allowed")
ErrSelfLoop is returned when a caller tries to add a self-loop.
Functions ¶
This section is empty.
Types ¶
type ConcurrentOrderedGraph ¶
type ConcurrentOrderedGraph[K comparable, V any] struct { // contains filtered or unexported fields }
ConcurrentOrderedGraph is a thread-safe directed or undirected graph whose node-set is backed by a ConcurrentOrderedMap, preserving insertion order for deterministic iteration.
Each node may hold an embedding vector ([]float64) enabling hybrid graph-traversal + semantic-search queries — the core primitive needed for agentic knowledge graphs and memory systems.
Type parameters:
- K: node identifier type (must be comparable, e.g. string, int, uuid)
- V: arbitrary payload stored in each node
func NewDirectedGraph ¶
func NewDirectedGraph[K comparable, V any]() *ConcurrentOrderedGraph[K, V]
NewDirectedGraph creates an empty directed graph.
func NewUndirectedGraph ¶
func NewUndirectedGraph[K comparable, V any]() *ConcurrentOrderedGraph[K, V]
NewUndirectedGraph creates an empty undirected graph. Every AddEdge call automatically creates the reverse edge.
func (*ConcurrentOrderedGraph[K, V]) AddEdge ¶
func (g *ConcurrentOrderedGraph[K, V]) AddEdge(from, to K, e EdgeData) error
AddEdge adds a directed edge from → to. For undirected graphs the reverse edge is also added automatically. Returns ErrSelfLoop or ErrNodeNotFound as appropriate.
func (*ConcurrentOrderedGraph[K, V]) AddNode ¶
func (g *ConcurrentOrderedGraph[K, V]) AddNode(id K, data V, vec []float64) error
AddNode inserts a new node. vec may be nil if no embedding is needed. Returns ErrDuplicateNode if the key already exists.
func (*ConcurrentOrderedGraph[K, V]) AllReachable ¶
func (g *ConcurrentOrderedGraph[K, V]) AllReachable(start K) ([]K, error)
AllReachable returns every node reachable from `start` (BFS order).
func (*ConcurrentOrderedGraph[K, V]) BFS ¶
func (g *ConcurrentOrderedGraph[K, V]) BFS(start K, visit func(K, V) bool) error
BFS performs a breadth-first traversal starting from `start`. The visitor function receives (nodeID, nodeData) for every reachable node. Return false from the visitor to stop traversal early.
func (*ConcurrentOrderedGraph[K, V]) BFSWithDepth ¶
func (g *ConcurrentOrderedGraph[K, V]) BFSWithDepth( start K, maxDepth int, visit func(id K, data V, depth int) bool, ) error
BFSWithDepth is BFS with hop-depth limit. Useful for bounded graph exploration in agentic scenarios where you want "context within N hops".
func (*ConcurrentOrderedGraph[K, V]) ConnectedComponents ¶
func (g *ConcurrentOrderedGraph[K, V]) ConnectedComponents() [][]K
ConnectedComponents returns groups of mutually-reachable node IDs. Useful for detecting isolated sub-graphs in an agent's knowledge base.
func (*ConcurrentOrderedGraph[K, V]) DFS ¶
func (g *ConcurrentOrderedGraph[K, V]) DFS(start K, visit func(K, V) bool) error
DFS performs a depth-first traversal starting from `start`. The visitor function receives (nodeID, nodeData). Return false to stop early.
func (*ConcurrentOrderedGraph[K, V]) GetNeighbors ¶
func (g *ConcurrentOrderedGraph[K, V]) GetNeighbors(id K) ([]K, error)
GetNeighbors returns the outgoing neighbour IDs of a node in insertion order.
func (*ConcurrentOrderedGraph[K, V]) GetNode ¶
func (g *ConcurrentOrderedGraph[K, V]) GetNode(id K) (*GraphNode[K, V], bool)
GetNode retrieves a node by ID.
func (*ConcurrentOrderedGraph[K, V]) HasEdge ¶
func (g *ConcurrentOrderedGraph[K, V]) HasEdge(from, to K) bool
HasEdge reports whether an edge from → to exists.
func (*ConcurrentOrderedGraph[K, V]) IsDirected ¶
func (g *ConcurrentOrderedGraph[K, V]) IsDirected() bool
IsDirected returns true if the graph is directed.
func (*ConcurrentOrderedGraph[K, V]) NodeCount ¶
func (g *ConcurrentOrderedGraph[K, V]) NodeCount() int
NodeCount returns the number of nodes.
func (*ConcurrentOrderedGraph[K, V]) Nodes ¶
func (g *ConcurrentOrderedGraph[K, V]) Nodes() []*GraphNode[K, V]
Nodes returns all nodes in insertion order.
func (*ConcurrentOrderedGraph[K, V]) RemoveEdge ¶
func (g *ConcurrentOrderedGraph[K, V]) RemoveEdge(from, to K) error
RemoveEdge removes the edge from → to. For undirected graphs the reverse is also removed.
func (*ConcurrentOrderedGraph[K, V]) RemoveNode ¶
func (g *ConcurrentOrderedGraph[K, V]) RemoveNode(id K) error
RemoveNode deletes a node and all edges that reference it.
func (*ConcurrentOrderedGraph[K, V]) SemanticNeighbors ¶
func (g *ConcurrentOrderedGraph[K, V]) SemanticNeighbors( nodeID K, queryVec []float64, topK int, ) ([]ScoredNode[K, V], error)
SemanticNeighbors is a convenience wrapper that returns the direct neighbours of `nodeID` ranked by semantic similarity to queryVec — no BFS, just the immediate 1-hop neighbourhood.
func (*ConcurrentOrderedGraph[K, V]) ShortestPath ¶
func (g *ConcurrentOrderedGraph[K, V]) ShortestPath(from, to K) (PathResult[K], error)
ShortestPath finds the shortest (lowest-weight) path between `from` and `to` using Dijkstra's algorithm. Edge weights must be non-negative. Returns PathResult with the ordered node IDs and total distance.
func (*ConcurrentOrderedGraph[K, V]) UpsertNode ¶
func (g *ConcurrentOrderedGraph[K, V]) UpsertNode(id K, data V, vec []float64)
UpsertNode adds or fully replaces a node (payload + vector).
func (*ConcurrentOrderedGraph[K, V]) VectorSearchBidirectional ¶
func (g *ConcurrentOrderedGraph[K, V]) VectorSearchBidirectional( start K, queryVec []float64, topK int, maxHops int, filter func(V) bool, ) ([]ScoredNode[K, V], error)
VectorSearchBidirectional expands the search in both directions on an undirected or directed graph by also following reverse edges. Useful for retrieving the broader context of a node (parents + children + siblings).
func (*ConcurrentOrderedGraph[K, V]) VectorSearchFromNode ¶
func (g *ConcurrentOrderedGraph[K, V]) VectorSearchFromNode( start K, queryVec []float64, topK int, maxHops int, filter func(V) bool, ) ([]ScoredNode[K, V], error)
VectorSearchFromNode performs a bounded BFS starting at `start`, scoring each visited node by cosine similarity with queryVec, and returns the topK most similar nodes found within maxHops hops.
This is the core primitive for agentic context retrieval: "given the current node (e.g. last tool call, last memory), what are the semantically closest related concepts reachable from here?"
Parameters:
- start — seed node for the BFS
- queryVec — embedding of the query (same dimensionality as node vectors)
- topK — maximum results to return
- maxHops — maximum BFS depth (use -1 for unlimited)
- filter — optional payload predicate; nil = no filter
func (*ConcurrentOrderedGraph[K, V]) VectorSearchGlobal ¶
func (g *ConcurrentOrderedGraph[K, V]) VectorSearchGlobal( queryVec []float64, topK int, filter func(V) bool, ) ([]ScoredNode[K, V], error)
VectorSearchGlobal scans every node in the graph and returns the topK nodes whose Vector embedding is most similar (cosine similarity) to queryVec.
filter is an optional predicate over the node payload; pass nil to include all nodes.
Results are returned in descending similarity order.
type EdgeData ¶
EdgeData holds the metadata associated with a directed connection between two nodes. Weight is used by Dijkstra; Label and Metadata are free-form.
type GraphNode ¶
type GraphNode[K comparable, V any] struct { ID K Data V Vector []float64 // optional; nil means "no embedding" // contains filtered or unexported fields }
GraphNode is a single vertex in the graph. It stores the caller's payload (Data), an optional embedding Vector, and its adjacency list as a ConcurrentOrderedMap so that neighbours are themselves thread-safe and ordered by insertion time.
func (*GraphNode[K, V]) Neighbors ¶
func (n *GraphNode[K, V]) Neighbors() []K
Neighbors returns all outgoing neighbour keys in insertion order.
func (*GraphNode[K, V]) UpdateData ¶
UpdateData mutates the payload under a write lock.
func (*GraphNode[K, V]) UpdateVector ¶
UpdateVector replaces the embedding under a write lock.
type PathResult ¶
type PathResult[K comparable] struct { Nodes []K Distance float64 }
PathResult holds a shortest-path result from Dijkstra.
type ScoredNode ¶
type ScoredNode[K comparable, V any] struct { Node *GraphNode[K, V] Score float64 }
ScoredNode is a query result: a node together with its similarity score.
func (ScoredNode[K, V]) String ¶
func (s ScoredNode[K, V]) String() string
String implements fmt.Stringer for debug output.