Integrate an agent in 5 minutes
Argus wraps your agent in an accountability layer: structured traces, on-chain mandate enforcement, cryptographic evidence sealing, and replayable proof packages. This guide shows the full integration path from trace construction to tamper verification.
Build a structured trace
Every agent action must be captured as an ArgusTrace before execution. The trace records the full decision path: what the agent observed, what it remembered, what it inferred, and what it proposed. All fields are deterministic — same inputs produce same hash.
// Monorepo workspace package — not yet on npm
import { canonicalize, traceRoot, tracePayloadForHash } from "@argus/shared";
// Monorepo workspace package — not yet on npm
import { LocalStorageFallbackAdapter } from "@argus/storage-0g";
// Build a structured trace for the agent's proposed action
const trace: ArgusTrace = {
schemaVersion: "argus.trace.v1",
traceId: crypto.randomUUID(),
createdAt: new Date().toISOString(),
chainId: 16661,
mandateId: "mandate-treasury-ops-1",
agentId: "agent-executor-7",
observation: { source: "market-feed", content: "ETH/USDC -4.2% in 1h" },
memory: { promptInjectionDetected: false, relevantMemory: ["rebalance on >3% swing"] },
inference: { summary: "Rebalance threshold exceeded", riskSignals: [] },
proposedAction: {
actionType: "SWAP", target: "0x...", recipient: "0x...",
asset: "0x...", amount: "500000000", // 500 USDC
actionId: "0x..."
},
policyCheck: { verdict: "approved", violationCodes: [], checks: [] },
execution: { status: "approved" },
penalty: { slashed: false, complianceScoreBefore: 800, complianceScoreAfter: 805 },
proof: { canonicalHash: "0x...", storageURI: "", committedTraceRoot: "0x..." }
};Canonicalise, hash, store
Canonical JSON serialisation ensures identical bytes for identical data. The trace root is keccak256(canonicalize(tracePayloadForHash(trace))). The storage URI returned by the adapter is included in the on-chain proposal.
// Canonicalise and hash the trace
const payload = tracePayloadForHash(trace);
const root = traceRoot(payload); // keccak256 of canonical JSON
// Store in 0G Storage (or local fallback)
const storage = new LocalStorageFallbackAdapter("./traces");
const receipt = await storage.putJSON(trace.traceId, trace);
// receipt.uri → "local://traces/agent-executor-7-a1b2c3d4.json"
// receipt.root → "0xabcd..." (matches root computed above)Route through ActionGate
submitAction() evaluates the proposal against all 6 mandate clauses on-chain. If any clause fails, the action is rejected before execution, the bond is slashed, andActionRejected is emitted with a violation bitmap. Use preview() to simulate without writing state.
import { ActionGate__factory } from "./typechain";
const actionGate = ActionGate__factory.connect(ACTION_GATE_ADDRESS, signer);
const proposal = {
mandateId: BigInt(1),
agentId: BigInt(7),
actionId: trace.proposedAction.actionId,
actionType: ethers.encodeBytes32String("SWAP"),
target: trace.proposedAction.target,
recipient: trace.proposedAction.recipient,
asset: trace.proposedAction.asset,
amount: BigInt(trace.proposedAction.amount),
traceRoot: root, // keccak256 of canonical trace
storageURI: receipt.uri
};
const tx = await actionGate.submitAction(proposal);
const receipt = await tx.wait();
// Emits ActionApproved or ActionRejected
// ActionRejected includes: reasonBitmap, slashed (wei)Verify the proof package
After the action is committed on-chain, any party can independently verify the evidence. Fetch the stored trace from the storage URI, recompute the root, and diff against thecommittedTraceRoot on-chain. A root mismatch proves the stored evidence was tampered with after commitment.
// Monorepo workspace package — not yet on npm
import { verifyTrace, buildProofPackage } from "@argus/shared";
// Fetch the stored trace from the storage URI
const storedTrace = await storage.getJSON(receipt.uri);
// Verify: recompute root, diff against committedTraceRoot
const result = verifyTrace(storedTrace, trace.proof.committedTraceRoot);
if (result.status === "valid") {
console.log("Trace root matches committed value — evidence intact");
} else if (result.status === "mismatch") {
// result.diff contains field-level diffs: path, expected, actual
console.error("Tampering detected:", result.diff);
}
// Build exportable proof package for shareable /proof/:root page
const pkg = buildProofPackage({ trace, proof: proofPanelData });Browser verification (no backend required)
The shared package exports browser-safe helpers that use the Web Crypto API. No server, no proxy, no trust requirement. Paste a trace, get a verdict.
// Monorepo workspace package — not yet on npm
// Browser-safe — no Node.js crypto required
import { verifyTraceInBrowser } from "@argus/shared";
const result = await verifyTraceInBrowser(traceJson, committedRoot);Local fallback vs. 0G Storage
The storage adapter interface is stable. Swapping from local fallback to 0G Storage requires only a constructor change. All upstream code — hashing, commitment, verification — is unchanged.
// Monorepo workspace package — not yet on npm
// Swap local fallback for 0G Storage adapter when ready
// No other code changes required
// Current: local filesystem
import { LocalStorageFallbackAdapter } from "@argus/storage-0g";
const storage = new LocalStorageFallbackAdapter("./traces");
// Planned: ZeroGStorageAdapter (adapter interface defined, 0G integration roadmap)
import { ZeroGStorageAdapter } from "@argus/storage-0g";
const storage = new ZeroGStorageAdapter({ rpc: "https://rpc.0g.ai", key: process.env.KEY });