12-factor-agents
v1.0.0
Published
12-factor methodology for autonomous AI agents - state management, checkpointing, resumable workflows
Maintainers
Readme
12-factor-agents
12-factor methodology for autonomous AI agents - state management, checkpointing, resumable workflows
Overview
12-factor-agents brings the proven principles of 12-factor apps to autonomous AI agent workflows. It provides robust infrastructure for long-running, resumable, and observable agent operations.
Core Principles
- Stateless Brains, Stateful System - Agents are ephemeral, state persists
- Checkpointed Steps - Every step is saved, workflows are resumable
- Idempotent Actions - Steps can be safely retried
- Resumable Workflows - Pick up exactly where you left off
- Human-in-the-Loop Batching - Collect inputs, minimize interruptions
- Observable Operations - Comprehensive logging and notifications
Installation
npm install 12-factor-agentsOr globally for CLI access:
npm install -g 12-factor-agentsQuick Start (5 minutes)
1. Initialize a Project
cd your-project
npx 12fa initThis creates .12fa/ directory for state management.
2. Basic Workflow
import { WorkflowRunner } from '12-factor-agents';
const runner = new WorkflowRunner({
projectRoot: process.cwd(),
enableGitCheckpoints: true,
enableNtfy: false
});
await runner.runWorkflow('my-workflow', [
{
id: 'step-1',
name: 'First step',
action: async () => {
console.log('Doing work...');
}
},
{
id: 'step-2',
name: 'Second step',
action: async () => {
console.log('More work...');
}
}
]);3. Run It
npx ts-node your-script.ts
# or
node your-script.jsIf interrupted, run it again—it will resume from the last checkpoint.
Architecture
┌─────────────────────────────────────────────────────────┐
│ WorkflowRunner │
│ Orchestrates state, checkpoints, logging, and inputs │
└────────────────┬────────────────────────────────────────┘
│
┌───────────┼───────────┬─────────────┬──────────┐
│ │ │ │ │
┌────▼─┐ ┌─────▼──┐ ┌─────▼────┐ ┌────▼──┐ ┌───▼──┐
│State │ │Checkpoint│ │Feature │ │Progress│ │Input │
│Mgr │ │Manager │ │Tracker │ │Logger │ │Coll │
└──────┘ └──────────┘ └─────────┘ └────────┘ └──────┘
│ │ │ │ │
└───────────┼───────────┴─────────────┴──────────┘
│
┌───────▼────────┐
│ .12fa/ State │
│ Persistence │
└────────────────┘
│
┌────▼─────┬──────────┬─────────────┐
│ Git │ NTFY │ Filesystem │
│ Commits │ Notify │ Logs │
└──────────┴──────────┴─────────────┘CLI Commands
# Project initialization
12fa init # Set up state directory
# Workflow management
12fa status # Show current workflow status
12fa checkpoints # List all checkpoints
12fa restore <checkpoint-id> # Restore to checkpoint
# Feature tracking
12fa features # List all features
12fa add-feature "Name" [priority] # Create feature
# Monitoring
12fa logs [session-id] # Show progress logs
12fa inputs # List pending human inputs
12fa respond <input-id> <response> # Provide input response
# Cleanup
12fa clean # Remove all state (destructive)
12fa --help # Show helpComprehensive Guide
Programmatic Usage
import { WorkflowRunner } from '12-factor-agents';
const runner = new WorkflowRunner({
projectRoot: process.cwd(),
enableGitCheckpoints: true,
enableNtfy: process.env.ENABLE_NTFY === 'true',
autoCommit: false
});
await runner.runWorkflow('build-feature', [
{
id: 'analyze',
name: 'Analyze requirements',
action: async () => {
console.log('Analyzing...');
}
},
{
id: 'implement',
name: 'Implement feature',
action: async () => {
console.log('Implementing...');
},
idempotent: true // Safe to retry
},
{
id: 'test',
name: 'Run tests',
action: async () => {
console.log('Testing...');
},
rollback: async () => {
console.log('Rolling back...');
}
}
]);Features
State Management
Persistent state across workflow executions:
const stateManager = runner.getStateManager();
// Check if step was completed
if (stateManager.isStepCompleted('build')) {
console.log('Build already done, skipping...');
}
// Update context
stateManager.updateContext({
apiKey: 'xxx',
deploymentUrl: 'https://example.com'
});Git Checkpointing
Automatic git commits at each step:
const checkpointManager = runner.getCheckpointManager();
// Create manual checkpoint
checkpointManager.createCheckpoint(
'deployment',
'pre-deploy',
{ version: '1.2.3' },
'Ready for deployment'
);
// List all checkpoints
const checkpoints = checkpointManager.listCheckpoints();
// Restore to previous checkpoint
checkpointManager.restoreCheckpoint('deployment-pre-deploy-1234567890');Feature Tracking
Manage features with priorities and status:
const featureTracker = runner.getFeatureTracker();
// Add feature
const feature = featureTracker.addFeature('User authentication', 'high');
// Update status
featureTracker.updateFeatureStatus(feature.id, 'in-progress');
featureTracker.updateFeatureStatus(feature.id, 'complete');
// List features by status
const pending = featureTracker.listFeatures('pending');Progress Logging
Chronological logging of all workflow actions:
const progressLogger = runner.getProgressLogger();
// Log action
progressLogger.log(
sessionId,
'build',
'compile',
'Compiling TypeScript',
'success',
'Built 42 files',
1234 // duration in ms
);
// Get session stats
const stats = progressLogger.getSessionStats(sessionId);
console.log(`Success rate: ${stats.successful}/${stats.totalActions}`);Human Input Collection
Batch human inputs to minimize interruptions:
const inputCollector = runner.getInputCollector();
// Request input
const inputId = inputCollector.requestInput(
'Which API endpoint should we use?',
{ options: ['staging', 'production'] }
);
// Check pending inputs
const pending = inputCollector.getPendingInputs();
// Provide response
inputCollector.provideResponse(inputId, 'staging');
// Wait for response (async)
const response = await inputCollector.waitForResponse(inputId, 60000);NTFY Notifications
Real-time notifications to desktop/mobile:
const ntfyClient = runner.getNtfyClient();
// Built-in notification types
ntfyClient.notifyStart('deployment', 'Starting deployment to production');
ntfyClient.notifyComplete('deployment', 'Deployment successful');
ntfyClient.notifyError('deployment', 'Deployment failed: timeout');
ntfyClient.notifyBlocked('deployment', 'Waiting for approval');
ntfyClient.notifyInputRequired('Select environment', inputId);
// Custom notification
ntfyClient.send({
title: 'Custom Event',
message: 'Something happened',
priority: 'high',
tags: ['warning', 'robot'],
click: 'https://example.com',
actions: [
{
action: 'view',
label: 'View Details',
url: 'https://dashboard.example.com'
}
]
});CLI Usage
# Initialize project
12fa init
# Show workflow status
12fa status
# List checkpoints
12fa checkpoints
# Restore checkpoint
12fa restore <checkpoint-id>
# Feature management
12fa features
12fa add-feature "User authentication" high
# View logs
12fa logs
12fa logs <session-id>
# Human inputs
12fa inputs
12fa respond <input-id> "production"
# Clean all state (WARNING: destructive)
12fa cleanConfiguration
interface WorkflowConfig {
projectRoot: string; // Required: project directory
stateDir?: string; // Default: .12fa/
enableGitCheckpoints?: boolean; // Default: true
enableNtfy?: boolean; // Default: false
ntfyUrl?: string; // Default: http://localhost:8889
ntfyTopic?: string; // Default: anombyte-dev
autoCommit?: boolean; // Default: false
}NTFY Setup
# Auto-setup (installs + starts server)
./node_modules/12-factor-agents/scripts/setup-ntfy.sh
# Manual setup
ntfy serve --listen-http :8889 &
# Subscribe to notifications
# Web: http://localhost:8889/anombyte-dev
# Mobile: Install ntfy app, subscribe to anombyte-devProject Structure
your-project/
└── .12fa/
├── agent-state.json # Current workflow state
├── checkpoints/ # Step checkpoints
│ └── *.json
├── features.json # Feature tracking
├── progress.jsonl # Chronological logs
└── human-inputs.json # Input requests/responsesBest Practices
1. Design Idempotent Steps
{
id: 'install-deps',
name: 'Install dependencies',
action: async () => {
// Check if already installed
if (fs.existsSync('node_modules')) {
console.log('Dependencies already installed');
return;
}
await exec('npm install');
},
idempotent: true
}2. Use Checkpoints for Critical Steps
const checkpoint = checkpointManager.createCheckpoint(
'deployment',
'pre-deploy',
{ version, buildHash },
'Pre-deployment checkpoint'
);3. Batch Human Inputs
// Collect all inputs upfront
const envInput = inputCollector.requestInput('Environment?');
const versionInput = inputCollector.requestInput('Version tag?');
// Notify once
ntfyClient.send({
title: 'Input Required',
message: '2 questions need answers',
priority: 'high'
});
// Wait for all responses
const [env, version] = await Promise.all([
inputCollector.waitForResponse(envInput),
inputCollector.waitForResponse(versionInput)
]);4. Log Everything
progressLogger.log(
sessionId,
phase,
step,
action,
result,
details,
duration
);Examples
See /examples directory for complete workflows:
build-pipeline.ts- CI/CD workflowdata-migration.ts- Database migrationfeature-development.ts- TDD workflow
Troubleshooting
Workflow won't resume
Check that .12fa/agent-state.json exists and is readable:
ls -la .12fa/
cat .12fa/agent-state.jsonNTFY notifications not working
Ensure ntfy server is running:
# Check if running
lsof -i :8889
# Start ntfy server
ntfy serve --listen-http :8889 &
# Subscribe to notifications
# Go to: http://localhost:8889/anombyte-devCLI commands not found
Ensure the package is installed globally or use npx:
# Global install
npm install -g 12-factor-agents
12fa --help
# Or with npx
npx 12-factor-agents --helpContributing
Contributions welcome! Areas for enhancement:
- Test suite (Jest/Vitest)
- Example workflows
- MCP server integration
- Advanced recovery strategies
- Performance optimizations
Roadmap
- v1.0.0 (current) - Stable core + CLI
- v1.1.0 - Enhanced error messages and debugging
- v1.2.0 - Performance optimizations
- v2.0.0 - MCP server integration + advanced patterns
License
MIT
Author
anombyte
Built for autonomous AI agents. Inspired by 12-factor apps. Designed for production.
Perfect for CI/CD pipelines, data migrations, multi-step deployments, and human-supervised AI tasks.
