Skip to content

Implementing ARAL-CORE Profile

Information

ARAL-CORE is the foundation profile covering Layers 1-5. It’s required for all ARAL agents and includes 68 normative requirements.

This guide provides a comprehensive walkthrough of implementing an ARAL-CORE conformant agent, covering all requirements across the five foundational layers.



Before implementing, ensure your architecture addresses:

cog ✅ Layer 1: Runtime (18 requirements)
  • RNT-001: Process lifecycle management (start, stop, restart)
  • RNT-002: Resource allocation (CPU, memory, storage, network)
  • RNT-003: Resource limit enforcement
  • RNT-004: Platform abstraction interface
  • RNT-005: Cross-platform compatibility (Linux, macOS, Windows)
  • RNT-006: Error handling with retry logic
  • RNT-007: Exponential backoff strategy
  • RNT-008: Configurable retry limits (1-10)
  • RNT-009: Health check endpoint
  • RNT-010: Metrics collection (CPU, memory, uptime)
  • RNT-011: Graceful shutdown (cleanup resources)
  • RNT-012: Concurrent task management
  • RNT-013: Task queue with priority levels
  • RNT-014: Task timeout configuration
  • RNT-015: Environment variable support
  • RNT-016: Configuration file support (JSON/YAML)
  • RNT-017: Logging with structured output
  • RNT-018: Log level configuration (debug, info, warn, error)
database ✅ Layer 2: Memory (12 requirements)
  • MEM-001: Short-term memory (STM) with context window
  • MEM-002: Context window size configuration
  • MEM-003: Pruning strategies (FIFO, summarize, semantic)
  • MEM-004: Long-term memory (LTM) persistence
  • MEM-005: Database support (SQL: PostgreSQL, MySQL, SQLite)
  • MEM-006: NoSQL support (MongoDB, Redis)
  • MEM-007: Data retention policies (configurable TTL)
  • MEM-008: Memory search/retrieval API
  • MEM-009: Semantic search support (optional)
  • MEM-010: Memory encryption at rest
  • MEM-011: Access control for memory operations
  • MEM-012: Memory backup/restore capabilities
puzzle-piece ✅ Layer 3: Capabilities (15 requirements)
  • CAP-001: Action registry system
  • CAP-002: Action schema with JSON Schema
  • CAP-003: Parameter validation before execution
  • CAP-004: Type checking (string, number, boolean, object, array)
  • CAP-005: Required vs optional parameters
  • CAP-006: Default values for optional parameters
  • CAP-007: Action execution engine
  • CAP-008: Async action support
  • CAP-009: Action timeout configuration
  • CAP-010: Action error handling
  • CAP-011: Permission system (RBAC)
  • CAP-012: Action audit logging
  • CAP-013: Built-in actions (HTTP, file, database)
  • CAP-014: Custom action registration
  • CAP-015: Action versioning support
brain ✅ Layer 4: Reasoning (14 requirements)
  • RSN-001: Decision engine interface
  • RSN-002: LLM provider abstraction (OpenAI, Anthropic, local)
  • RSN-003: Model configuration (name, temperature, max_tokens)
  • RSN-004: Prompt template system
  • RSN-005: System prompt injection
  • RSN-006: Context injection from memory
  • RSN-007: Chain-of-thought (CoT) reasoning
  • RSN-008: Multi-step planning capability
  • RSN-009: Planning strategy configuration (sequential, parallel)
  • RSN-010: Action extraction from LLM response
  • RSN-011: Function calling support (if available)
  • RSN-012: Fallback strategies on LLM failure
  • RSN-013: Response validation
  • RSN-014: Cost tracking per LLM call
user-circle ✅ Layer 5: Persona (9 requirements)
  • PER-001: Persona identity (name, role, description)
  • PER-002: Personality traits (0-1 scale)
  • PER-003: Tone configuration (formality, emoji, language)
  • PER-004: Behavioral constraints (must/must_not lists)
  • PER-005: Topic constraints (allowed/forbidden)
  • PER-006: System prompt template
  • PER-007: Response post-processing to enforce tone
  • PER-008: Constraint violation detection
  • PER-009: Persona configuration via JSON/YAML

runtime/core-runtime.ts
import { EventEmitter } from 'events';
interface RuntimeConfig {
resources: {
cpu: { percent: number };
memory: { mb: number };
storage: { mb: number };
};
errorHandling: {
maxRetries: number;
retryDelay: number;
strategy: 'exponential-backoff' | 'fixed';
};
logging: {
level: 'debug' | 'info' | 'warn' | 'error';
structured: boolean;
};
}
export class ARALCoreRuntime extends EventEmitter {
private processes: Map<string, any> = new Map();
private metrics: any = {};
private config: RuntimeConfig;
constructor(config: RuntimeConfig) {
super();
this.config = config;
this.validateConfig();
}
// RNT-001: Process lifecycle
async startProcess(id: string, fn: Function): Promise<void> {
if (this.processes.has(id)) {
throw new Error(`Process ${id} already running`);
}
this.log('info', `Starting process: ${id}`);
this.processes.set(id, { id, fn, status: 'running', startedAt: Date.now() });
this.emit('process:started', id);
}
async stopProcess(id: string): Promise<void> {
if (!this.processes.has(id)) {
throw new Error(`Process ${id} not found`);
}
this.log('info', `Stopping process: ${id}`);
this.processes.delete(id);
this.emit('process:stopped', id);
}
async restartProcess(id: string): Promise<void> {
const process = this.processes.get(id);
if (!process) {
throw new Error(`Process ${id} not found`);
}
await this.stopProcess(id);
await this.startProcess(id, process.fn);
}
// RNT-003: Resource limit enforcement
private enforceResourceLimits(): void {
const usage = process.memoryUsage();
const memoryMB = usage.heapUsed / 1024 / 1024;
if (memoryMB > this.config.resources.memory.mb) {
this.log('warn', `Memory limit exceeded: ${memoryMB.toFixed(2)}MB`);
this.emit('resource:limit-exceeded', { type: 'memory', usage: memoryMB });
}
}
// RNT-006: Error handling with retry
async executeWithRetry<T>(
fn: () => Promise<T>,
retries: number = this.config.errorHandling.maxRetries
): Promise<T> {
let lastError: Error;
for (let attempt = 0; attempt <= retries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
this.log('warn', `Attempt ${attempt + 1} failed: ${error.message}`);
if (attempt < retries) {
const delay = this.calculateBackoff(attempt);
await this.sleep(delay);
}
}
}
throw lastError!;
}
// RNT-007: Exponential backoff
private calculateBackoff(attempt: number): number {
if (this.config.errorHandling.strategy === 'fixed') {
return this.config.errorHandling.retryDelay;
}
return Math.min(
this.config.errorHandling.retryDelay * Math.pow(2, attempt),
30000 // Max 30 seconds
);
}
// RNT-009: Health check
healthCheck(): { status: string; uptime: number; processes: number } {
return {
status: 'healthy',
uptime: process.uptime(),
processes: this.processes.size
};
}
// RNT-010: Metrics collection
getMetrics(): any {
const usage = process.memoryUsage();
const cpuUsage = process.cpuUsage();
return {
memory: {
heapUsed: usage.heapUsed / 1024 / 1024,
heapTotal: usage.heapTotal / 1024 / 1024,
external: usage.external / 1024 / 1024
},
cpu: {
user: cpuUsage.user / 1000000, // Convert to seconds
system: cpuUsage.system / 1000000
},
uptime: process.uptime(),
processes: this.processes.size
};
}
// RNT-011: Graceful shutdown
async shutdown(): Promise<void> {
this.log('info', 'Initiating graceful shutdown...');
// Stop all processes
for (const [id] of this.processes) {
await this.stopProcess(id);
}
// Cleanup resources
this.emit('shutdown');
this.log('info', 'Shutdown complete');
}
// RNT-017: Structured logging
private log(level: string, message: string, meta?: any): void {
if (this.config.logging.structured) {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level,
message,
...meta
}));
} else {
console.log(`[${level.toUpperCase()}] ${message}`);
}
}
private validateConfig(): void {
if (this.config.errorHandling.maxRetries < 1 || this.config.errorHandling.maxRetries > 10) {
throw new Error('RNT-008: maxRetries must be between 1 and 10');
}
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
runtime/core_runtime.py
from typing import Dict, Callable, Any
import asyncio
import time
import psutil
import json
from datetime import datetime
class ARALCoreRuntime:
def __init__(self, config: dict):
self.config = config
self.processes: Dict[str, Any] = {}
self.metrics = {}
self._validate_config()
# RNT-001: Process lifecycle
async def start_process(self, id: str, fn: Callable):
if id in self.processes:
raise ValueError(f"Process {id} already running")
self.log('info', f"Starting process: {id}")
self.processes[id] = {
'id': id,
'fn': fn,
'status': 'running',
'started_at': time.time()
}
async def stop_process(self, id: str):
if id not in self.processes:
raise ValueError(f"Process {id} not found")
self.log('info', f"Stopping process: {id}")
del self.processes[id]
async def restart_process(self, id: str):
process = self.processes.get(id)
if not process:
raise ValueError(f"Process {id} not found")
await self.stop_process(id)
await self.start_process(id, process['fn'])
# RNT-003: Resource limit enforcement
def _enforce_resource_limits(self):
process = psutil.Process()
memory_mb = process.memory_info().rss / 1024 / 1024
if memory_mb > self.config['resources']['memory']['mb']:
self.log('warn', f"Memory limit exceeded: {memory_mb:.2f}MB")
# RNT-006: Error handling with retry
async def execute_with_retry(
self,
fn: Callable,
retries: int = None
):
if retries is None:
retries = self.config['error_handling']['max_retries']
last_error = None
for attempt in range(retries + 1):
try:
return await fn()
except Exception as error:
last_error = error
self.log('warn', f"Attempt {attempt + 1} failed: {error}")
if attempt < retries:
delay = self._calculate_backoff(attempt)
await asyncio.sleep(delay / 1000)
raise last_error
# RNT-007: Exponential backoff
def _calculate_backoff(self, attempt: int) -> int:
if self.config['error_handling']['strategy'] == 'fixed':
return self.config['error_handling']['retry_delay']
return min(
self.config['error_handling']['retry_delay'] * (2 ** attempt),
30000 # Max 30 seconds
)
# RNT-009: Health check
def health_check(self) -> dict:
return {
'status': 'healthy',
'uptime': time.time() - self.processes.get('__start__', time.time()),
'processes': len(self.processes)
}
# RNT-010: Metrics collection
def get_metrics(self) -> dict:
process = psutil.Process()
return {
'memory': {
'rss': process.memory_info().rss / 1024 / 1024,
'vms': process.memory_info().vms / 1024 / 1024
},
'cpu': {
'percent': process.cpu_percent()
},
'uptime': time.time() - self.processes.get('__start__', time.time()),
'processes': len(self.processes)
}
# RNT-011: Graceful shutdown
async def shutdown(self):
self.log('info', 'Initiating graceful shutdown...')
# Stop all processes
for id in list(self.processes.keys()):
await self.stop_process(id)
self.log('info', 'Shutdown complete')
# RNT-017: Structured logging
def log(self, level: str, message: str, meta: dict = None):
if self.config['logging']['structured']:
log_entry = {
'timestamp': datetime.now().isoformat(),
'level': level,
'message': message
}
if meta:
log_entry.update(meta)
print(json.dumps(log_entry))
else:
print(f"[{level.upper()}] {message}")
def _validate_config(self):
max_retries = self.config['error_handling']['max_retries']
if max_retries < 1 or max_retries > 10:
raise ValueError('RNT-008: max_retries must be between 1 and 10')

memory/core-memory.ts
interface MemoryConfig {
shortTerm: {
maxTokens: number;
pruningStrategy: 'fifo' | 'summarize' | 'semantic';
};
longTerm: {
store: 'postgresql' | 'mongodb' | 'redis';
connection: string;
retentionDays: number;
encryption: boolean;
};
}
export class ARALCoreMemory {
private stm: any[] = [];
private ltm: any; // Database connection
private config: MemoryConfig;
constructor(config: MemoryConfig) {
this.config = config;
this.initializeLongTermStorage();
}
// MEM-001: Short-term memory with context window
async addToShortTerm(entry: any): Promise<void> {
this.stm.push({
...entry,
timestamp: Date.now()
});
// MEM-002: Enforce context window size
const totalTokens = this.calculateTokens(this.stm);
if (totalTokens > this.config.shortTerm.maxTokens) {
await this.pruneShortTerm();
}
}
// MEM-003: Pruning strategies
private async pruneShortTerm(): Promise<void> {
switch (this.config.shortTerm.pruningStrategy) {
case 'fifo':
// Remove oldest entries
this.stm = this.stm.slice(-10);
break;
case 'summarize':
// Summarize old entries
const oldEntries = this.stm.slice(0, -5);
const summary = await this.summarizeEntries(oldEntries);
this.stm = [summary, ...this.stm.slice(-5)];
break;
case 'semantic':
// Keep semantically important entries
this.stm = await this.filterByRelevance(this.stm);
break;
}
}
// MEM-004: Long-term persistence
async persist(userId: string, data: any): Promise<void> {
// MEM-010: Encrypt before storing
const encrypted = this.config.longTerm.encryption
? this.encrypt(data)
: data;
await this.ltm.insert({
user_id: userId,
data: encrypted,
timestamp: Date.now(),
// MEM-007: Set TTL
expires_at: Date.now() + (this.config.longTerm.retentionDays * 24 * 60 * 60 * 1000)
});
// MEM-012: Audit log
this.logAccess('write', userId);
}
// MEM-008: Search/retrieval
async search(userId: string, query?: string): Promise<any[]> {
// MEM-011: Access control
if (!this.hasAccess(userId, 'read')) {
throw new Error('Access denied');
}
this.logAccess('read', userId);
if (query) {
// MEM-009: Semantic search (if available)
return await this.semanticSearch(userId, query);
}
return await this.ltm.find({ user_id: userId });
}
private initializeLongTermStorage(): void {
// MEM-005, MEM-006: Database initialization
// Implementation depends on chosen store
}
private calculateTokens(entries: any[]): number {
// Approximate token count
return entries.reduce((sum, entry) => sum + (entry.content?.length || 0) / 4, 0);
}
private async summarizeEntries(entries: any[]): Promise<any> {
// Use LLM to summarize
return { type: 'summary', content: '...', timestamp: Date.now() };
}
private async filterByRelevance(entries: any[]): Promise<any[]> {
// Use semantic similarity
return entries.slice(-10);
}
private encrypt(data: any): any {
// Implement encryption
return data;
}
private hasAccess(userId: string, operation: string): boolean {
// Implement RBAC
return true;
}
private logAccess(operation: string, userId: string): void {
console.log(`[AUDIT] ${operation} by ${userId} at ${new Date().toISOString()}`);
}
private async semanticSearch(userId: string, query: string): Promise<any[]> {
// Implement vector search
return [];
}
}

See the Capabilities Layer documentation for complete implementation details with all 15 requirements (CAP-001 through CAP-015).


See the Reasoning Layer documentation for complete implementation details with all 14 requirements (RSN-001 through RSN-014).


See the Persona Layer documentation for complete implementation details with all 9 requirements (PER-001 through PER-009).


Runtime Tests
// Test process lifecycle
await runtime.startProcess('test', async () => {});
await runtime.stopProcess('test');
await runtime.restartProcess('test');
// Test resource limits
runtime.getMetrics(); // Should show current usage
// Test error handling
await runtime.executeWithRetry(async () => {
throw new Error('Test');
});
// Test health check
const health = runtime.healthCheck();
assert(health.status === 'healthy');
// Test graceful shutdown
await runtime.shutdown();
Memory Tests
// Test short-term memory
await memory.addToShortTerm({ content: 'Hello' });
// Test context window enforcement
for (let i = 0; i < 100; i++) {
await memory.addToShortTerm({ content: `Message ${i}` });
}
// Verify pruning occurred
// Test long-term persistence
await memory.persist('user-123', { data: 'test' });
// Test search
const results = await memory.search('user-123', 'test');
assert(results.length > 0);
// Test encryption
// Verify data is encrypted in database
// Test access control
try {
await memory.search('unauthorized-user', 'test');
assert(false); // Should throw
} catch (error) {
assert(error.message.includes('Access denied'));
}
Capabilities Tests
// Test action registration
capabilities.register({
name: 'test_action',
parameters: { type: 'object', properties: {} },
handler: async () => ({ success: true })
});
// Test parameter validation
try {
await capabilities.execute('test_action', { invalid: true });
assert(false); // Should throw validation error
} catch (error) {
assert(error.message.includes('validation'));
}
// Test execution
const result = await capabilities.execute('test_action', {});
assert(result.success === true);
// Test permissions
// Verify RBAC enforcement
// Test audit logging
// Check logs contain action executions
Reasoning Tests
// Test LLM integration
const response = await reasoning.reason('Hello', []);
assert(response.response.length > 0);
// Test action extraction
const result = await reasoning.reason('Check order #123', []);
assert(result.actions.length > 0);
// Test chain-of-thought
// Verify reasoning steps are generated
// Test fallback
// Simulate LLM failure and verify fallback
// Test cost tracking
const cost = reasoning.getTotalCost();
assert(cost >= 0);
Persona Tests
// Test persona loading
const persona = new Persona(config);
assert(persona.getName() === 'Alex');
// Test tone enforcement
const response = persona.apply('here is ur answer dude');
// Verify professional tone
// Test constraint violations
try {
persona.validateResponse('Political opinion...');
assert(false); // Should throw
} catch (error) {
assert(error.message.includes('constraint'));
}
// Test trait influence
// Verify personality affects responses

Use the official ARAL conformance suite:

Terminal window
npm install -g @aral/conformance-tester
# Run all ARAL-CORE tests
aral-test --profile core --config ./agent-config.json
# Output:
# ✅ RNT-001: Process lifecycle ... PASS
# ✅ RNT-002: Resource allocation ... PASS
# ...
# ✅ PER-009: Persona configuration ... PASS
#
# Result: 68/68 tests passed
# Status: CONFORMANT ✅

Once all tests pass, apply for official ARAL-CORE certification:

  1. Submit test results to the ARAL Conformance Board
  2. Provide implementation documentation
  3. Pass security audit (if required)
  4. Receive certification badge
Information

Use the ARAL-CORE badge in your README:

[![ARAL-CORE Conformant](https://img.shields.io/badge/ARAL-CORE%20Conformant-success)](https://aral.dev/conformance/core)