A powerful, event-driven agent framework for Node.js that provides a flexible hook system for building modular applications with state management and error handling.
The Agent Framework is a lightweight, modular system for creating and managing agents with a sophisticated hook-based architecture. It allows developers to build applications using a clean separation of concerns with before/execute/after hook patterns, comprehensive state management, and robust error handling.
- Event-Driven Architecture: Built on Node.js EventEmitter for efficient event handling
- Hook System: Comprehensive before/execute/after hook patterns for modular code organization
- State Management: Advanced state controller with nested object support and array operations
- Agent Management: Singleton pattern for centralized agent lifecycle management
- Error Handling: Configurable error exclusion and comprehensive error tracking
- Modular Design: JSON-based configuration for easy agent setup and management
- ES6 Modules: Modern JavaScript with import/export syntax
- Async/Await Support: Full support for asynchronous operations
- Process Signal Handling: Graceful shutdown on SIGINT, SIGTERM, and SIGQUIT
- Dynamic Module Loading: Runtime loading of action modules based on configuration
- Type Safety: JSDoc annotations for better development experience
- Node.js 14+ (ES6 modules support required)
- npm or yarn package manager
- Clone the repository:
git clone https://github.com/dreamingrainbow/agent.git
cd agent- Install dependencies:
npm install- For the example application:
cd example
npm installThe framework uses ES6 modules and doesn't require a build step for development:
# Run the main example
node example/index.js
# Run from the root (if you have a main entry point)
node index.jsThe framework is designed to run directly with Node.js without compilation. For production deployments:
- Ensure all dependencies are installed
- Configure your agents using the JSON configuration system
- Deploy with your Node.js application
agent/
├── Agent.js # Core Agent class with hook system
├── AgentManager.js # Singleton agent manager
├── StateController.js # Advanced state management
├── index.js # Main exports
├── package.json # Package configuration
├── license.md # License information
└── example/ # Example implementation
├── index.js # Example entry point
├── package.json # Example dependencies
└── agents/ # Agent configurations and actions
├── agents.json # Agent configuration
└── main-agent/ # Example agent
└── actions/ # Action modules organized by hook type
├── startup/
│ ├── onBefore/
│ ├── onExecute/
│ └── onAfter/
├── shutdown/
│ └── onExecute/
└── count/
└── onExecute/
The core component that extends EventEmitter and provides:
- Hook Management: Register and execute before/execute/after hooks
- State Management: Integrated StateController for persistent state
- Error Handling: Configurable error exclusion and tracking
- Lifecycle Management: ID, name, and owner tracking
import { Agent } from 'agent';
const agent = new Agent();
agent.setId('my-agent');
agent.setName('My Agent');
agent.setOwner('user123');Singleton pattern for centralized agent management:
- Agent Registration: Add/remove agents from the system
- Agent Retrieval: Find agents by ID, name, or owner
- Lifecycle Control: Manage all agents in the system
import { AgentManager } from 'agent';
const manager = AgentManager.getInstance();
manager.addAgent(agent);
const agent = manager.getAgent('my-agent');Advanced state management with nested object support:
- Nested Path Access: Dot notation for deep object access
- Array Operations: Push, pop, length operations
- Object Merging: Deep merge capabilities
- Type Detection: Automatic type checking
// Set nested state
state.setKey('user.profile.name', 'John Doe');
state.setKey('user.settings.theme', 'dark');
// Array operations
state.push('items', { id: 1, name: 'Item 1' });
const length = state.length('items');Agents are configured using JSON files that define:
- Basic Properties: ID, name, owner, description
- Initial State: Default state values
- Hook Definitions: Before/execute/after hook configurations
- Error Handling: Excluded error types
- Action Modules: File paths and parameters for each action
{
"id": "main-agent",
"name": "My Agent",
"owner": "user123",
"state": {
"initialized": false,
"counter": 0
},
"hooks": {
"startup": {
"action": "startup",
"run": true,
"onBefore": [
{
"action": "startup",
"name": "startup",
"filename": "startup.js"
}
],
"onExecute": {
"action": "startup",
"name": "load",
"filename": "load.js"
},
"onAfter": [
{
"action": "startup",
"name": "initialize",
"filename": "initialize.js"
}
]
}
},
"excludedErrors": []
}- onBefore: Execute before the main action
- onExecute: The main action execution
- onAfter: Execute after the main action
onBefore hooks → onExecute hook → onAfter hooks
Action modules are ES6 modules that export functions:
// actions/startup/onExecute/load.js
export async function load(params) {
console.log('Loading agent...');
// Your logic here
return true;
}- getKey(path): Retrieve value using dot notation
- setKey(path, value): Set value using dot notation
- setState(object): Bulk state updates
- hasKey(path): Check if key exists
- removeKey(path): Remove key from state
- push(path, value): Add item to array
- pop(path): Remove last item from array
- length(path): Get array length
- merge(path, object): Merge objects at path
Configure which errors should be ignored:
agent.excludeError('CustomError');
agent.excludeError('ValidationError');- Errors are automatically captured in hook execution
- Access errors via
agent.getErrors(hookName) - Check for errors with
agent.hasErrors(hookName) - Clear errors with
agent.clearErrors(hookName)
The framework doesn't include built-in internationalization, but the modular design allows for easy integration:
- State-based Localization: Store language preferences in agent state
- Hook-based Translation: Create translation hooks for different languages
- Configuration-driven: Use JSON configuration for multi-language support
Example implementation:
// Store language in state
agent.setState({ language: 'en', locale: 'en-US' });
// Translation hook
agent.onExecute('translate', async (key, params) => {
const lang = this.getState().language;
return await translate(key, params, lang);
});Similar to internationalization, theme settings can be implemented using the state management system:
// Theme configuration in state
agent.setState({
theme: {
mode: 'dark',
primaryColor: '#007bff',
secondaryColor: '#6c757d',
fontFamily: 'Arial, sans-serif'
}
});
// Theme application hook
agent.onExecute('applyTheme', async () => {
const theme = this.getState().theme;
// Apply theme to UI components
return true;
});import { Agent, AgentManager } from 'agent';
// Create agent
const agent = new Agent();
agent.setId('example-agent');
agent.setName('Example Agent');
// Register hooks
agent.onBefore('process', async (data) => {
console.log('Before processing:', data);
});
agent.onExecute('process', async (data) => {
console.log('Processing:', data);
// Your processing logic
});
agent.onAfter('process', async (data) => {
console.log('After processing:', data);
});
// Add to manager
AgentManager.getInstance().addAgent(agent);
// Run the hook
agent.run('process', { message: 'Hello World' });// Set initial state
agent.setState({
user: {
name: 'John Doe',
preferences: {
theme: 'dark',
language: 'en'
}
},
counters: {
requests: 0,
errors: 0
}
});
// Update state
agent.state.setKey('user.preferences.theme', 'light');
agent.state.push('user.history', { action: 'login', timestamp: Date.now() });
// Access state
const userName = agent.state.getKey('user.name');
const requestCount = agent.state.getKey('counters.requests');setId(id): Set agent IDsetName(name): Set agent namesetOwner(owner): Set agent ownergetState(): Get current statesetState(state): Set agent stateonBefore(name, callback): Register before hookonExecute(name, callback): Register execute hookonAfter(name, callback): Register after hookrun(name, ...args): Execute hook with argumentsexcludeError(error): Exclude error typegetErrors(name): Get hook errorshasErrors(name): Check for errorsclearErrors(name): Clear hook errors
getKey(path): Get value by pathsetKey(path, value): Set value by pathsetState(object): Set multiple valueshasKey(path): Check if key existsremoveKey(path): Remove keypush(path, value): Add to arraypop(path): Remove from arraylength(path): Get array lengthmerge(path, object): Merge objects
getInstance(): Get singleton instanceaddAgent(agent): Add agentremoveAgent(agent): Remove agentgetAgent(id): Get agent by IDgetAgentByName(name): Get agent by namegetAgentsByOwner(owner): Get agents by owner
All rights reserved 2025 M.A.D. Computer Consulting LLC
This is a proprietary framework. For contributions or questions, please contact [email protected].
For support and questions:
- Email: [email protected]
- Issues: https://github.com/dreamingrainbow/agent/issues