Litechain is a simple yet powerful drop-in replacement for Langchain to build powerful LLM agents with tools. It provides a unified, ergonomic API for integrating OpenAI, Gemini, Claude, and Groq models, allowing you to register custom tools and let the LLM invoke them as needed, or chain multiple LLMs together for complex AI agent workflows.
npm i litechain
Langchain:
import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";
import { Tool } from "@langchain/core/tools";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { RunnableSequence } from "@langchain/core/runnables";
Litechain:
import litechain from "litechain";
Langchain:
import { PromptTemplate } from "@langchain/core/prompts";
const template = PromptTemplate.fromTemplate(
"You are a helpful assistant. User query: {query}, Context: {context}"
);
const formattedPrompt = await template.format({
query: "What's the weather?",
context: "User is in NYC"
});
Litechain:
const llm = litechain.llm.openai({ apiKey: "sk-...", model: "gpt-4" });
// Direct string with templates
llm.systemprompt = "You are a helpful assistant. Context: {context}";
// Replace templates while invoking
const response = await llm.invoke("What's the weather?", {
context: "User is in NYC"
});
Langchain:
import { Tool } from "@langchain/core/tools";
import { z } from "zod";
const addTool = new Tool({
name: "add",
description: "Add two numbers",
schema: z.object({
a: z.number().describe("The first number"),
b: z.number().describe("The second number")
}),
func: async ({ a, b }) => (a + b).toString()
});
Litechain:
const tool = {
name: "add",
description: "Add two numbers",
parameters: {
a: { type: "number", description: "The first number" },
b: { type: "number", description: "The second number" }
},
execute: async ({ a, b }) => (a + b).toString()
};
llm.addTool(tool);
Langchain:
import { RunnableSequence } from "@langchain/core/runnables";
import { ChatOpenAI } from "@langchain/openai";
const entryLLM = new ChatOpenAI({ model: "gpt-3.5-turbo" });
const techLLM = new ChatOpenAI({ model: "gpt-4" });
// Complex routing logic with custom functions
const chain = RunnableSequence.from([
{
input: (input: string) => input,
llm: entryLLM
},
(output) => {
if (output.includes("technical")) {
return techLLM.invoke(output);
}
return output;
}
]);
Litechain:
const entryLLM = litechain.llm.openai({ apiKey: "sk-...", model: "gpt-3.5-turbo" });
const techLLM = litechain.llm.openai({ apiKey: "sk-...", model: "gpt-4" });
// Simple connection with automatic routing
entryLLM.connect({ TECH: techLLM });
// LLM automatically routes based on [TRANSFER:TECH] in response
- π οΈ Tool/Function Calling: Register your own tools/functions and let the LLM call them automatically.
- π LLM Chaining: Chain multiple LLMs together with automatic routing and transfer capabilities.
- π€ Unified API: Use OpenAI, Gemini, Claude, or Groq with a consistent interface.
- β‘ Simple Integration: Just one importβno need to import types or utilities separately.
- π§© Extensible: Add as many tools as you want, with custom parameters and logic.
- π State Tracking: Built-in conversation flow and transfer history for debugging and transparency.
- π° Budget Tracking: Monitor token usage and costs across all LLM calls with automatic limit enforcement.
- π Custom Embeddings: Use OpenAI, Cohere, HuggingFace, or your own embedding functions for enhanced vector memory.
npm install litechain
Note: You must also install the relevant LLM SDKs for the providers you use (e.g.,
openai
,@google/genai
,@anthropic-ai/sdk
,groq-sdk
).
import litechain from "litechain"; // One line import
const llm = litechain.llm.openai({ // Yes, that's simple
apiKey: process.env.OPENAI_API_KEY!,
model: "gpt-4o-mini",
budget: { limit: 10 }, // $10 budget limit
memory: 'vector', // Vector memory for context
embeddings: { // Custom embeddings for better search
provider: 'openai',
apiKey: process.env.OPENAI_API_KEY!
}
});
// Use invoke for standard responses
const response = await llm.invoke("Hello!");
// Check budget usage
const usage = llm.getUsage();
console.log(`Cost: $${usage.cost.totalCost.toFixed(4)}`);
// Use run for streaming and advanced options
await llm.run("Write a story", {
stream: true,
onChunk: (chunk) => process.stdout.write(chunk.delta),
onComplete: (content) => console.log(`\nCompleted: ${content.length} chars`)
});
const tool = {
description: "Add two numbers",
name: "add",
parameters: {
a: { type: "number", description: "The first number" },
b: { type: "number", description: "The second number" }
},
execute: async (parameters) => (parameters.a + parameters.b).toString()
};
llm.addTool(tool); // Tool added - no need for Zod or any imports
llm.systemprompt = "You are a helpful assistant"; // System prompt defined
const techLLM = litechain.llm.openai({ apiKey: "sk-...", model: "gpt-4" });
llm.connect({ TECH: techLLM }); // Yes, this is how simple it is to connect LLMs
llm.state; // Access state at any point
llm.getConversationFlow(); // Get conversation history
llm.getTransferHistory(); // Get transfer history
llm.clearState(); // Clear conversation state
import litechain from "litechain";
import dotenv from "dotenv";
dotenv.config();
const client = litechain.llm.openai({
apiKey: process.env.OPENAI_API_KEY!,
model: "gpt-4o-mini",
tools: [
{
name: "add",
description: "Add two numbers",
parameters: {
a: { type: "number", description: "The first number" },
b: { type: "number", description: "The second number" }
},
execute: async ({ a, b }) => (a + b).toString()
}
]
});
const response = await client.invoke("add 5 and 3");
console.log(response); // "8"
import litechain from "litechain";
// 1. Setup LLMs
const entryLLM = litechain.llm.openai({
apiKey: "sk-entry",
model: "gpt-3.5-turbo"
});
const techLLM = litechain.llm.openai({
apiKey: "sk-tech",
model: "gpt-3.5-turbo"
});
const billingLLM = litechain.llm.openai({
apiKey: "sk-billing",
model: "gpt-3.5-turbo"
});
// 2. Set system prompts
entryLLM.systemprompt = `
You are the entry point support agent.
Answer basic queries. For billing issues, respond with: [TRANSFER:BILLING]
For technical issues, respond with: [TRANSFER:TECH]
`;
techLLM.systemprompt = `You are a tech support specialist. Fix technical issues.`;
billingLLM.systemprompt = `
You handle billing inquiries. If a refund is needed, respond with: [ESCALATE:HUMAN]
`;
// 3. Connect LLMs
entryLLM.connect({
BILLING: billingLLM,
TECH: techLLM
});
billingLLM.connect({
HUMAN: async (message) => {
console.log("β οΈ Escalating to human...");
return "A human will join shortly.";
}
});
// 4. Handle message (automatic chaining)
const reply = await entryLLM.invoke("I want a refund for my last order");
console.log(reply); // Final response after going through all LLMs
Litechain makes building AI agents extremely simple by allowing you to chain LLMs together with automatic routing. Each LLM can transfer to another LLM or escalate to a human/custom function using simple text patterns.
- Transfers (
[TRANSFER:XXX]
): Route to another LLM - Escalations (
[ESCALATE:XXX]
): Route to a custom function (e.g., human intervention) - Connections: Define routing rules between LLMs and functions
- State Tracking: Automatic conversation flow and transfer history
Connect an LLM to other LLMs or functions for routing.
llm.connect({
BILLING: billingLLM,
TECH: techLLM,
HUMAN: async (message) => "Human response"
});
Get the conversation flow for debugging.
const flow = llm.getConversationFlow();
// Returns array of conversation entries with LLM names, messages, responses, and timestamps
Get the transfer history for debugging.
const transfers = llm.getTransferHistory();
// Returns array of transfer/escalation events
Clear the conversation state and start fresh.
llm.clearState();
// Entry point
const entry = litechain.llm.openai({
apiKey: "sk-entry",
model: "gpt-3.5-turbo"
});
// Specialized departments
const sales = litechain.llm.openai({
apiKey: "sk-sales",
model: "gpt-4"
});
const support = litechain.llm.openai({
apiKey: "sk-support",
model: "gpt-3.5-turbo"
});
const billing = litechain.llm.openai({
apiKey: "sk-billing",
model: "gpt-3.5-turbo"
});
// Set up routing
entry.connect({
SALES: sales,
SUPPORT: support,
BILLING: billing,
URGENT: async (message) => {
// Custom logic for urgent issues
await sendSlackNotification(message);
return "Urgent issue escalated. You'll be contacted shortly.";
}
});
// Handle complex queries
const response = await entry.invoke("I need to cancel my subscription and get a refund");
// Automatically routes through appropriate departments
- OpenAI (
openai
) - Gemini (
@google/genai
) - Claude (
@anthropic-ai/sdk
) - Groq (
groq-sdk
)
- Register tools with a name, description, parameters, and an
execute
function. - Invoke the LLM with a prompt. If the LLM decides a tool is needed, Litechain:
- Parses the tool call from the LLM.
- Executes your tool(s) with the provided arguments.
- Feeds the result(s) back to the LLM.
- Returns the final LLM response to you.
- Set up LLMs with appropriate system prompts.
- Connect them using the
connect()
method. - Invoke the entry LLM with a message.
- Automatic routing based on
[TRANSFER:XXX]
and[ESCALATE:XXX]
patterns. - State tracking maintains conversation flow and transfer history.
Enhanced method supporting streaming and advanced options.
await llm.run("Generate content", {
stream: true,
onChunk: (chunk: StreamChunk) => void,
onComplete: (content: string) => void,
onError: (error: Error) => void
});
Standard invocation with variable interpolation.
const response = await llm.invoke("Hello {name}", { name: "Alice" });
Add tools for function calling.
llm.addTool({
name: "tool_name",
description: "Tool description",
parameters: { /* parameter schema */ },
execute: async (params) => "result"
});
Connect LLM to other LLMs or functions for chaining.
llm.connect({
SUPPORT: supportLLM,
BILLING: billingLLM,
HUMAN: async (msg) => "Human response"
});
Get detailed conversation history with timestamps.
const flow: ConversationFlowEntry[] = llm.getConversationFlow();
// Returns: [{ llmName, message, response, timestamp, transferTarget? }]
Get LLM transfer/escalation history.
const transfers: TransferResponse[] = llm.getTransferHistory();
// Returns: [{ type, target, originalResponse, timestamp }]
Reset conversation state and start fresh.
llm.clearState(); // New thread_id, empty history
Create memory instances with different backends.
// String configs
const chatMemory = createMemory('chat');
const vectorMemory = createMemory('vector');
// Object configs
const fileMemory = createMemory({
type: 'file',
path: './memory/conversations'
});
const hybridMemory = createMemory({
type: 'hybrid',
chat: { type: 'file', path: './chat' },
vector: { provider: 'local' }
});
interface StreamChunk {
content: string; // Full content so far
delta: string; // New content in this chunk
isComplete: boolean; // Whether streaming is done
timestamp?: Date;
metadata?: Record<string, any>;
}
interface StreamOptions {
onChunk?: (chunk: StreamChunk) => void;
onComplete?: (fullContent: string) => void;
onError?: (error: Error) => void;
}
interface Tool<P = Record<string, any>> {
name: string;
description: string;
parameters: P; // JSON schema for parameters
execute: (parameters: P) => Promise<string>;
}
type ConnectionType = LLMBase | ((message: string) => Promise<string> | string);
interface ConnectionRoutes {
[key: string]: ConnectionType;
}
apiKey
: Your provider API key.model
: The model name (e.g.,"gpt-4o-mini"
).tools
: Array of tool definitions.
{
name: string;
description: string;
parameters: Record<string, { type: string; description: string }>;
execute: (parameters: Record<string, any>) => Promise<string>;
}
type ConnectionType = LLMBase | ((message: string) => Promise<string> | string);
Create sophisticated tools that combine multiple operations:
// Composite tool that internally uses multiple operations
const compositeTools = [
{
name: "analyze_text_complete",
description: "Complete text analysis with word count, timestamps, and UUID",
parameters: {
text: { type: "string", description: "Text to analyze" }
},
execute: async (parameters: any) => {
const text = parameters.text;
const words = text.trim().split(/\s+/).filter(w => w.length > 0);
const chars = text.length;
const timestamp = new Date().toISOString();
const analysisId = crypto.randomUUID();
return `Complete Analysis [${analysisId}]:
- Text: "${text}"
- Word count: ${words.length}
- Character count: ${chars}
- Analysis time: ${timestamp}
- Sentences: ${text.split(/[.!?]+/).filter(s => s.trim().length > 0).length}`;
}
},
{
name: "system_status",
description: "Get comprehensive system status with performance metrics",
parameters: {},
execute: async () => {
const timestamp = new Date().toISOString();
const uptime = process.uptime();
const memory = process.memoryUsage();
return `System Status Report:
- Current time: ${timestamp}
- Uptime: ${Math.floor(uptime / 60)} minutes
- Memory usage: ${Math.round(memory.heapUsed / 1024 / 1024)}MB
- Process ID: ${process.pid}
- Status: Operational`;
}
}
];
llm.addTool(compositeTools[0]);
llm.addTool(compositeTools[1]);
// Complex multi-tool workflows
const complexQueries = [
"Calculate 15% of 1000, then check the weather in New York, and create a file called 'weather-report.txt'",
"Generate a UUID, get the current time in ISO format, then analyze our weekly sales data",
"Count words in 'The quick brown fox jumps over the lazy dog', calculate the square of that number, and list all files"
];
for (const query of complexQueries) {
const response = await llm.invoke(query);
console.log(`Query: ${query}`);
console.log(`Result: ${response}\n`);
}
Built-in performance analysis for tool execution:
// Performance testing for individual tools
async function performanceTest(toolName: string, query: string) {
const startTime = Date.now();
const response = await llm.invoke(query);
const duration = Date.now() - startTime;
return {
tool: toolName,
query,
duration,
responseLength: response.length
};
}
// Benchmark multiple tools
const performanceTests = [
{ tool: "calculate", query: "Calculate 123 * 456" },
{ tool: "get_time", query: "What time is it in ISO format?" },
{ tool: "weather_lookup", query: "What's the weather in Tokyo?" },
{ tool: "word_count", query: "Count words in 'Hello world from Litechain'" }
];
const results = [];
for (const test of performanceTests) {
llm.clearState(); // Clean state for accurate timing
const result = await performanceTest(test.tool, test.query);
results.push(result);
}
// Performance analytics
console.log("Performance Results:");
results.forEach(result => {
console.log(` ${result.tool}: ${result.duration}ms (${result.responseLength} chars)`);
});
const avgDuration = results.reduce((sum, r) => sum + r.duration, 0) / results.length;
console.log(` Average: ${Math.round(avgDuration)}ms`);
Test all Litechain capabilities with a complete test suite:
import litechain from "litechain";
async function comprehensiveTest() {
// 1. Basic LLM Creation
const client = litechain.llm.gemini({
apiKey: process.env.GEMINI_API_KEY!,
model: "gemini-2.0-flash"
});
// 2. System Prompt Configuration
client.systemprompt = "You are a helpful assistant for mathematical calculations and time queries.";
// 3. Tool Integration
const tools = [
{
name: "add",
description: "Add two numbers",
parameters: {
a: { type: "number", description: "First number" },
b: { type: "number", description: "Second number" }
},
execute: async ({ a, b }) => (a + b).toString()
},
{
name: "multiply",
description: "Multiply two numbers",
parameters: {
a: { type: "number", description: "First number" },
b: { type: "number", description: "Second number" }
},
execute: async ({ a, b }) => (a * b).toString()
},
{
name: "get_time",
description: "Get current time",
parameters: {},
execute: async () => new Date().toISOString()
}
];
tools.forEach(tool => client.addTool(tool));
// 4. Complex Tool Chain Execution
const complexQuery = "multiply 4 with 5 and add the result with 342 and get the current time in human format?";
const response = await client.invoke(complexQuery);
console.log("Complex chain result:", response);
// 5. State Management Inspection
const state = client.state;
console.log("State Info:", {
threadId: state.thread_id.substring(0, 8) + "...",
historyEntries: state.history.length,
conversationFlow: state.conversation_flow.length,
currentLLM: state.current_llm,
toolsAvailable: client.tools.length
});
// 6. Conversation Context Tracking
const followUp = "What was the final result of that calculation?";
const contextResponse = await client.invoke(followUp);
console.log("Context preserved:", contextResponse);
// 7. History Analysis
console.log("Recent conversation:");
client.state.history.slice(-3).forEach((entry, i) => {
const preview = entry.content.substring(0, 50) + "...";
console.log(` ${i + 1}. ${entry.role}: ${preview}`);
});
// 8. Conversation Flow Tracking
if (client.state.conversation_flow.length > 0) {
console.log("Flow tracking:");
client.state.conversation_flow.forEach((entry, i) => {
const preview = entry.response.substring(0, 40) + "...";
console.log(` ${i + 1}. [${entry.timestamp.toLocaleTimeString()}] ${entry.llmName}: ${preview}`);
});
}
return {
success: true,
testsCompleted: 8,
toolsIntegrated: tools.length,
stateManaged: true,
contextPreserved: true
};
}
// Run comprehensive test
comprehensiveTest()
.then(results => {
console.log("β
All tests passed!", results);
})
.catch(error => {
console.error("β Test failed:", error);
});
- Customer Support: Route queries to specialized departments
- Sales Funnel: Guide prospects through qualification and closing
- Content Creation: Chain research, writing, and editing LLMs
- Code Review: Route to different specialized code reviewers
- Multi-step Processing: Chain validation, processing, and notification LLMs
- Decision Trees: Route based on business rules and conditions
- Escalation Systems: Automatic human intervention when needed
Litechain supports real-time streaming for a better user experience with immediate response feedback:
import litechain from "litechain";
const llm = litechain.llm.openai({
apiKey: process.env.OPENAI_API_KEY!,
model: "gpt-4o-mini"
});
// Stream response with real-time chunks
await llm.run("Write a short story about AI", {
stream: true,
onChunk: (chunk) => {
process.stdout.write(chunk.delta); // Real-time output
if (chunk.isComplete) {
console.log("\nβ
Streaming completed!");
}
},
onComplete: (fullContent) => {
console.log(`Full response: ${fullContent.length} characters`);
},
onError: (error) => {
console.error("Streaming error:", error.message);
}
});
// Custom chunk processing with real-time analytics
let wordCount = 0;
let sentenceCount = 0;
await llm.run("Explain machine learning in detail", {
stream: true,
onChunk: (chunk) => {
if (chunk.delta) {
// Real-time text analysis
const words = chunk.delta.split(/\s+/).filter(w => w.length > 0);
const sentences = chunk.delta.split(/[.!?]+/).filter(s => s.trim().length > 0);
wordCount += words.length;
sentenceCount += sentences.length;
// Update live statistics
process.stdout.write(`\rπ Words: ${wordCount}, Sentences: ${sentenceCount}`);
}
}
});
// Concurrent streaming from multiple LLMs
const llm1 = litechain.llm.openai({ apiKey: "...", model: "gpt-4o-mini" });
const llm2 = litechain.llm.openai({ apiKey: "...", model: "gpt-4o-mini" });
llm1.systemprompt = "You are a technical expert.";
llm2.systemprompt = "You are a creative writer.";
// Run multiple streams concurrently
const promises = [
llm1.run("Explain HTTP protocol", { stream: true, onChunk: (chunk) => console.log(`[Tech] ${chunk.delta}`) }),
llm2.run("Write a poem about coding", { stream: true, onChunk: (chunk) => console.log(`[Creative] ${chunk.delta}`) })
];
await Promise.all(promises);
- 10-15% faster completion times compared to non-streaming
- Immediate user feedback with progressive content display
- Real-time processing capabilities for live analytics
- Concurrent streams for multi-faceted responses
Litechain includes built-in budget tracking to monitor token usage and costs across all LLM calls:
import litechain from "litechain";
const llm = litechain.llm.openai({
apiKey: process.env.OPENAI_API_KEY!,
model: "gpt-4o-mini",
budget: {
limit: 10, // $10 USD limit
onExceeded: (usage) => {
console.log("Budget exceeded!", usage);
}
}
});
// Use normally - budget is tracked automatically
const response = await llm.invoke("Hello!");
// Check current usage
const usage = llm.getUsage();
console.log({
tokens: usage.tokens.totalTokens,
cost: usage.cost.totalCost // In USD
});
// Detailed budget configuration
const llm = litechain.llm.openai({
apiKey: "...",
model: "gpt-4o-mini",
budget: {
limit: 50,
trackTokens: true,
onExceeded: (usage) => {
// Custom handler - log, send alert, etc.
console.log(`Budget exceeded: $${usage.cost.totalCost}`);
// Optionally stop execution or switch to cheaper model
}
}
});
// Get detailed report
console.log(llm.getBudgetReport());
// Output:
// Budget Usage Report:
// - Tokens: 1,250 (800 input, 450 output)
// - Cost: $0.0045 ($0.0024 input, $0.0021 output)
// - Remaining: $49.9955
// - Status: OK
// Check if budget exceeded
if (llm.isBudgetExceeded()) {
console.log("Switch to cheaper model or stop");
}
// Reset budget for new session
llm.resetBudget();
// Update budget limits dynamically
llm.updateBudgetConfig({ limit: 100 });
// All providers support budget tracking
const openai = litechain.llm.openai({
apiKey: "...",
model: "gpt-4o-mini",
budget: { limit: 10 }
});
const gemini = litechain.llm.gemini({
apiKey: "...",
model: "gemini-2.0-flash",
budget: { limit: 10 }
});
const claude = litechain.llm.claude({
apiKey: "...",
model: "claude-3-haiku",
budget: { limit: 10 }
});
// Compare costs across providers
const prompt = "Explain quantum computing";
const [openaiResponse, geminiResponse, claudeResponse] = await Promise.all([
openai.invoke(prompt),
gemini.invoke(prompt),
claude.invoke(prompt)
]);
console.log("Cost comparison:");
console.log("OpenAI:", openai.getUsage().cost.totalCost);
console.log("Gemini:", gemini.getUsage().cost.totalCost);
console.log("Claude:", claude.getUsage().cost.totalCost);
await llm.run("Write a long essay", {
stream: true,
onChunk: (chunk) => {
process.stdout.write(chunk.delta);
},
onComplete: (content) => {
// Budget is automatically tracked during streaming
const usage = llm.getUsage();
console.log(`\nCost: $${usage.cost.totalCost.toFixed(4)}`);
}
});
Track token usage and costs automatically with built-in budget limits:
const chain = litechain({
provider: 'openai',
model: "gpt-4o",
apiKey: "sk-...",
budget: {
limit: 10, // USD
onExceeded: () => console.log("Limit exceeded")
}
});
const response = await chain.invoke("Hello!");
const usage = chain.getUsage();
// => { tokens: 5000, cost: 0.75, calls: 1, inputTokens: 2000, outputTokens: 3000 }
Use built-in providers or custom embedding functions:
// Built-in provider
const chain = litechain({
model: "gpt-4o",
apiKey: "sk-...",
embeddings: {
provider: "cohere",
apiKey: "...",
model: "embed-v3"
}
});
// Custom embedding function
const chain = litechain({
model: "gpt-4o",
apiKey: "sk-...",
embeddings: async (text) => {
// Your custom embedding logic
return [0.1, 0.2, 0.3]; // Return vector
}
});