/** * xProof Agent Audit Log Guard — Eliza OS Plugin * Standard: https://xproof.app/.well-known/agent-audit-schema.json * * CRITICAL: The AUDIT_BEFORE_EXECUTE action will THROW if xProof certification fails. * Register this plugin BEFORE any action plugin that executes critical operations. * * Usage: * import { xproofAuditPlugin } from "./audit-guard-eliza"; * const agent = new AgentRuntime({ plugins: [xproofAuditPlugin, ...yourOtherPlugins] }); */ import type { Action, IAgentRuntime, Memory, State, HandlerCallback, Plugin } from "@elizaos/core"; import crypto from "crypto"; const XPROOF_API_KEY = process.env.XPROOF_API_KEY ?? "pm_YOUR_API_KEY"; const XPROOF_BASE_URL = process.env.XPROOF_BASE_URL ?? "https://xproof.app"; export class AuditRequiredError extends Error { constructor(message: string) { super(message); this.name = "AuditRequiredError"; } } /** * Certify an audit log with xProof. Throws AuditRequiredError if certification fails. */ async function certifyAuditLog(params: { agentId: string; actionType: string; actionDescription: string; inputsHash: string; riskLevel: string; decision: string; riskSummary?: string; }): Promise<{ proofId: string; auditUrl: string }> { const payload = { agent_id: params.agentId, session_id: crypto.randomUUID(), action_type: params.actionType, action_description: params.actionDescription, inputs_hash: params.inputsHash, risk_level: params.riskLevel, decision: params.decision, risk_summary: params.riskSummary, timestamp: new Date().toISOString(), }; const response = await fetch(`${XPROOF_BASE_URL}/api/audit`, { method: "POST", headers: { Authorization: `Bearer ${XPROOF_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify(payload), signal: AbortSignal.timeout(15_000), }); if (!response.ok) { const text = await response.text().catch(() => ""); throw new AuditRequiredError( `EXECUTION BLOCKED: xProof certification failed (HTTP ${response.status}). ${text.slice(0, 200)}` ); } const data = (await response.json()) as { proof_id?: string; audit_url?: string }; if (!data.proof_id) { throw new AuditRequiredError("EXECUTION BLOCKED: xProof returned no proof_id."); } return { proofId: data.proof_id, auditUrl: data.audit_url ?? "" }; } const auditBeforeExecute: Action = { name: "AUDIT_BEFORE_EXECUTE", similes: ["CERTIFY_ACTION", "XPROOF_AUDIT", "COMPLIANCE_GATE"], description: "Certify this agent's work session with xProof BEFORE executing any critical action. " + "Throws AuditRequiredError if certification fails — blocking the action.", validate: async (_runtime: IAgentRuntime, _message: Memory): Promise => true, handler: async ( runtime: IAgentRuntime, message: Memory, state: State | undefined, options: { actionType: string; actionDescription: string; inputsHash: string; riskLevel: "low" | "medium" | "high" | "critical"; decision: "approved" | "rejected" | "deferred"; riskSummary?: string; }, callback?: HandlerCallback ): Promise => { const agentId = runtime.agentId ?? "eliza-agent"; // Throws AuditRequiredError if certification fails — execution is blocked const { proofId, auditUrl } = await certifyAuditLog({ agentId, actionType: options.actionType, actionDescription: options.actionDescription, inputsHash: options.inputsHash, riskLevel: options.riskLevel, decision: options.decision, riskSummary: options.riskSummary, }); if (callback) { await callback({ text: `Audit certified. proof_id: ${proofId}\naudit_url: ${auditUrl}\nDecision: ${options.decision} | Risk: ${options.riskLevel}`, attachments: [], }); } // Store proof_id in state for downstream actions if (state) { (state as any).xproofProofId = proofId; (state as any).xproofAuditUrl = auditUrl; } return true; }, examples: [], }; export const xproofAuditPlugin: Plugin = { name: "xproof-audit-guard", description: "xProof Agent Audit Log — certifies agent decisions on MultiversX before execution. " + "Schema: ${XPROOF_BASE_URL}/.well-known/agent-audit-schema.json", actions: [auditBeforeExecute], providers: [], evaluators: [], };