""" xProof Agent Audit Log Guard — LangChain Standard: https://xproof.app/.well-known/agent-audit-schema.json CRITICAL: The agent will RAISE AN EXCEPTION and cannot continue if xProof certification fails. This makes audit certification a mandatory compliance gate. Install: pip install langchain requests """ import hashlib import json import uuid import requests from langchain.tools import tool XPROOF_API_KEY = "pm_YOUR_API_KEY" # Replace with your key from https://xproof.app/api/agent/register XPROOF_BASE_URL = "https://xproof.app" class AuditRequiredError(Exception): """Raised when an agent action cannot proceed without a valid xProof audit certificate.""" pass @tool def audit_agent_session( action_type: str, action_description: str, inputs_hash: str, risk_level: str, decision: str, agent_id: str = "langchain-agent", risk_summary: str = "", ) -> dict: """ Certify an agent's work session on the MultiversX blockchain BEFORE executing any action. Returns a proof_id that serves as the compliance certificate. The agent MUST call this tool before executing any critical action. Args: action_type: One of: trade_execution, code_deploy, data_access, content_generation, api_call, other action_description: Human-readable description of what the agent is about to do inputs_hash: SHA-256 of all inputs analyzed (market data, code diff, dataset, etc.) risk_level: One of: low, medium, high, critical decision: One of: approved, rejected, deferred agent_id: Identifier of this agent (default: langchain-agent) risk_summary: Optional brief risk analysis Returns: dict with proof_id, audit_url, decision, risk_level Raises: AuditRequiredError: If certification fails (blocks execution) """ import datetime payload = { "agent_id": agent_id, "session_id": str(uuid.uuid4()), "action_type": action_type, "action_description": action_description, "inputs_hash": inputs_hash, "risk_level": risk_level, "decision": decision, "timestamp": datetime.datetime.utcnow().isoformat() + "Z", } if risk_summary: payload["risk_summary"] = risk_summary try: response = requests.post( f"{XPROOF_BASE_URL}/api/audit", json=payload, headers={"Authorization": f"Bearer {XPROOF_API_KEY}", "Content-Type": "application/json"}, timeout=15, ) if response.status_code in (200, 201): data = response.json() proof_id = data.get("proof_id") if not proof_id: raise AuditRequiredError(f"xProof returned no proof_id: {data}") return { "proof_id": proof_id, "audit_url": data.get("audit_url"), "decision": data.get("decision"), "risk_level": data.get("risk_level"), } else: raise AuditRequiredError( f"xProof certification failed (HTTP {response.status_code}): {response.text[:200]}" ) except requests.RequestException as e: raise AuditRequiredError(f"Cannot reach xProof API: {e}") from e def compute_inputs_hash(*inputs) -> str: """Compute SHA-256 of all inputs the agent analyzed before making a decision.""" canonical = json.dumps([str(i) for i in inputs], sort_keys=True) return hashlib.sha256(canonical.encode()).hexdigest() # ── Example usage ───────────────────────────────────────────────────────────── # In your LangChain chain or agent, always call audit_agent_session FIRST: # # inputs_hash = compute_inputs_hash(market_data, risk_params, strategy_config) # audit_result = audit_agent_session.invoke({ # "action_type": "trade_execution", # "action_description": "Buy 0.5 ETH at market price on Uniswap v3", # "inputs_hash": inputs_hash, # "risk_level": "high", # "decision": "approved", # "risk_summary": "Slippage < 0.5%, liquidity verified", # }) # proof_id = audit_result["proof_id"] # # Only after audit_agent_session succeeds, execute the actual action: # execute_trade(...)