@elqnt/kg
Complete knowledge graph SDK for the Eloquent platform. Build semantic search, graph-based queries, node/edge schemas, web crawling pipelines, and integrate document knowledge into AI agents.
Installation
npm install @elqnt/kg
Entry Points
| Import | Description |
|---|---|
@elqnt/kg | All exports (hooks, models, api, utils) |
@elqnt/kg/hooks | React hooks (useGraphs, useKGQuery, useKGDesigner, useCrawlJobs) |
@elqnt/kg/models | TypeScript types |
@elqnt/kg/api | Internal browser API functions (use hooks instead) |
@elqnt/kg/api/server | Server-side API (SSR, Server Actions) |
@elqnt/kg/utils | Query builder utilities (KGQueryBuilder, createNodeQuery) |
React Hooks
useGraphs
Hook for knowledge graph CRUD operations.
import { useGraphs } from "@elqnt/kg/hooks";
const {
loading,
error,
listGraphs,
getGraph,
createGraph,
updateGraph,
deleteGraph,
} = useGraphs({
baseUrl: apiGatewayUrl,
orgId: selectedOrgId,
});
// List all graphs
const graphs = await listGraphs();
// Get graph by ID
const graph = await getGraph("graph-uuid");
// Create graph
const newGraph = await createGraph({
name: "Product Knowledge",
description: "Product catalog and relationships",
});
// Update graph
const updated = await updateGraph("graph-uuid", {
description: "Updated description",
});
// Delete graph
const success = await deleteGraph("graph-uuid");
Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
listGraphs | - | Graph[] | List all graphs |
getGraph | graphId: string | Graph | null | Get graph by ID |
createGraph | graph: CreateGraphRequest | Graph | null | Create a new graph |
updateGraph | graphId: string, updates: Partial<Graph> | Graph | null | Update a graph |
deleteGraph | graphId: string | boolean | Delete a graph |
useKGQuery
Hook for querying knowledge graph nodes with semantic search.
import { useKGQuery } from "@elqnt/kg/hooks";
const {
loading,
error,
query,
getLabels,
getNode,
ingestNode,
updateNode,
} = useKGQuery({
baseUrl: apiGatewayUrl,
orgId: selectedOrgId,
graphId: selectedGraphId,
});
// Query nodes
const result = await query({
label: "Product",
fields: [
{ name: "category", operator: "eq", value: "electronics" },
{ name: "price", operator: "gt", value: 100 },
],
limit: 50,
depth: 1,
sortBy: "name",
sortOrder: "asc",
});
console.log(result.nodes, result.edges);
// Semantic similarity search
const similarDocs = await query({
label: "Document",
fields: [{ name: "_search", operator: "similar", value: "machine learning" }],
limit: 10,
});
// Get all labels with counts
const labels = await getLabels();
// [{ label: "Product", count: 1500 }, { label: "Category", count: 50 }]
// Get specific node
const node = await getNode("node-uuid");
// Ingest new node
const nodeId = await ingestNode({
label: "Product",
keyField: "sku",
fields: {
sku: "PROD-001",
name: "Wireless Headphones",
price: 199.99,
category: "electronics",
},
generateEmbeddings: true,
embeddingsFields: ["name", "description"],
duplicatePolicy: "replace",
});
// Update node
const updated = await updateNode("node-uuid", {
fields: { price: 179.99 },
});
Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
query | queryParams: KGQuery | KGQueryResult | null | Query nodes with filters |
getLabels | - | KGLabelInfo[] | Get all labels with counts |
getNode | nodeId: string | KGNode | null | Get node by ID |
ingestNode | node: KGNodeIngestRequest | string | null | Ingest a node, returns ID |
updateNode | nodeId: string, updates: Partial<KGNode> | boolean | Update a node |
useKGDesigner
Hook for managing graph schema - node and edge definitions.
import { useKGDesigner } from "@elqnt/kg/hooks";
const {
loading,
error,
// Node operations
listNodes,
getNode,
createNode,
updateNode,
deleteNode,
// Edge operations
listEdges,
createEdge,
updateEdge,
deleteEdge,
} = useKGDesigner({
baseUrl: apiGatewayUrl,
orgId: selectedOrgId,
graphId: selectedGraphId,
});
// List node definitions
const nodeDefinitions = await listNodes();
// Create node definition
const productNode = await createNode({
label: "Product",
description: "Product in the catalog",
schema: {
type: "object",
properties: {
sku: { type: "string", title: "SKU" },
name: { type: "string", title: "Name" },
price: { type: "number", title: "Price" },
category: { type: "string", title: "Category" },
},
required: ["sku", "name"],
},
});
// Create edge definition
const belongsToEdge = await createEdge({
label: "BELONGS_TO",
description: "Product belongs to category",
fromNode: "Product",
toNode: "Category",
schema: {
type: "object",
properties: {
isPrimary: { type: "boolean", title: "Primary Category" },
},
},
});
// Update definitions
await updateNode("Product", { description: "Updated description" });
await updateEdge("BELONGS_TO", { description: "Updated description" });
// Delete definitions
await deleteNode("Product");
await deleteEdge("BELONGS_TO");
Node Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
listNodes | - | GraphNodeDefinition[] | List all node definitions |
getNode | label: string | GraphNodeDefinition | null | Get node definition by label |
createNode | node: GraphNodeDefinition | GraphNodeDefinition | null | Create node definition |
updateNode | label: string, updates: Partial<...> | GraphNodeDefinition | null | Update node definition |
deleteNode | label: string | boolean | Delete node definition |
Edge Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
listEdges | - | GraphEdgeDefinition[] | List all edge definitions |
createEdge | edge: GraphEdgeDefinition | GraphEdgeDefinition | null | Create edge definition |
updateEdge | label: string, updates: Partial<...> | GraphEdgeDefinition | null | Update edge definition |
deleteEdge | label: string | boolean | Delete edge definition |
useCrawlJobs
Hook for web crawling job management.
import { useCrawlJobs } from "@elqnt/kg/hooks";
const {
loading,
error,
listJobs,
startJob,
getJobStatus,
cancelJob,
getCrawledPages,
} = useCrawlJobs({
baseUrl: apiGatewayUrl,
orgId: selectedOrgId,
graphId: selectedGraphId,
});
// List all crawl jobs
const { jobs, total } = await listJobs({ limit: 20, offset: 0 });
// Start a new crawl job
const jobId = await startJob({
baseUrl: "https://docs.example.com",
depth: 3,
maxPages: 500,
});
// Check job status
const job = await getJobStatus(jobId);
console.log(`Status: ${job.status}, Pages: ${job.pagesProcessed}`);
// Get crawled pages
const pages = await getCrawledPages(jobId);
// Cancel a running job
await cancelJob(jobId);
Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
listJobs | { limit?, offset?, status? } | { jobs, total } | List crawl jobs |
startJob | { baseUrl, depth, maxPages } | string | null | Start crawl, returns job ID |
getJobStatus | jobId: string | CrawlJob | null | Get job status |
cancelJob | jobId: string | boolean | Cancel a job |
getCrawledPages | jobId: string | CrawledPage[] | Get crawled pages |
Query Builder
Fluent API for building KGQuery objects programmatically.
import { KGQueryBuilder, createNodeQuery, createSimilarityQuery } from "@elqnt/kg/utils";
// Fluent builder pattern
const query = new KGQueryBuilder()
.label("Person")
.field("age", "gt", 21)
.field("status", "eq", "active")
.where("department", "Engineering")
.edge("WORKS_AT", "outgoing", "Company")
.edge("REPORTS_TO", "incoming", "Person")
.limit(50)
.depth(2)
.sortBy("name", "asc")
.summaryOnly()
.build();
// Simple node query helper
const products = createNodeQuery("Product", {
category: "electronics",
inStock: true,
}, {
limit: 100,
sortBy: "price",
sortOrder: "asc"
});
// Similarity search helper
const similarDocs = createSimilarityQuery(
"Document",
"How do I configure authentication?",
{ limit: 10, embeddingsSource: "openai" }
);
KGQueryBuilder Methods
| Method | Parameters | Description |
|---|---|---|
label(label) | string | Set the node label to query |
field(name, operator, value) | string, string, any | Add field filter |
where(name, value) | string, any | Add equality filter (shorthand) |
whereAll(fields) | Record<string, any> | Add multiple equality filters |
edge(label, direction, toLabel?, options?) | string, string, ... | Add edge traversal |
outgoing(label, toLabel?) | string, string? | Add outgoing edge |
incoming(label, toLabel?) | string, string? | Add incoming edge |
limit(n) | number | Set result limit |
depth(n) | number | Set traversal depth |
offset(n) | number | Set pagination offset |
sortBy(field, order) | string, "asc"|"desc" | Set sort order |
embeddingsSource(source) | string | Set embeddings source |
skipEmbedding() | - | Skip embedding generation |
summaryOnly() | - | Return only summary fields |
build() | - | Build the KGQuery object |
Query Operators
import {
KGFieldQueryOperatorEqual, // "eq"
KGFieldQueryOperatorNotEqual, // "neq"
KGFieldQueryOperatorGreater, // "gt"
KGFieldQueryOperatorLess, // "lt"
KGFieldQueryOperatorGreaterOrEqual, // "gte"
KGFieldQueryOperatorLessOrEqual, // "lte"
KGFieldQueryOperatorLike, // "like" (pattern matching)
KGFieldQueryOperatorSimilar, // "similar" (semantic search)
KGFieldQueryOperatorIn, // "in" (array membership)
KGFieldQueryOperatorArrayContains, // "arrayContains"
} from "@elqnt/kg/utils";
Models
Graph
import type { Graph, CreateGraphRequest } from "@elqnt/kg/models";
interface Graph {
id: string;
name: string;
description: string;
isDefault: boolean;
createdAt: string;
updatedAt: string;
}
interface CreateGraphRequest {
id?: string; // Optional custom ID
name: string;
description: string;
}
KGNode & KGEdge
import type { KGNode, KGEdge } from "@elqnt/kg/models";
interface KGNode {
id: string;
label: string;
fields: Record<string, any>;
relationships?: KGEdge[];
score?: number; // Relevance score for search results
}
interface KGEdge {
id: string;
label: string;
fields: Record<string, any>;
from: string; // Source node ID
to: string; // Target node ID
}
KGQuery
import type { KGQuery, KGFieldQuery, KGEdgeQuery, KGQueryResult } from "@elqnt/kg/models";
interface KGQuery {
label: string;
fields: KGFieldQuery[];
limit: number;
depth: number;
sortBy: string;
sortOrder: string;
edges?: KGEdgeQuery[];
embeddingsSource?: string;
skipEmbedding?: boolean;
summaryOnly?: boolean; // Filter heavy fields for UI performance
}
interface KGFieldQuery {
name: string;
value: any;
operator: KGFieldQueryOperator;
}
interface KGEdgeQuery {
label: string;
direction: "incoming" | "outgoing";
fields?: Record<string, any>;
toLabel: string;
toFieldKey: string;
toFieldValue: any;
}
interface KGQueryResult {
nodes: KGNode[];
edges: KGEdge[];
}
interface KGLabelInfo {
label: string;
count: number;
}
Node Ingestion
import type { KGNodeIngestRequest, KGEdgeIngestRequest, DuplicatePolicy } from "@elqnt/kg/models";
import {
DuplicatePolicyCreateIf, // "createIfNotExist"
DuplicatePolicyIgnore, // "ignore"
DuplicatePolicyReplace, // "replace"
DuplicatePolicyFail, // "fail"
DuplicatePolicyCreate, // "create"
} from "@elqnt/kg/models";
interface KGNodeIngestRequest {
label: string;
keyField?: string; // Field used for deduplication
reverseEdgeLabel?: string;
fields: Record<string, any>;
edges?: KGEdgeIngestRequest[];
duplicatePolicy?: DuplicatePolicy;
generateEmbeddings?: boolean;
embeddingsSource?: string;
embeddingsFields?: string[]; // Fields to embed
}
interface KGEdgeIngestRequest {
label: string;
fields: Record<string, any>;
toLabel: string;
toFieldKey: string;
toFieldValue: any;
createReciprocal: boolean;
reciprocalLabel: string;
allowEmbeddingsSearch?: boolean;
}
Designer Definitions
import type { GraphNodeDefinition, GraphEdgeDefinition } from "@elqnt/kg/models";
interface GraphNodeDefinition {
label: string;
description: string;
schema: Record<string, any>; // JSON Schema
createdAt: string;
updatedAt: string;
}
interface GraphEdgeDefinition {
label: string;
description: string;
fromNode: string; // Source node label
toNode: string; // Target node label
schema: Record<string, any>; // JSON Schema for edge properties
createdAt: string;
updatedAt: string;
}
Crawl Jobs
interface CrawlJob {
id: string;
baseUrl: string;
depth: number;
maxPages: number;
status: string; // "pending", "running", "completed", "failed", "cancelled"
pagesProcessed: number;
createdAt: string;
updatedAt: string;
}
interface CrawledPage {
url: string;
title: string;
status: string;
processedAt: string;
}
Server API (SSR)
Server-side functions for Next.js Server Actions and SSR.
import {
listGraphsServer,
getGraphServer,
queryGraphServer,
getGraphLabelsServer,
} from "@elqnt/kg/api/server";
// In a Next.js Server Action
"use server";
export async function searchKnowledgeBase(query: string, graphId: string, orgId: string) {
const result = await queryGraphServer(
{
label: "Document",
fields: [{ name: "_search", operator: "similar", value: query }],
limit: 10,
depth: 1,
sortBy: "",
sortOrder: "",
},
{
gatewayUrl: process.env.API_GATEWAY_URL!,
jwtSecret: process.env.JWT_SECRET!,
orgId,
graphId,
}
);
return result.data?.nodes || [];
}
NATS Subjects
For backend service communication:
import {
// Graph management
KGGraphCreate, // "kg.graph.create"
KGGraphUpdate, // "kg.graph.update.*"
KGGraphDelete, // "kg.graph.delete.*"
KGGraphGet, // "kg.graph.get.*"
KGGraphList, // "kg.graph.list"
KGGraphOptimize, // "kg.graph.optimize"
// Designer - Nodes
KGDesignerNodeCreate, // "kg.designer.node.create"
KGDesignerNodeUpdate, // "kg.designer.node.update.*"
KGDesignerNodeDelete, // "kg.designer.node.delete.*"
KGDesignerNodeGet, // "kg.designer.node.get.*"
KGDesignerNodeList, // "kg.designer.node.list"
// Designer - Edges
KGDesignerEdgeCreate, // "kg.designer.edge.create"
KGDesignerEdgeUpdate, // "kg.designer.edge.update.*"
KGDesignerEdgeDelete, // "kg.designer.edge.delete.*"
KGDesignerEdgeGet, // "kg.designer.edge.get.*"
KGDesignerEdgeList, // "kg.designer.edge.list"
// Database management
KGDBCreate, // "kg.db.create"
// Document management
KGDocumentDelete, // "kg_ingest.document.delete"
// Sync jobs
KGSyncJobUpdate, // "kg.sync.job.update"
KGSyncJobList, // "kg.sync.job.list"
// Synchronous ingestion
KGIngestNodeSync, // "kg.sync.node"
KGIngestBatchSync, // "kg.sync.batch"
} from "@elqnt/kg/models";
API Gateway Routes
| Function | Method | Gateway Route |
|---|---|---|
| Graphs | ||
| List | GET | /api/v1/kg/graphs |
| Get | GET | /api/v1/kg/graphs/{graphId} |
| Create | POST | /api/v1/kg/graphs |
| Update | PUT | /api/v1/kg/graphs/{graphId} |
| Delete | DELETE | /api/v1/kg/graphs/{graphId} |
| Query | ||
| Query Nodes | POST | /api/v1/kg/query |
| Get Labels | GET | /api/v1/kg/labels |
| Nodes | ||
| Get Node | GET | /api/v1/kg/nodes/{nodeId} |
| Ingest Node | POST | /api/v1/kg/nodes |
| Update Node | PUT | /api/v1/kg/nodes/{nodeId} |
| Connection Stats | GET | /api/v1/kg/nodes/{nodeId}/connections |
| Documents | ||
| Ingest Document | POST | /api/v1/kg/ingest |
| Delete Document | DELETE | /api/v1/kg/documents/{documentId} |
| Optimize Graph | POST | /api/v1/kg/graph/optimize |
| Designer - Nodes | ||
| List | GET | /api/v1/kg/designer/nodes |
| Get | GET | /api/v1/kg/designer/nodes/{label} |
| Create | POST | /api/v1/kg/designer/nodes |
| Update | PUT | /api/v1/kg/designer/nodes/{label} |
| Delete | DELETE | /api/v1/kg/designer/nodes/{label} |
| Designer - Edges | ||
| List | GET | /api/v1/kg/designer/edges |
| Get | GET | /api/v1/kg/designer/edges/{label} |
| Create | POST | /api/v1/kg/designer/edges |
| Update | PUT | /api/v1/kg/designer/edges/{label} |
| Delete | DELETE | /api/v1/kg/designer/edges/{label} |
| Crawl Jobs | ||
| List | GET | /api/v1/kg/crawl/jobs |
| Start | POST | /api/v1/kg/crawl/jobs |
| Get Status | GET | /api/v1/kg/crawl/jobs/{jobId} |
| Cancel | POST | /api/v1/kg/crawl/jobs/{jobId}/cancel |
| Get Pages | GET | /api/v1/kg/crawl/jobs/{jobId}/pages |
Type Generation
KG types are generated from Go using tygo:
cd backend && tygo generate
| Go Package | TypeScript Output |
|---|---|
blazi/common/kg | @elqnt/kg/models/kg.ts |
blazi/services/kg/models | @elqnt/kg/models/kg-designer.ts |
See Also
- Knowledge Graph - Architecture guide
- @elqnt/agents - Using KG with agents
- @elqnt/docs - Document processing