chronagraph v0.0.5
ChronaGraph
The Simple, Intuitive Graph Framework for AI & Workflow Orchestration (LangGraph alternative)
Build AI Agents & Workflows Without the Complexity
ChronaGraph is a lightweight, TypeScript-based framework for building graph-based workflows and AI agents. Inspired by LangGraph, but with a focus on simplicity, speed, and ease of use.
π Why ChronaGraph?
β
Type-Safe API β Built with TypeScript for robust, error-free workflows
β
State Management β Built-in memory and state handling across nodes
β
Checkpointing β Save and resume workflow states with FileCheckpointer
β
Event System β Rich event callbacks for monitoring workflow execution
β
Conditional Routing β Dynamic edge conditions for complex flows
β
Error Handling β Robust error management and workflow status tracking
β‘ Installation
Install ChronaGraph via npm:
npm install chronagraph
π§ Quick Start
Here's a practical example of building an activity recommendation system using ChronaGraph:
import { StateGraph } from "chronagraph";
import { FileCheckpointer } from "chronagraph/checkpointers";
import { GraphMemory, NodeImplementation } from "chronagraph/types";
import fs from "fs/promises";
import path from "path";
export const ACTIVITIES = [
{ type: "outdoor", budget: "low", name: "Walking" },
{ type: "outdoor", budget: "medium", name: "Climbing" },
{ type: "outdoor", budget: "high", name: "Skiing" },
{ type: "indoor", budget: "low", name: "Gym" },
{ type: "indoor", budget: "medium", name: "Yoga" },
{ type: "indoor", budget: "high", name: "Pilates" },
];
// Define activity types
interface Activity {
type: string;
budget: string;
name: string;
}
// Define node implementations
export class TypeNode implements NodeImplementation {
async run(memory: GraphMemory) {
// Filter activities by type (indoor/outdoor)
return {
activitiesToDo: ACTIVITIES.filter(
(activity) => activity.type === memory.type
),
};
}
}
export class BudgetNode implements NodeImplementation {
async run(memory: GraphMemory) {
// Filter activities by budget
return {
activitiesToDo: memory.activitiesToDo.filter(
(activity: any) => activity.budget === memory.budget
),
};
}
}
const id = "activity-flow";
// Replace __dirname based path construction with import.meta.url
const checkpointDir = path.dirname(new URL(import.meta.url).pathname);
await fs.mkdir(checkpointDir, { recursive: true }); // Create directory if it doesn't exist
const fileCheckpointer = new FileCheckpointer(checkpointDir);
// Initialize workflow with checkpointing
const workflow = new StateGraph("activity-recommender", {
type: "indoor",
budget: "medium",
activitiesToDo: [],
})
.setCheckpointer(fileCheckpointer)
.addNode("type", new TypeNode())
.addNode("budget", new BudgetNode())
.addEdge("START", "type")
.addEdge("type", "budget")
.addEdge("budget", "END");
await workflow.loadFromCheckpoint(id, fileCheckpointer);
// Add event listener for monitoring
workflow.on((state) => {
const { event, node, output } = state;
console.log(`Event: ${event}`, { node, output });
});
// Run the workflow
const result = await workflow.run();
console.log("Result:", result);
π Core Concepts
Node Implementation
Nodes are the building blocks of your workflow. Each node should:
- Implement the
NodeImplementation
interface - Return an object containing the data it produces
- Have access to the complete workflow memory via
GraphMemory
class ExampleNode implements NodeImplementation {
async run(memory: GraphMemory) {
// Access any previous data from memory
const previousData = memory.someKey;
// Return new data to be stored in memory
return {
newData: "This will be stored in memory",
computedValue: 42,
};
}
}
Workflow Memory
The GraphMemory
object is:
- A complete, up-to-date state of your workflow
- Automatically updated with each node's return data
- Accessible in every node's
run
method - Strongly typed when using TypeScript
Graph Structure
Every workflow has:
- A mandatory
START
edge pointing to your first node - A mandatory
END
edge from your final node - Custom edges connecting your nodes in between
const workflow = new StateGraph("my-workflow", initialMemory)
.addNode("first", new FirstNode())
.addNode("second", new SecondNode())
.addEdge("START", "first") // Required start edge
.addEdge("first", "second") // Custom edge
.addEdge("second", "END"); // Required end edge
Event System
Monitor your workflow using the event system:
workflow.on((state) => {
const { event, node, output, error } = state;
console.log(`Event: ${event}`, { node, output, error });
});
Events include:
- Node execution start/end
- Edge transitions
- Error occurrences
- Workflow completion
Error Handling & Workflow Status
The workflow tracks status at both node and graph levels:
- If a node throws an uncaught error, the workflow ends with
WorkflowStatus.Failed
- Each node's status is tracked independently
- The overall workflow status reflects the current state of execution
const result = await workflow.run();
console.log(result.status); // WorkflowStatus.Completed or WorkflowStatus.Failed
console.log(result.nodeStatuses); // Status of each node
Checkpointing
Checkpointing is optional but powerful:
- Allows saving and resuming workflow state
- Create custom checkpointers by extending
AbstractCheckpointer
- Built-in
FileCheckpointer
for file-based storage
// Custom checkpointer example
class MyCheckpointer extends AbstractCheckpointer {
async save(id: string, data: any): Promise<void> {
// Implement your storage logic
}
async load(id: string): Promise<any> {
// Implement your loading logic
}
}
// Using a checkpointer
const workflow = new StateGraph("my-workflow", initialMemory).setCheckpointer(
new MyCheckpointer()
);
// ... rest of workflow setup
π Key Features
State Management
- Persistent memory across workflow steps
- Type-safe state handling with TypeScript
- Automatic state propagation between nodes
Checkpointing
- Save workflow progress with FileCheckpointer
- Resume workflows from saved states
- Perfect for long-running or interruptible processes
Event System
- Monitor node execution with detailed events
- Track edge transitions and conditions
- Comprehensive error reporting
Error Handling
- Graceful error management
- Workflow status tracking
- Detailed error states and recovery options
π Perfect For
- AI/LLM Workflow Orchestration
- Data Processing Pipelines
- Decision Trees
- Multi-step Business Processes
- Stateful Application Workflows
π Examples
Check out the src/examples
directory for usage examples.
πΊοΈ Roadmap
ChronaGraph is actively being developed. Here are some of the planned improvements and features:
Type System Enhancements
- Stricter type checking for node inputs and outputs
- Runtime type validation for memory states
- Enhanced TypeScript generics support for better IDE integration
- Type-safe edge condition definitions
Workflow Control
- Pause and resume functionality for long-running workflows
- Step-by-step workflow execution mode
State Management
- Additional checkpointing providers (Redis, MongoDB, etc.)
Developer Experience
- Enhanced debugging tools and visualizations
- Better error messages and debugging hints
- More comprehensive documentation and examples
π€ Contributing
Contributions are welcome! Feel free to:
- Open issues for bugs or feature requests
- Submit pull requests
- Share your use cases and examples
π¬ Stay Connected
- Star and watch this repository for updates
- Open issues for feature requests or bug reports
- Share your ChronaGraph projects with the community
- Follow @strange_quirks on X (Twitter) for updates and support
π License
MIT License - Feel free to use in your own projects!