ari-error-recovery
Error handling, recovery, and resilience patterns for ARI
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Error handling, recovery, and resilience patterns for ARI
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Discord slash commands, approval routing, channel policy, button interaction patterns for OpenClaw/ARI Discord integration
Obsidian vault integration patterns — vault-analyzer.ts, /ari-vault-* commands, morning briefing snippet, PARA structure, read-only enforcement
OpenClaw plugin development patterns — hooks, manifest structure, plugin SDK, APEX/CODEX enforcement
NOVA's P1 PayThePryce pipeline — market signal ingest, card detection, price monitoring, script generation, thumbnail generation, video assembly, approval gate
CHASE's P2 Pryceless Solutions pipeline — lead discovery, 5-criteria audit, LLM qualification, Prompt Forge 4-pass lock, demo generation, outreach approval gate
NOVA's thumbnail generation pipeline — Ideogram V3 via Fal.ai (primary) + DALL-E 3 fallback, 4-variant strategy, Pokemon TCG copyright rules,
| name | ari-error-recovery |
| description | Error handling, recovery, and resilience patterns for ARI |
| triggers | ["error handling","error recovery","resilience","failure handling"] |
Ensure ARI handles errors gracefully, recovers from failures, and maintains system stability.
Per ARI's philosophy: Don't suppress errors silently. Log, understand, integrate.
// ❌ WRONG: Silent suppression
try {
await operation();
} catch (error) {
// Silent failure - NEVER DO THIS
}
// ✅ CORRECT: Log and integrate
try {
await operation();
} catch (error) {
await eventBus.emit('audit:log', {
action: 'operation_failed',
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
throw error; // Re-throw after logging
}
class SecurityError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly riskScore: number
) {
super(message);
this.name = 'SecurityError';
}
}
// Usage
throw new SecurityError('Injection detected', 'SEC001', 0.95);
class ValidationError extends Error {
constructor(
message: string,
public readonly field: string,
public readonly value: unknown
) {
super(message);
this.name = 'ValidationError';
}
}
class AgentError extends Error {
constructor(
message: string,
public readonly agent: string,
public readonly taskId: string
) {
super(message);
this.name = 'AgentError';
}
}
class GovernanceError extends Error {
constructor(
message: string,
public readonly rule: string,
public readonly proposal: unknown
) {
super(message);
this.name = 'GovernanceError';
}
}
async function withRetry<T>(
operation: () => Promise<T>,
maxRetries = 3,
baseDelay = 1000
): Promise<T> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
if (attempt === maxRetries) throw error;
const delay = baseDelay * Math.pow(2, attempt - 1);
await sleep(delay);
eventBus.emit('audit:log', {
action: 'retry_attempt',
attempt,
maxRetries,
delay
});
}
}
throw new Error('Unreachable');
}
class CircuitBreaker {
private failures = 0;
private lastFailure = 0;
private state: 'closed' | 'open' | 'half-open' = 'closed';
async execute<T>(operation: () => Promise<T>): Promise<T> {
if (this.state === 'open') {
if (Date.now() - this.lastFailure > this.resetTimeout) {
this.state = 'half-open';
} else {
throw new Error('Circuit breaker is open');
}
}
try {
const result = await operation();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
}
async function withFallback<T>(
primary: () => Promise<T>,
fallback: () => Promise<T>
): Promise<T> {
try {
return await primary();
} catch (primaryError) {
eventBus.emit('audit:log', {
action: 'fallback_triggered',
primaryError: primaryError.message
});
return await fallback();
}
}
eventBus.on('agent:error', async (event) => {
const { agent, error, taskId } = event;
// Log the failure
await eventBus.emit('audit:log', {
action: 'agent_failure',
agent,
error: error.message,
taskId
});
// Attempt recovery based on agent type
switch (agent) {
case 'guardian':
// Security agent failure = block operation
await eventBus.emit('security:guardian_offline', { taskId });
break;
case 'planner':
// Retry with simpler decomposition
await eventBus.emit('planner:retry_simple', { taskId });
break;
case 'executor':
// Rollback and retry
await eventBus.emit('executor:rollback', { taskId });
break;
}
});
// If memory manager fails, use temporary storage
if (!memoryManager.isAvailable()) {
logger.warn('Memory manager unavailable, using temporary storage');
return tempStorage.store(data);
}
// If governance is slow, use cached decisions
if (await governanceTimeout()) {
const cached = await getCachedDecision(proposal);
if (cached && cached.age < MAX_CACHE_AGE) {
return cached.decision;
}
throw new GovernanceError('Governance timeout', 'GOV001');
}
interface HealthStatus {
overall: 'healthy' | 'degraded' | 'unhealthy';
components: {
gateway: boolean;
agents: Record<string, boolean>;
governance: boolean;
audit: boolean;
};
lastCheck: string;
}
async function checkHealth(): Promise<HealthStatus> {
const components = {
gateway: await pingGateway(),
agents: await checkAllAgents(),
governance: await checkGovernance(),
audit: await verifyAuditChain()
};
return {
overall: calculateOverallHealth(components),
components,
lastCheck: new Date().toISOString()
};
}