⚠️ Alpha Software - API may change. Not recommended for production use yet.
Workflow orchestration with controlled iteration.
Drift enables capabilities that traditional DAGs and unmanaged cyclic graphs cannot provide:
- ✅ Bounded loops with max iterations to prevent infinite cycles
- ✅ Convergence detection to auto-stop when conditions are met
- ✅ Multi-path remediation with different strategies per failure type
- ✅ State tracking with full audit trail of execution paths
- ✅ Snapshots & resume for long-running workflows
- ✅ Plugin system for extensibility
- ✅ Service injection for testability
import { ManagedCyclicGraph, Manager } from '@quarry-systems/drift-core';
// Create a self-healing workflow
const graph = new ManagedCyclicGraph('auto-healer')
.guard('isHealthy', ctx => ctx.data.serviceHealth === 'healthy')
.guard('canRetry', ctx => ctx.data.attempts < 3)
.node('detect', { label: 'Detect Issue' })
.node('diagnose', { label: 'Diagnose Problem' })
.node('fix', { label: 'Apply Fix' })
.node('verify', { label: 'Verify Health' })
.node('escalate', { label: 'Escalate', isEndpoint: true })
.edge({ from: 'detect', to: 'diagnose' })
.edge({ from: 'diagnose', to: 'fix' })
.edge({ from: 'fix', to: 'verify' })
.edge({ from: 'verify', to: 'detect', guards: ['!isHealthy', 'canRetry'] })
.edge({ from: 'verify', to: 'escalate', guards: ['!isHealthy', '!canRetry'] })
.start('detect')
.build();
// Execute the workflow
const manager = new Manager(graph);
const result = await manager.run({
data: { serviceHealth: 'unhealthy', attempts: 0 }
});npm install @quarry-systems/drift-core- API Reference - Complete TypeDoc API documentation
- Examples - Working code examples for common patterns
- Testing Guide - Testing best practices with mock services
Control iteration with guards and max iteration limits:
const graph = new ManagedCyclicGraph('retry-workflow')
.guard('canRetry', ctx => ctx.data.attempts < 3)
.node('process', { label: 'Process Data' })
.node('verify', { label: 'Verify Result' })
.edge({ from: 'process', to: 'verify' })
.edge({ from: 'verify', to: 'process', guards: ['!success', 'canRetry'] })
.start('process')
.build();Inject services for testability and flexibility:
const manager = new Manager(graph, {
services: {
http: httpService,
db: databaseService,
llm: openaiService
}
});
// In your node handler
async function processNode(ctx) {
const response = await ctx.services.http.get('/api/data');
return { data: response };
}Extend functionality with middleware:
import { createLoggingMiddleware } from '@quarry-systems/drift-core';
const logging = createLoggingMiddleware({ level: 'debug' });
const manager = new Manager(graph, {
middleware: [logging]
});
await manager.run({ data: {} });Deterministic testing with mock services and recording/replay:
import { RecordingMiddleware, ReplayMiddleware } from '@quarry-systems/drift-testing';
// Record actual execution
const recorder = new RecordingMiddleware();
const manager = new Manager(graph, { middleware: [recorder] });
await manager.run({ data: {} });
const recording = recorder.export();
// Replay deterministically in tests
const replayer = new ReplayMiddleware(recording);
const testManager = new Manager(graph, { middleware: [replayer] });
await testManager.run({ data: {} }); // Uses recorded responsesTrack performance and execution with built-in middleware:
import { MetricsMiddleware, TraceMiddleware } from '@quarry-systems/drift-core';
const metrics = new MetricsMiddleware();
const trace = new TraceMiddleware({ captureInputs: true, captureOutputs: true });
const manager = new Manager(graph, {
middleware: [metrics, trace]
});
await manager.run({ data: {} });
// Export metrics
console.log(metrics.exportJSON());
// Export trace
console.log(trace.exportHTML());The Drift system is organized into multiple packages:
| Package | Description |
|---|---|
| drift-core | Core graph functionality, builder, and manager |
| drift-contracts | TypeScript types and Zod validation schemas |
| drift-testing | Mock services, recording/replay, test utilities |
| drift-ai-core | AI agent core functionality |
const ragPipeline = new ManagedCyclicGraph('rag')
.node('query', { label: 'Process Query' })
.node('retrieve', { label: 'Retrieve Documents' })
.node('generate', { label: 'Generate Answer' })
.node('verify', { label: 'Verify Quality' })
.edge({ from: 'query', to: 'retrieve' })
.edge({ from: 'retrieve', to: 'generate' })
.edge({ from: 'generate', to: 'verify' })
.start('query')
.build();const approvalFlow = new ManagedCyclicGraph('approval')
.guard('isApproved', ctx => ctx.data.status === 'approved')
.guard('canEscalate', ctx => ctx.data.escalationLevel < 3)
.node('submit', { label: 'Submit Request' })
.node('review', { label: 'Review' })
.node('escalate', { label: 'Escalate' })
.node('approve', { label: 'Approve', isEndpoint: true })
.node('reject', { label: 'Reject', isEndpoint: true })
.edge({ from: 'submit', to: 'review' })
.edge({ from: 'review', to: 'approve', guards: ['isApproved'] })
.edge({ from: 'review', to: 'escalate', guards: ['!isApproved', 'canEscalate'] })
.edge({ from: 'review', to: 'reject', guards: ['!isApproved', '!canEscalate'] })
.edge({ from: 'escalate', to: 'review' })
.start('submit')
.build();More examples in ./examples directory.
# Build all drift libraries
nx run-many --target=build --projects=drift-*
# Build specific library
nx build drift-core# Test all drift libraries
nx run-many --target=test --projects=drift-*
# Test specific library
nx test drift-core# Generate TypeDoc documentation
npm run docs:driftIf you're migrating from the standalone managed-cyclic-graph package:
| Old Package | New Package |
|---|---|
@quarry-systems/managed-cyclic-graph |
@quarry-systems/drift-core |
@quarry-systems/mcg-contracts |
@quarry-systems/drift-contracts |
@quarry-systems/mcg-ai-core |
@quarry-systems/drift-ai-core |
Update your imports:
// Old
import { ManagedCyclicGraph } from '@quarry-systems/managed-cyclic-graph';
// New
import { ManagedCyclicGraph } from '@quarry-systems/drift-core';Drift is dual-licensed under:
- GNU Affero General Public License v3.0 (AGPL-3.0)
- Commercial License
See LICENSE-AGPL and LICENSE-COMMERCIAL.md for details.
# Build all drift libraries
nx run-many --target=build --projects=drift-*
# Build specific library
nx build drift-core# Test all drift libraries
nx run-many --target=test --projects=drift-*
# Test specific library
nx test drift-coreFollow the Quarry Systems development rules:
- Maintain DRY principles
- Keep single responsibility per module
- Use existing shared utilities
- Follow TypeScript naming conventions
- Add tests for new functionality
For issues, questions, or commercial licensing inquiries: