Native Plugin

Native Plugin

Generate RunProofs directly from OpenClaw-based runtimes like NemoClaw/OpenShell.


Overview

The native plugin path captures execution-proof events inside the agent runtime, without wrapping your code in a Python SDK.

OpenClaw Gateway (NemoClaw/OpenShell)

  runproof-capture plugin

   RunProof API (Railway)

   /verify endpoint

One-line summary: NemoClaw secures execution. RunProof proves execution.


Two Proof Paths

PathHow it worksBest for
Python SDKWrap your framework (LangGraph, etc.)Custom runtimes, frameworks
Native PluginDrop into OpenClaw gatewayNemoClaw, OpenShell, secure runtimes

This page documents the Native Plugin path.


What Gets Captured

The native plugin hooks into the OpenClaw gateway and captures:

HookCapturedMeaning
before_prompt_buildPrompt/environment capture
before_tool_callTool invocation with params hash
after_tool_callTool result with output hash

These events form a hash-chained execution trace with cryptographic proof.


Quick Start

1. Install the plugin

# Inside NemoClaw sandbox
cd ~/.openclaw/extensions
mkdir -p runproof-capture
# Copy plugin files (index.js, package.json)

2. Configure the API endpoint

Set the RunProof API URL in the plugin:

const RUNPROOF_URL = "https://runproof-api-production.up.railway.app";
const AGENT_ID = "your-agent-id";

3. Restart the gateway

# Kill existing gateway
pkill -f openclaw-gatewa
 
# Start fresh
nohup openclaw gateway run > /tmp/gateway.log 2>&1 &
 
# Verify plugin loaded
grep "runproof-capture" /tmp/gateway.log

4. Run an agent command

openclaw agent --agent main -m "List files in /tmp"

5. Finalize the run

curl -X POST "https://runproof-api-production.up.railway.app/v1/run/end" \
  -H "Content-Type: application/json" \
  -d '{"run_id": "YOUR_RUN_ID", "success": true}'

6. Verify

curl "https://runproof-api-production.up.railway.app/v1/runproof/YOUR_RUN_ID/verify"

Expected output:

{
  "verified": true,
  "chain_valid": true,
  "signatures": {
    "count": 1,
    "all_valid": true
  }
}

Plugin Code

Minimal index.js for runproof-capture:

const crypto = require("crypto");
 
const RUNPROOF_URL = "https://runproof-api-production.up.railway.app";
const AGENT_ID = "my-agent";
 
function log(msg) { console.log(`[runproof-capture] ${msg}`); }
function genId(p) { return `${p}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`; }
function hash(d) { 
  return d ? crypto.createHash("sha256")
    .update(typeof d==="string" ? d : JSON.stringify(d))
    .digest("hex").slice(0,16) : "null"; 
}
 
let run = null;
 
async function startRun() {
  if (run) return run;
  const run_id = genId("run");
  const trace_id = genId("trace");
  const res = await fetch(`${RUNPROOF_URL}/v1/run/start`, {
    method: "POST", 
    headers: {"Content-Type":"application/json"},
    body: JSON.stringify({ run_id, trace_id, agent_id: AGENT_ID, runtime: "openclaw" })
  });
  if (res.ok) { run = { run_id, trace_id }; log(`Run: ${run_id}`); }
  return run;
}
 
async function sendEvent(type, data) {
  if (!run) return;
  await fetch(`${RUNPROOF_URL}/v1/run/event`, {
    method: "POST", 
    headers: {"Content-Type":"application/json"},
    body: JSON.stringify({ 
      run_id: run.run_id, trace_id: run.trace_id,
      event_id: genId("evt"), type, 
      timestamp: new Date().toISOString(), 
      source: "runproof-capture", data 
    })
  });
}
 
module.exports = function(api) {
  api.on("before_prompt_build", async () => {
    await startRun();
    await sendEvent("prompt.build", {});
  }, { priority: 100 });
  
  api.on("before_tool_call", async (ev) => {
    await startRun();
    await sendEvent("tool.invoke", { 
      tool: ev.toolName || "unknown", 
      params_hash: hash(ev.params) 
    });
  }, { priority: 100 });
  
  api.on("after_tool_call", async (ev) => {
    await sendEvent("tool.result", { 
      tool: ev.toolName || "unknown", 
      result_hash: hash(ev.result) 
    });
  }, { priority: 100 });
  
  log("Plugin registered");
};

HTTP API Reference

ActionMethodEndpoint
Start runPOST/v1/run/start
Send eventPOST/v1/run/event
Finalize runPOST/v1/run/end
Get proofGET/v1/runproof/{run_id}
VerifyGET/v1/runproof/{run_id}/verify

Verify Response

{
  "run_id": "run-abc123",
  "verified": true,
  "chain_valid": true,
  "signatures": {
    "count": 1,
    "all_valid": true,
    "results": [{
      "signer_id": "runtime:e91fd80c",
      "valid": true
    }]
  },
  "root_hash": "3939767aa50fd226..."
}
FieldMeaning
verifiedOverall verification passed
chain_validEvent hash chain is intact
signatures.all_validAll signatures verified

Proof Profiles

The Native Plugin supports two proof profiles, depending on runtime environment and event fidelity.

execution-proof

Available today.

Designed for embedded/runtime-native execution surfaces where tool/action-level proof is the main requirement.

Captures:

  • Prompt/environment build
  • Tool invocations
  • Tool results
  • Completion/finalization
  • Receipt generation + verification

Current status:

CheckStatus
Golden receipts verified
Stable proof generation
Live NemoClaw revalidation⚠️ Pending plugin reinstall

full-run-proof

Available today on gateway/channel deployments.

Designed for environments where inbound/outbound message envelopes are available.

Captures everything in execution-proof, plus:

  • message_received event
  • message_sent event
  • Richer run boundaries
  • End-to-end conversational verification

Current status:

CheckStatus
Live on gateway/channel path
Verified end to end

Environment Support

Environmentexecution-prooffull-run-proofNotes
Gateway (Telegram/Discord)Full support
Embedded CLI (NemoClaw)No message envelope
Python SDKVariesFramework-dependent

Finalization Behavior

ModeAuto-finalizeManual finalize
Gateway (with streaming)Via session_end/v1/run/end API
Gateway (no streaming)Via message_sent/v1/run/end API
Embedded CLI/v1/run/end API required

Note: Auto-finalization via session:end and message:sent events is being hardened in v1.3.


Known Caveats

Manual finalization in v1

Embedded CLI mode supports execution-proof capture, but finalization is manual until an automatic terminal trigger is stabilized.

# You must call /run/end to finalize
curl -X POST ".../v1/run/end" -d '{"run_id": "...", "success": true}'

Hooks not captured in embedded mode

HookEmbedded CLI
message_received
message_sent

For full message-envelope proof, use gateway/channel mode.


Troubleshooting

Plugin loads but no events in API

  • Check API URL is correct (not localhost)
  • Verify gateway was restarted after plugin update
  • Check required fields: event_id, source, trace_id

Events exist but verify fails

  • Run was not finalized
  • Wrong run_id in verify call

Run doesn’t auto-complete

Expected in v1. Use manual finalization.


Demo Script

A complete demo script is available:

# From the substr8 workspace
./scripts/demo_nemoclaw_native_proof.sh

This script:

  1. Checks NemoClaw accessibility
  2. Runs an agent command
  3. Finds the run in Railway
  4. Finalizes and verifies
  5. Prints the result


What RunProof Proves Today

RunProof proves the integrity of captured execution events by:

  • Hashing event data into a tamper-evident chain
  • Producing a root hash commitment
  • Signing the receipt
  • Allowing independent verification with verify-kit or the /verify endpoint

Today, this means RunProof can prove:

  • That an agent run occurred
  • Which execution events were captured
  • That the event chain has not been tampered with
  • That the receipt verifies independently

RunProof does not yet claim full multi-agent, full state-transition, or full policy/ledger proof. Those are part of the broader protocol roadmap.


Current Note on Finalization

Manual and compact-based finalization are stable today.

Automatic finalization via session:end and message:sent is planned for v1.3, alongside a hook registration/reload fix.


Summary

The native plugin path provides:

  • Zero-code integration — drop into OpenClaw gateway
  • Tool execution proof — captures what the agent did
  • Signed receipts — cryptographic verification
  • Railway API — hosted proof storage

v1.2 Status (March 2026):

  • execution-proof — golden-verified and stable ✅
  • full-run-proof — live on gateway/channel path ✅
  • Live NemoClaw execution-proof — pending plugin reinstall ⚠️
  • Auto-finalization — deferred to v1.3

Next Steps