Core Concepts - JavaScript¶
This guide covers the fundamental concepts of GraphBit for JavaScript/Node.js developers, explaining key components and how they work together.
Overview¶
GraphBit is built around these core concepts:
- Library Initialization - Setting up the GraphBit environment
- LLM Providers - Configuring language model clients
- Workflows - Directed graphs that define execution flow
- Nodes - Individual processing units
- Executors - Engines that run workflows
- Tools - External functions accessible to LLMs
- Results - Accessing execution outcomes
Library Initialization¶
Before using GraphBit, initialize the library:
import { init, version, getSystemInfo, healthCheck } from '@infinitibit_gmbh/graphbit';
// Initialize the library
init();
// Check version and system status
console.log(`GraphBit version: ${version()}`);
console.log('System info:', getSystemInfo());
console.log('Health check:', healthCheck());
System Information¶
import { init, getSystemInfo } from '@infinitibit_gmbh/graphbit';
init();
const info = getSystemInfo();
console.log('System Information:', {
nodeVersion: info.nodeVersion,
cpuCount: info.cpuCount,
platform: process.platform,
arch: process.arch
});
Health Checks¶
import { init, healthCheck } from '@infinitibit_gmbh/graphbit';
init();
const health = healthCheck();
if (health.overallHealthy) {
console.log('✅ System is healthy');
} else {
console.warn('⚠️ System health issues detected');
console.log('Memory healthy:', health.memoryHealthy);
console.log('CPU healthy:', health.cpuHealthy);
}
LLM Providers¶
GraphBit supports multiple LLM providers with a unified API.
OpenAI Configuration¶
import { LlmConfig } from '@infinitibit_gmbh/graphbit';
// Basic configuration
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY || 'sk-...'
});
// With custom model
const customConfig = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-4o-mini' // Optional, defaults to gpt-4o-mini
});
Anthropic Configuration¶
import { LlmConfig } from '@infinitibit_gmbh/graphbit';
const config = LlmConfig.anthropic({
apiKey: process.env.ANTHROPIC_API_KEY || 'sk-ant-...'
});
// With custom model
const customConfig = LlmConfig.anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-3-5-sonnet-20241022'
});
OpenRouter Configuration¶
import { LlmConfig } from '@infinitibit_gmbh/graphbit';
// OpenRouter provides access to 400+ models
const config = LlmConfig.openrouter({
apiKey: process.env.OPENROUTER_API_KEY
});
// With specific model
const customConfig = LlmConfig.openrouter({
apiKey: process.env.OPENROUTER_API_KEY,
model: 'anthropic/claude-3.5-sonnet'
});
Ollama Configuration (Local Models)¶
import { LlmConfig } from '@infinitibit_gmbh/graphbit';
// Local Ollama instance
const config = LlmConfig.ollama({
model: 'llama3.2' // Optional, defaults to llama3.2
});
// Custom Ollama URL
const customConfig = LlmConfig.ollama({
baseUrl: 'http://localhost:11434',
model: 'llama3.2:70b'
});
Additional Providers¶
import { LlmConfig } from '@infinitibit_gmbh/graphbit';
// DeepSeek
const deepseekConfig = LlmConfig.deepseek({
apiKey: process.env.DEEPSEEK_API_KEY
});
// Fireworks AI
const fireworksConfig = LlmConfig.fireworks({
apiKey: process.env.FIREWORKS_API_KEY
});
// Groq
const groqConfig = LlmConfig.groq({
apiKey: process.env.GROQ_API_KEY
});
// Together AI
const togetherConfig = LlmConfig.together({
apiKey: process.env.TOGETHER_API_KEY
});
LLM Client¶
Execute LLM requests directly without workflows:
Basic Completion¶
import { init, LlmConfig, LlmClient } from '@infinitibit_gmbh/graphbit';
async function basicCompletion() {
init();
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY
});
const client = new LlmClient(config);
const response = await client.complete('What is the capital of France?');
console.log('Response:', response);
}
basicCompletion().catch(console.error);
Batch Completions¶
async function batchCompletions() {
init();
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY
});
const client = new LlmClient(config);
const prompts = [
'Capital of France?',
'Capital of Germany?',
'Capital of Italy?'
];
const results = await client.completeBatch(
prompts,
100, // maxTokens
0.7, // temperature
3 // concurrency
);
results.forEach((result, i) => {
console.log(`${prompts[i]} → ${result}`);
});
}
Streaming Responses¶
async function streamingResponse() {
init();
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY
});
const client = new LlmClient(config);
console.log('Streaming response:');
const stream = await client.stream('Write a short poem');
for await (const chunk of stream) {
process.stdout.write(chunk);
}
console.log('\nDone');
}
Workflows¶
Workflows define the execution structure as a directed acyclic graph (DAG).
Creating Workflows¶
import { Workflow } from '@infinitibit_gmbh/graphbit';
const workflow = new Workflow('MyWorkflow');
console.log('Workflow created:', workflow);
Adding Nodes¶
import { Workflow, Node } from '@infinitibit_gmbh/graphbit';
async function createWorkflow() {
const workflow = new Workflow('SimpleWorkflow');
// Create an agent node
const agent = Node.agent(
'Analyzer', // name
'Analyze this input', // prompt
'analyzer' // agent_id (unique identifier)
);
// Add node to workflow
await workflow.addNode(agent);
return workflow;
}
Connecting Nodes¶
async function createConnectedWorkflow() {
const workflow = new Workflow('ConnectedWorkflow');
const node1 = Node.agent('Agent 1', 'First task', 'agent_1');
const node2 = Node.agent('Agent 2', 'Second task', 'agent_2');
const node3 = Node.agent('Agent 3', 'Third task', 'agent_3');
await workflow.addNode(node1);
await workflow.addNode(node2);
await workflow.addNode(node3);
// Connect nodes: agent_1 → agent_2 → agent_3
await workflow.connect('agent_1', 'agent_2');
await workflow.connect('agent_2', 'agent_3');
return workflow;
}
Validating Workflows¶
async function validateWorkflow() {
const workflow = new Workflow('ValidatedWorkflow');
const node1 = Node.agent('Agent 1', 'Task', 'agent_1');
await workflow.addNode(node1);
// Always validate before execution
try {
await workflow.validate();
console.log('✅ Workflow is valid');
} catch (error) {
console.error('❌ Workflow validation failed:', error);
}
}
Nodes¶
Nodes are the building blocks of workflows. Different node types serve different purposes.
Agent Nodes¶
Agent nodes execute LLM-based tasks:
import { Node } from '@infinitibit_gmbh/graphbit';
// Simple agent
const agent = Node.agent(
'Summarizer',
'Summarize the following text',
'summarizer'
);
// Agent with context variables
const contextAgent = Node.agent(
'Analyzer',
'Analyze the data: {{data}}', // Template with variable
'analyzer'
);
Task Nodes¶
Task nodes execute computational tasks (not yet available in JavaScript bindings, Python-only feature):
// Note: Task nodes are available in Python but not yet in JavaScript
// Use agent nodes with specific prompts for computational tasks
Condition Nodes¶
Condition nodes enable branching logic:
const condition = Node.condition(
'Checker',
'Evaluate if condition is met',
'checker'
);
// Connect with conditions
await workflow.addNode(condition);
await workflow.addNode(yesPath);
await workflow.addNode(noPath);
await workflow.connectCondition('checker', 'yes_path', true);
await workflow.connectCondition('checker', 'no_path', false);
Parallel Nodes¶
Parallel nodes execute multiple sub-nodes concurrently:
const parallel = Node.parallel('ParallelTasks', [
Node.agent('Task A', 'Do A', 'task_a'),
Node.agent('Task B', 'Do B', 'task_b'),
Node.agent('Task C', 'Do C', 'task_c')
]);
await workflow.addNode(parallel);
Executors¶
Executors run workflows with different performance characteristics.
Default Executor¶
import { Executor } from '@infinitibit_gmbh/graphbit';
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY
});
const executor = new Executor(config);
Low-Latency Executor¶
Optimized for fast response times (single thread):
High-Throughput Executor¶
Optimized for batch processing (multi-thread):
Executing Workflows¶
async function executeWorkflow() {
init();
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY
});
const executor = new Executor(config);
const workflow = new Workflow('ExecutableWorkflow');
const node = Node.agent('Agent', 'Task', 'agent_1');
await workflow.addNode(node);
await workflow.validate();
// Execute workflow
const result = await executor.execute(workflow);
if (result.isSuccess()) {
console.log('✅ Success:', result.variables());
} else {
console.error('❌ Failed:', result.error());
}
}
Tools¶
Tools extend LLM capabilities with custom functions.
Creating Tool Registry¶
Registering Tools¶
async function registerCalculator() {
init();
const registry = new ToolRegistry();
registry.register('add', 'Add two numbers', {
a: { type: 'number' },
b: { type: 'number' }
}, (args: any) => {
return { result: args.a + args.b };
});
console.log('Tool registered');
}
Executing Tools¶
async function executeTool() {
init();
const registry = new ToolRegistry();
registry.register('multiply', 'Multiply two numbers', {
x: { type: 'number' },
y: { type: 'number' }
}, (args: any) => {
return args.x * args.y;
});
const result = await registry.execute('multiply', { x: 5, y: 3 });
console.log('Result:', result); // 15
}
Listing Tools¶
async function listTools() {
init();
const registry = new ToolRegistry();
// For sync tools, use register() directly
registry.register('tool1', 'First tool (sync)', {}, () => 'result1');
// For async tools, use registerAsync() for proper timing
// This ensures the Promise is handled correctly by the Rust core
registerAsync(registry, 'asyncTool', 'Async tool', {}, async () => {
await someAsyncOperation();
return 'result';
});
registry.register('tool2', 'Second tool (sync)', {}, () => 'result2');
const tools = registry.getRegisteredTools();
console.log('Available tools:', tools);
}
Note: For async callbacks (that use
awaitor return Promises), always useregisterAsync(). See Tool Calling Guide for details.
Results¶
Access workflow execution results:
Checking Success¶
const result = await executor.execute(workflow);
if (result.isSuccess()) {
console.log('✅ Workflow succeeded');
const variables = result.variables();
console.log('Variables:', variables);
} else {
console.error('❌ Workflow failed');
const error = result.error();
console.error('Error:', error);
}
Accessing Variables¶
const result = await executor.execute(workflow);
if (result.isSuccess()) {
const vars = result.variables();
// Access specific variables from the workflow context
console.log('Output:', vars.output);
console.log('Status:', vars.status);
}
Error Handling¶
try {
const result = await executor.execute(workflow);
if (!result.isSuccess()) {
const errorMsg = result.error();
console.error('Workflow error:', errorMsg);
// Implement recovery logic
handleWorkflowError(errorMsg);
}
} catch (error) {
console.error('Execution exception:', error);
}
Complete Example¶
Putting it all together:
import {
init,
LlmConfig,
Executor,
Workflow,
Node,
ToolRegistry,
registerAsync
} from '@infinitibit_gmbh/graphbit';
async function completeExample() {
// 1. Initialize
init();
// 2. Configure LLM
const config = LlmConfig.openai({
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-4o-mini'
});
// 3. Create executor
const executor = new Executor(config);
// 4. Register tools
const registry = new ToolRegistry();
// Register async tool
registerAsync(registry, 'get_weather', 'Get current weather for a location', {
location: { type: 'string' }
}, async (args: any) => {
// Simulate async API call
await new Promise(resolve => setTimeout(resolve, 100));
return {
location: args.location,
temperature: 72,
condition: 'sunny'
};
});
// 5. Build workflow
const workflow = new Workflow('WeatherWorkflow');
const locationAgent = Node.agent(
'Location Parser',
'Extract the location from user query',
'location_parser'
);
const weatherAgent = Node.agent(
'Weather Fetcher',
'Get weather for location using get_weather tool',
'weather_fetcher'
);
const responseAgent = Node.agent(
'Response Generator',
'Generate friendly response with weather info',
'response_generator'
);
await workflow.addNode(locationAgent);
await workflow.addNode(weatherAgent);
await workflow.addNode(responseAgent);
await workflow.connect('location_parser', 'weather_fetcher');
await workflow.connect('weather_fetcher', 'response_generator');
// 6. Validate
await workflow.validate();
// 7. Execute
const result = await executor.execute(workflow);
// 8. Handle result
if (result.isSuccess()) {
console.log('✅ Workflow completed successfully');
console.log('Result:', result.variables());
} else {
console.error('❌ Workflow failed:', result.error());
}
}
completeExample().catch(console.error);
Async/Await Pattern¶
All GraphBit operations are async:
// ❌ Wrong - missing await
const result = executor.execute(workflow);
console.log(result); // Prints Promise object
// ✅ Correct - with await
const result = await executor.execute(workflow);
console.log(result); // Prints actual result
// ✅ Correct - with .then()
executor.execute(workflow)
.then(result => console.log(result))
.catch(error => console.error(error));
// ✅ Correct - with try/catch
try {
const result = await executor.execute(workflow);
console.log(result);
} catch (error) {
console.error(error);
}
Common Patterns¶
Sequential Workflow¶
const workflow = new Workflow('Sequential');
await workflow.addNode(Node.agent('Step 1', 'First', 'step1'));
await workflow.addNode(Node.agent('Step 2', 'Second', 'step2'));
await workflow.addNode(Node.agent('Step 3', 'Third', 'step3'));
await workflow.connect('step1', 'step2');
await workflow.connect('step2', 'step3');
Parallel Workflow¶
const workflow = new Workflow('Parallel');
const parallel = Node.parallel('ParallelWork', [
Node.agent('Task A', 'Do A', 'a'),
Node.agent('Task B', 'Do B', 'b'),
Node.agent('Task C', 'Do C', 'c')
]);
await workflow.addNode(parallel);
Branching Workflow¶
const workflow = new Workflow('Branching');
const decision = Node.condition('Decide', 'Check condition', 'check');
const yesPath = Node.agent('Yes', 'Handle yes', 'yes');
const noPath = Node.agent('No', 'Handle no', 'no');
await workflow.addNode(decision);
await workflow.addNode(yesPath);
await workflow.addNode(noPath);
await workflow.connectCondition('check', 'yes', true);
await workflow.connectCondition('check', 'no', false);
Best Practices¶
- Always call
init()before using GraphBit - Validate workflows before execution
- Use meaningful node IDs (unique and descriptive)
- Handle errors explicitly with try/catch
- Choose appropriate executor type for your use case
- Use environment variables for API keys
- Check system health in production
- Implement retry logic for resilience