Eloquent

Documentation

@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

ImportDescription
@elqnt/kgAll exports (hooks, models, api, utils)
@elqnt/kg/hooksReact hooks (useGraphs, useKGQuery, useKGDesigner, useCrawlJobs)
@elqnt/kg/modelsTypeScript types
@elqnt/kg/apiInternal browser API functions (use hooks instead)
@elqnt/kg/api/serverServer-side API (SSR, Server Actions)
@elqnt/kg/utilsQuery 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:

MethodParametersReturnsDescription
listGraphs-Graph[]List all graphs
getGraphgraphId: stringGraph | nullGet graph by ID
createGraphgraph: CreateGraphRequestGraph | nullCreate a new graph
updateGraphgraphId: string, updates: Partial<Graph>Graph | nullUpdate a graph
deleteGraphgraphId: stringbooleanDelete 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:

MethodParametersReturnsDescription
queryqueryParams: KGQueryKGQueryResult | nullQuery nodes with filters
getLabels-KGLabelInfo[]Get all labels with counts
getNodenodeId: stringKGNode | nullGet node by ID
ingestNodenode: KGNodeIngestRequeststring | nullIngest a node, returns ID
updateNodenodeId: string, updates: Partial<KGNode>booleanUpdate 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:

MethodParametersReturnsDescription
listNodes-GraphNodeDefinition[]List all node definitions
getNodelabel: stringGraphNodeDefinition | nullGet node definition by label
createNodenode: GraphNodeDefinitionGraphNodeDefinition | nullCreate node definition
updateNodelabel: string, updates: Partial<...>GraphNodeDefinition | nullUpdate node definition
deleteNodelabel: stringbooleanDelete node definition

Edge Methods:

MethodParametersReturnsDescription
listEdges-GraphEdgeDefinition[]List all edge definitions
createEdgeedge: GraphEdgeDefinitionGraphEdgeDefinition | nullCreate edge definition
updateEdgelabel: string, updates: Partial<...>GraphEdgeDefinition | nullUpdate edge definition
deleteEdgelabel: stringbooleanDelete 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:

MethodParametersReturnsDescription
listJobs{ limit?, offset?, status? }{ jobs, total }List crawl jobs
startJob{ baseUrl, depth, maxPages }string | nullStart crawl, returns job ID
getJobStatusjobId: stringCrawlJob | nullGet job status
cancelJobjobId: stringbooleanCancel a job
getCrawledPagesjobId: stringCrawledPage[]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

MethodParametersDescription
label(label)stringSet the node label to query
field(name, operator, value)string, string, anyAdd field filter
where(name, value)string, anyAdd 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)numberSet result limit
depth(n)numberSet traversal depth
offset(n)numberSet pagination offset
sortBy(field, order)string, "asc"|"desc"Set sort order
embeddingsSource(source)stringSet 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

FunctionMethodGateway Route
Graphs
ListGET/api/v1/kg/graphs
GetGET/api/v1/kg/graphs/{graphId}
CreatePOST/api/v1/kg/graphs
UpdatePUT/api/v1/kg/graphs/{graphId}
DeleteDELETE/api/v1/kg/graphs/{graphId}
Query
Query NodesPOST/api/v1/kg/query
Get LabelsGET/api/v1/kg/labels
Nodes
Get NodeGET/api/v1/kg/nodes/{nodeId}
Ingest NodePOST/api/v1/kg/nodes
Update NodePUT/api/v1/kg/nodes/{nodeId}
Connection StatsGET/api/v1/kg/nodes/{nodeId}/connections
Documents
Ingest DocumentPOST/api/v1/kg/ingest
Delete DocumentDELETE/api/v1/kg/documents/{documentId}
Optimize GraphPOST/api/v1/kg/graph/optimize
Designer - Nodes
ListGET/api/v1/kg/designer/nodes
GetGET/api/v1/kg/designer/nodes/{label}
CreatePOST/api/v1/kg/designer/nodes
UpdatePUT/api/v1/kg/designer/nodes/{label}
DeleteDELETE/api/v1/kg/designer/nodes/{label}
Designer - Edges
ListGET/api/v1/kg/designer/edges
GetGET/api/v1/kg/designer/edges/{label}
CreatePOST/api/v1/kg/designer/edges
UpdatePUT/api/v1/kg/designer/edges/{label}
DeleteDELETE/api/v1/kg/designer/edges/{label}
Crawl Jobs
ListGET/api/v1/kg/crawl/jobs
StartPOST/api/v1/kg/crawl/jobs
Get StatusGET/api/v1/kg/crawl/jobs/{jobId}
CancelPOST/api/v1/kg/crawl/jobs/{jobId}/cancel
Get PagesGET/api/v1/kg/crawl/jobs/{jobId}/pages

Type Generation

KG types are generated from Go using tygo:

cd backend && tygo generate
Go PackageTypeScript Output
blazi/common/kg@elqnt/kg/models/kg.ts
blazi/services/kg/models@elqnt/kg/models/kg-designer.ts

See Also