s memory consolidation
private async triggerDreamCycle(): Promise<void> {
const patterns = await this.llmRouter.analyzePatterns(this.semantic.observationBuffer);
const promoted = patterns.filter(p => p.frequency >= 3);
this.semantic.curatedKnowledge = this.mergeIntoKnowledgeBase(
this.semantic.curatedKnowledge,
promoted
);
// Prune source buffer to maintain bounded storage
this.semantic.observationBuffer = this.semantic.observationBuffer.slice(-10);
await this.episodic.activityDatabase.purgeConsolidatedEntries();
}
}
**Architecture Rationale:** Procedural memory is loaded at initialization and strictly read-only during runtime. This prevents identity drift and ensures behavioral boundaries remain intact. Semantic memory uses a dual-buffer approach: a curated knowledge file stays within prompt limits, while an observation buffer captures raw experiences. The Dream Cycle runs asynchronously, using the LLM to extract recurring patterns and promote them to long-term storage. This prevents context window saturation while preserving institutional knowledge.
### Step 2: Construct the A2A Communication Protocol
Agents require explicit routing, not shared chat logs. The Agent-to-Agent (A2A) protocol implements a mailbox system with delivery guarantees and an attention controller that prioritizes cognitive cycles.
```typescript
interface A2AMessage {
id: string;
sender: string;
recipient: string;
payload: string;
priority: 'critical' | 'standard' | 'background';
requiresReply: boolean;
timestamp: number;
}
class AgentMailbox {
private outbox: A2AMessage[] = [];
private inbox: A2AMessage[] = [];
private archive: A2AMessage[] = [];
async dispatch(msg: A2AMessage): Promise<void> {
this.outbox.push(msg);
// Async by default; sync mode handled by caller awaiting reply
await this.routeToRecipient(msg.recipient, msg);
}
async retrievePending(): Promise<A2AMessage[]> {
const pending = this.inbox.filter(m => !m.processed);
return pending.sort((a, b) => b.priority.localeCompare(a.priority));
}
async archiveProcessed(msgId: string): Promise<void> {
const msg = this.inbox.find(m => m.id === msgId);
if (msg) {
msg.processed = true;
this.archive.push(msg);
this.inbox = this.inbox.filter(m => m.id !== msgId);
}
}
}
class AttentionController {
private taskQueue: PriorityQueue<Task>;
private mailbox: AgentMailbox;
async allocateCognitiveCycle(): Promise<ExecutionDirective> {
// Priority 1: Critical tasks
const criticalTask = this.taskQueue.peek('critical');
if (criticalTask) return { type: 'execute_task', payload: criticalTask };
// Priority 2: Unread A2A messages
const pendingMail = await this.mailbox.retrievePending();
if (pendingMail.length > 0) return { type: 'process_mail', payload: pendingMail[0] };
// Priority 3: Standard queue
const nextTask = this.taskQueue.dequeue('standard');
return nextTask ? { type: 'execute_task', payload: nextTask } : { type: 'idle' };
}
}
Architecture Rationale: The mailbox enforces async-first communication, preventing blocking deadlocks. Synchronous interactions are explicitly requested via requiresReply: true and handled at the application layer, not the transport layer. The Attention Controller acts as a deterministic scheduler, ensuring agents always process high-priority work before background noise. This mirrors production message queue patterns (e.g., RabbitMQ priorities) adapted for LLM execution loops.
Step 3: Enforce 9-State Task Governance
Reliability requires explicit state transitions. The task governance system implements a finite state machine with built-in quality gates and trust-based autonomy.
type TaskState =
| 'pending' | 'in_progress' | 'blocked' | 'review'
| 'completed' | 'failed' | 'rejected' | 'cancelled' | 'archived';
interface TaskGovernanceEngine {
transitions: Record<TaskState, TaskState[]>;
trustLevels: Record<string, TrustPolicy>;
}
class TaskOrchestrator {
private fsm: TaskGovernanceEngine;
private activeTasks: Map<string, TaskRecord>;
constructor() {
this.fsm = {
transitions: {
pending: ['in_progress', 'cancelled'],
in_progress: ['blocked', 'review', 'failed'],
blocked: ['in_progress', 'cancelled'],
review: ['completed', 'rejected'],
completed: ['archived'],
failed: ['pending', 'cancelled'],
rejected: ['pending', 'cancelled'],
cancelled: ['archived'],
archived: []
},
trustLevels: {
probation: { reviewThreshold: 'all', canApprove: false },
standard: { reviewThreshold: 'complex', canApprove: false },
trusted: { reviewThreshold: 'critical', canApprove: false },
senior: { reviewThreshold: 'none', canApprove: true }
}
};
}
async transitionTask(taskId: string, nextState: TaskState, actor: AgentProfile): Promise<void> {
const task = this.activeTasks.get(taskId);
if (!task) throw new Error('Task not found');
const allowed = this.fsm.transitions[task.state];
if (!allowed.includes(nextState)) {
throw new Error(`Invalid transition: ${task.state} -> ${nextState}`);
}
// SRM Workflow Enforcement
if (nextState === 'completed' && actor.trustLevel !== 'senior') {
const requiresReview = this.fsm.trustLevels[actor.trustLevel].reviewThreshold;
if (requiresReview !== 'none' && task.complexity >= requiresReview) {
nextState = 'review';
}
}
task.state = nextState;
task.auditTrail.push({ from: task.state, to: nextState, actor: actor.id, timestamp: Date.now() });
}
}
Architecture Rationale: The FSM prevents invalid state jumps, ensuring every task follows a predictable lifecycle. The Submit-Review-Merge (SRM) workflow is baked into the transition logic, enforcing a four-eyes principle based on trust levels. Probationary agents require review on all deliverables, while senior agents can self-approve. This eliminates manual oversight bottlenecks while maintaining compliance.
Step 4: Deploy the Heartbeat Scheduler
Autonomous operation requires proactive execution, not just reactive triggers. The Heartbeat mechanism runs at configurable intervals, allowing agents to scan for work, process communications, and execute patrol routines.
interface HeartbeatConfig {
intervalMs: number; // 60000 to 300000
patrolRoutine: string; // Path to HEARTBEAT.md or script
mailboxCheck: boolean;
taskScan: boolean;
}
class AutonomousPulseScheduler {
private config: HeartbeatConfig;
private isRunning: boolean = false;
private timer: NodeJS.Timeout | null = null;
constructor(config: HeartbeatConfig) {
this.config = config;
}
start(): void {
if (this.isRunning) return;
this.isRunning = true;
this.timer = setInterval(async () => {
await this.executePulse();
}, this.config.intervalMs);
}
private async executePulse(): Promise<void> {
const directives: string[] = [];
if (this.config.mailboxCheck) {
const unread = await this.mailbox.retrievePending();
if (unread.length > 0) directives.push('process_communications');
}
if (this.config.taskScan) {
const pending = await this.taskOrchestrator.getPendingTasks();
if (pending.length > 0) directives.push('execute_scheduled_work');
}
if (this.config.patrolRoutine) {
directives.push('run_patrol_routine');
}
if (directives.length > 0) {
await this.agentRuntime.dispatchDirectives(directives);
}
}
stop(): void {
if (this.timer) clearInterval(this.timer);
this.isRunning = false;
}
}
Architecture Rationale: The Heartbeat replaces external CI/CD triggers for recurring agent tasks. By checking mailboxes, task queues, and patrol routines at 60β300 second intervals, agents maintain continuous operational awareness. The scheduler is deliberately lightweight, only dispatching directives when work exists, preventing unnecessary LLM invocations and cost inflation.
Pitfall Guide
Production multi-agent systems fail when architectural boundaries blur. The following pitfalls represent the most common failure modes observed in deployed runtimes.
| Pitfall | Explanation | Fix |
|---|
| Unbounded Episodic Growth | Storing every interaction in the active context window causes token overflow and degraded reasoning quality within 15-20 cycles. | Implement a bounded observation buffer with automated consolidation. Promote recurring patterns to semantic memory and purge raw logs after Dream Cycle execution. |
| Synchronous A2A Deadlocks | Forcing all inter-agent communication to wait for replies creates circular dependencies and stalls the entire runtime. | Default to async mailbox delivery. Reserve synchronous waits for explicit decision gates. Implement timeout thresholds and fallback routing for unresponsive agents. |
| Trust Level Bypass in SRM | Allowing agents to skip review gates undermines quality control and creates compliance gaps in regulated environments. | Encode trust policies directly into the FSM transition logic. Reject state jumps to completed unless the actor's trust level permits self-approval. |
| Context Window Fragmentation | Assembling system prompts without segmenting or caching leads to redundant token consumption and slower inference. | Use a 24-segment prompt assembly strategy with KV-cache optimization. Pre-compile static procedural rules and only inject dynamic semantic/episodic context when relevant. |
| Heartbeat Storming | Setting pulse intervals below 30 seconds or polling unconditionally generates excessive LLM calls, inflating costs and API rate limits. | Configure intervals between 60β300 seconds. Implement work-presence checks before dispatching directives. Add exponential backoff during API throttling events. |
| Procedural Memory Mutation | Allowing agents to rewrite their own identity or behavioral constraints causes role drift and unpredictable output patterns. | Store procedural memory in immutable files loaded at initialization. Restrict write access to human operators only. Validate system prompt assembly against a cryptographic hash of the source. |
| State Machine Spaghetti | Adding ad-hoc transitions without formal validation creates unreachable states and orphaned tasks that never complete or archive. | Define all allowed transitions in a centralized FSM configuration. Implement a transition validator that rejects invalid jumps. Log every state change for audit trails. |
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| High-throughput background processing | Async A2A + Heartbeat polling | Prevents blocking, scales horizontally, reduces idle LLM calls | Low (batched invocations) |
| Critical decision routing | Sync A2A with timeout fallback | Ensures deterministic handoffs, prevents orphaned approvals | Medium (waits increase latency) |
| Enterprise compliance environment | Strict SRM + Senior trust gates | Enforces four-eyes principle, maintains audit trails | High (review overhead) |
| Rapid prototyping / MVP | Simplified FSM + shared context | Faster iteration, lower architectural complexity | Low (but scales poorly) |
| Long-running autonomous agents | Tiered memory + Dream Cycle | Prevents context drift, maintains institutional knowledge | Medium (consolidation costs) |
Configuration Template
runtime:
memory:
procedural:
path: ./config/agent_identity.yaml
immutable: true
semantic:
max_curated_chars: 15000
observation_buffer_limit: 50
dream_cycle_interval_hours: 24
episodic:
session_retention_days: 90
activity_db: sqlite://./data/agent_activities.db
communication:
a2a_protocol:
default_mode: async
sync_timeout_seconds: 30
mailbox_partitions:
- outbox
- inbox
- archive
attention_controller:
priority_levels:
- critical
- standard
- background
governance:
fsm:
states:
- pending
- in_progress
- blocked
- review
- completed
- failed
- rejected
- cancelled
- archived
trust_levels:
probation:
review_threshold: all
can_approve: false
standard:
review_threshold: complex
can_approve: false
trusted:
review_threshold: critical
can_approve: false
senior:
review_threshold: none
can_approve: true
autonomy:
heartbeat:
interval_seconds: 120
mailbox_check: true
task_scan: true
patrol_routine: ./config/heartbeat_patrol.md
Quick Start Guide
- Initialize the runtime skeleton: Create the three core modules (
CognitiveMemoryManager, AgentMailbox, TaskOrchestrator) using the provided TypeScript interfaces. Wire them into a central AgentRuntime class.
- Configure memory boundaries: Set up the procedural identity file, semantic observation buffer, and episodic SQLite database. Define the Dream Cycle consolidation threshold (50 observations) and pattern promotion rules.
- Deploy the FSM and trust policies: Load the 9-state transition map. Assign initial trust levels to agents. Enable SRM workflow enforcement for all state jumps to
completed.
- Start the Heartbeat scheduler: Configure the pulse interval (start at 120s). Enable mailbox and task scanning. Attach a patrol routine for autonomous background work.
- Validate with synthetic workloads: Inject test tasks, simulate inter-agent messages, and trigger memory consolidation. Verify state transitions, audit logs, and context window stability before production deployment.